Simpleth

Simpleth (Simplified Ethereum) is a facade of web3.py to simplify use of an Ethereum blockchain and interaction with Solidity contracts.

Classes

  • Blockchain - interact with Ethereum blockchain

  • Contract - interact with Solidity contracts

  • Convert - conversion methods for Ether denominations and time values

  • EventSearch - search for events emitted by transactions

  • Results - details of a mined transaction

Exceptions

  • SimplethError - raised on errors from methods in Blockchain, Convert, Contract, EventSearch or Results.

simpleth.ARTIFACTS_DIR_ENV_VAR: Final[str] = 'SIMPLETH_ARTIFACTS_DIR'

Environment variable name for filepath to artifact directory

simpleth.ARTIFACTS_DIR_DEFAULT: Final[str] = '.'

If environment variable not set, use current working directory

simpleth.ABI_SUFFIX: Final[str] = '.abi'

Filename suffix for the ABI files.

simpleth.BYTECODE_SUFFIX: Final[str] = '.bin'

Filename suffix for the bytecode files.

simpleth.ADDRESS_SUFFIX: Final[str] = '.addr'

Filename suffix for the contract address files.

simpleth.GAS_LIMIT: Final[int] = 6000000

Gas limit for a transaction, in units of gas.

simpleth.MAX_BASE_FEE_GWEI: Final[Union[int, float]] = 100

Maximum tip to pay the miners, per unit of gas, in gwei.

simpleth.MAX_PRIORITY_FEE_GWEI: Final[Union[int, float]] = 2

Maximum tip to pay the miners, per unit of gas, in gwei.

simpleth.MAX_FEE_GWEI: Final[Union[int, float]] = 102

Maximum total to pay the miners, per unit of gas, in gwei.

simpleth.TIMEOUT: Final[Union[int, float]] = 120

Time to wait for transaction to be mined, in seconds.

simpleth.POLL_LATENCY: Final[Union[int, float]] = 0.1

Time between checking if mining is finished, in seconds.

simpleth.GANACHE_URL_ENV_VAR: Final[str] = 'SIMPLETH_GANACHE_URL'

Environment variable name for URL to connect to local Ganache blockchain

simpleth.GANACHE_URL_DEFAULT: Final[str] = 'http://127.0.0.1:7545'

If environment variable not set, use Ganache default URL

simpleth.TIME_FORMAT: Final[str] = '%Y-%m-%d %H:%M:%S'

Default datetime format coding used to represent time values as a string

simpleth.PRECISION: Final[int] = 40

Level of precision for Decimal values used in Ether denomination conversions. Arbitrary value. Consider a better value.

simpleth.T_ABI = typing.Any

ABI type is a list with JSON read from the artifact file.

simpleth.T_ATTRIBUTE_DICT = typing.Any

AttributeDict type is not known to type hint. Use Any for now.

simpleth.T_BLOCKCHAIN_OBJ = typing.Any

Blockchain object type is simpleth.Blockchain. Use Any for now. Created by simpleth methods. See T_result about those single quotes.

simpleth.T_BYTECODE = typing.Any

bytecode type is HexBytes read from the artifact file. Use Any for now.

simpleth.T_CONTRACT_EVENT = typing.Any

contract_event` type is web3._utils.datatypes.<event_name>'. Use Any for now.

simpleth.T_DECIMAL = typing.Any

Decimal type. Use Any for now.

simpleth.T_DEPLOYED_CODE = typing.Any

Deployed code type is class HexBytes. Use Any for now. Created by web3.py method.

simpleth.T_EXC_INFO = typing.Any

Transaction exception info type is a tuple returned by sys.exc_info() after an exception. Use Any for now.

simpleth.T_ETH_OBJ = typing.Any

Eth object type is web3.eth.Eth. Use Any for now. Created by web3.py methods.

simpleth.T_EVENT = typing.Any

Event type is an AttributeDict. Use Any for now.

simpleth.T_EVENT_LOG_OBJ = typing.Any

Event log type is a list of T_EVENT items.

simpleth.T_FILTER_OBJ = typing.Any

EventSearch object type is web3._utils.filters.LogFilter. Use Any for now. Created by web3.py methods.

simpleth.T_FILTER_LIST = typing.Any

EventSearch list type is created by web3.py event_filter. Use Any for now.

simpleth.T_HASH = typing.Any

Transaction hash type is HexBytes in web3.py. Use Any for now.

simpleth.T_HEX_BYTE = typing.Any

HexByte type is not known to type hint. Use Any for now.

simpleth.T_RECEIPT = typing.Any

Transaction receipt type is AttributeDict. Use Any for now. Created by web3.py methods.

simpleth.T_RESULT = typing.Any

Transaction result is a class object with the various outcomes from mining a transaction. Created by the simpleth class, Results. Use Any for now.

simpleth.T_TRANSACTION = typing.Any

Transaction type is class web3.datastructures.AttributeDict. Use Any for now. Created by web3.py getTransaction().

simpleth.T_WEB3_OBJ = typing.Any

Web3 object type is web3.main.Web3 object. Use Any for now. Created by web3.py methods.

simpleth.T_WEB3_ETH_OBJ = typing.Any

Web3 object type is web3.eth.Eth object. Use Any for now.

simpleth.T_WEB3_CONTRACT_OBJ = typing.Any

Web3 contract object type is web3._utils.datatypes.Contract object. Use Any for now.

simpleth.T_WEB3_EXC = typing.Any

Web3 Exception type is module web3.exceptions. Use Any for now. Provided by web3.py

simpleth.CONTRACT_LOGIC_ERROR_REVERT_MESSAGE: Final[str] = 'execution reverted: VM Exception while processing transaction: revert'

ContractLogicError exception message for a reverted transaction.

simpleth.VALUE_ERROR_REVERT_TEXT: Final[str] = 'VM Exception while processing transaction: revert'

ValueError exception message for a reverted transaction.

class simpleth.Blockchain(url: Optional[str] = None)

Interact with an Ethereum blockchain.

Sets up the web3 object which establishes the connection to an Ethereum blockchain and supports access to various values and functions related to the blockchain.

PROPERTIES

METHODS

GANACHE URL

The constructor for Blockchain connects to Ganache via a URL. There are three ways to specify that URL, in order of precedence:

  1. Use the optional parameter, url, for the Blockchain constructor. This only remains in effect for this instance of your Blockchain object.

  2. Create an environment variable, SIMPLETH_GANACHE_URL, and specify the URL as the value. This remains in effect for all subsequent Blockchain objects - as long as the variable is set.

  3. Do nothing. The default value for the URL is GANACHE_URL_DEFAULT. This is always in effect unless you do one of the above and should work for most situations.

Warning

This has only been tested with Ganache

__init__(url: Optional[str] = None) None

Create blockchain instance.

Parameters

url (str) – Ethereum blockchain web address (optional, default: None)

Return type

None

Raises

SimplethError

  • if unable to connect to the blockchain client (B-010-010)

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
property accounts: list

Return list of accounts provided by Ganache.

Return type

list

Returns

list of blockchain addresses

Example
>>> from simpleth import Blockchain
>>> Blockchain().accounts    
['0x235A686386d03a5Bb986Fb13E71A0dC86846c636',   ...snip... ]

Note

Since this is a list a negative index such as, accounts[-1], works and will return the last item.

property api_version: str

Return the installed web3 API version.

Return type

str

Returns

API version number

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> b.api_version   
'5.24.0'
property block_number: int

Return the number of the last block added to the chain.

Return type

int

Returns

sequence number of the block at the end of the chain

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> b.block_number   
2284
property client_version: str

Return the blockchain client version.

Return type

str

Returns

blockchain client version

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> b.client_version    
'EthereumJS TestRPC/v2.13.1/ethereum-js'
property eth: Any

Return the web3.eth object.

Return type

object

Returns

web3.eth object

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> b.eth   
<web3.eth.Eth object at 0x0000019CEBAC8760>
>>> b.eth.gas_price
20000000000

Note

This can be used to access any of the web3.eth methods not provided by simpleth.

property url: str

Return the Ganache URL.

Return type

str

Returns

URL for Ganache

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> b.url
'http://127.0.0.1:7545'
property web3: Any

Return the web3 object.

Return type

object

Returns

web3 object

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> b.web3   
<web3.main.Web3 object at 0x0000019CE7AF3520>
>>> b.web3.toWei(1, 'ether')
1000000000000000000

Note

This can be used to access any of the web3.eth methods not provided by simpleth.

account_num(account_address: str) Optional[int]

Return account number for the specified address.

Parameters

account_address (str) – address to convert to account number

Return type

int | None

Returns

  • index of the account in the list Ganache-provided accounts

  • None if account_address not one provided by Ganache

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> user = b.accounts[6]
>>> b.account_num(user)
6

See also

accounts() for the list of all account addresses.

address(account_num: int) str

Return the blockchain address of the specified account number.

Parameters

account_num (int) – index into the account list

Return type

str

Returns

blockchain address of the requested account

Raises

SimplethError

  • if account_num is out of range (B-020-010)

Example
>>> from simpleth import Blockchain
>>> b=Blockchain()
>>> b.address(2)    
'0x02F6903D426Be890BA4F882eD19cF6780ecdfA5b'
balance_of(address: str) int

Return the amount of Ether owned by an account.

Parameters

address (str) – blockchain address of the account

Return type

int

Returns

account’s ether balance, in wei

Raises

SimplethError

  • if address is not a string (B-030-010)

  • if address is not a valid account (B-030-020)

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> user0 = b.address(0)
>>> b.balance_of(user0)    
99977013240000000000

Note

The method name, balance_of() was chosen to match the name used in the ERC-20 standard for tokens. You use balance_of with a Blockchain() object to get the Ether balance of an address and use the same method name with a token object to the token balance for an address.

block_time_epoch(block_number: int) int

Return the time, as epoch seconds, when a block was mined.

Parameters

block_number (int) – number of the block on the chain

Return type

int

Returns

time block was mined, in epoch seconds.

Raises

SimplethError

  • if block_number is invalid (B-040-010)

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> b.block_time_epoch(20)    
1638120893
block_time_string(block_number: int, time_format: str = '%Y-%m-%d %H:%M:%S') str

Return the time, as a string, when a block was mined.

Parameters
  • block_number (int) – number of the block on the chain

  • time_format (str) – format codes used to create time string (optional, default: TIME_FORMAT)

Return type

str

Returns

time block was mined, in local timezone, as a string

Raises

SimplethError

  • if block_number is invalid (B-050-010)

  • if time_format is not a string (B-050-020)

Example
>>> from simpleth import Blockchain
>>> Blockchain().block_time_string(20)   
'2021-11-28 11:34:53'
>>> Blockchain().block_time_string(20, '%A %I:%M %p')   
'Sunday 11:34 AM'

Note

Does not check for valid time format code string.

See also

Python page on time format codes

fee_history(num_blocks: int = 3) dict

Return fee information for recently mined blocks.

This could be used to determine a reasonable max_fee_gwei and max_priority_fee_gwei to offer when submitting a new transaction.

Parameters

num_blocks (int) – information for the last num_blocks will be returned (optional, default: 3)

Return type

dict

Returns

dictionary with:

  • ’reward’: a list with the low and high reward amounts offered for transactions in this block: low is the 10th percentile; high is the 90th percentile

  • ’baseFeePerGas’: base fee set by the network for this block

  • ’gasUsedRatio’: gasUsed/gasLimit for this block

  • ’oldestBlock’: block number for the oldest block in the list and will be block_number - num_blocks

Raises

SimplethError

  • if the method is called (B-060-010)

Warning

This does not work. The w3.eth.fee_history() method is specified in the web3.py documentation but does not seem to be supported by Ganache yet. Currently, it throws a ValueError exception.

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> b.fee_history()   
...
HINT: method not yet implemented in Ganache.

Note

This method is being included in simpleth in hopes it is soon implemented by Ganache. The method has value for simpleth. It is coded and ready to test and use.

is_valid_address(address: str) bool

Test for valid blockchain address

Parameters

address – blockchain address to verify

Return type

bool

Returns

  • True if valid

  • False otherwise

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> user0 = b.address(0)
>>> b.is_valid_address(user0)
True
>>> bogus = '0x380A36BE82A06A63395D'
>>> b.is_valid_address(bogus)
False
send_ether(sender: str, receiver: str, amount_wei: int) Any

Transfer Ether from one account to another.

amount is deducted from sender and added to receiver.

Parameters
  • sender (str) – address of the account that sends the Ether

  • receiver (str) – address of the account that receives the Ether

  • amount_wei (int) – amount of Ether transferred; denominated in wei

Return type

str

Returns

trx_hash of the transfer transaction

Raises

SimplethError

  • if sender is bad (B-070-010)

  • if receiver is bad (B-070-010)

  • if amount exceeds the sender balance_of (B-070-010)

  • if receiver is a non-payable contract (B-070-010)

  • if amount is not an int (B-070-020)

  • if receiver is a non-payable contract (B-070-030)

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> user4 = b.address(4)
>>> user8 = b.address(8)
>>> b.send_ether(user4, user8, 1000)    

See also

  • balance_of() to get amount of Ether owned by an account.

  • transaction() to get details of the transfer transaction using the trx_hash.

transaction(trx_hash: str) Any

Return details about the transaction.

Parameters

trx_hash (str) – transaction hash to identify the transaction of interest

Return type

dict

Returns

transaction details as a dictionary

Raises

SimplethError

  • if transaction for trx_hash is not found (B-080-010)

  • if trx_hash is not a valid type (B-080-020)

Example
>>> from simpleth import Blockchain
>>> t = '0xe6bbbc34f53ef4137de80dc63f156b820d71f9f176b8210a42 ...'
>>> Blockchain().transaction(t)   
{'hash': HexBytes('0xe6bbbc34f53ef4137de80dc63f156b820d71 )...}'

See also

  • run_trx() and send_trx() return a trx_hash .

  • Results can be used to get more details.

trx_count(address: str) int

Return the number of transactions sent by an address.

Parameters

address (str) – blockchain address of account to check

Return type

int

Returns

total number of transactions on the blockchain

Raises

SimplethError

  • if address is not a string (B-090-010)

  • if address is not a valid account (B-090-020)

Example
>>> from simpleth import Blockchain
>>> b = Blockchain()
>>> user0 = b.address(0)
>>> b.trx_count(user0)   
48
trx_sender(trx_hash: str) str

Return the account address that sent this transaction.

Parameters

trx_hash (str) – transaction hash of the transaction

Return type

str

Returns

address that sent the transaction

Example
>>> from simpleth import Blockchain, Contract
>>> user = Blockchain().accounts[3]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> r = c.run_trx(user,'storeNums',1,2,3)
>>> thash = r['transactionHash']
>>> Blockchain().trx_sender(thash)    
'0xfEeB074976F8a2B53d2F8c737BD94cd16ad599F0'
class simpleth.Contract(name: str)

Use to interact with Solidity contracts.

Use this class to:

  • deploy a contract onto the blockchain

  • connect to a previously deployed contract

  • submit transactions to be run

  • get results of a transaction

  • call functions

  • get public state variable values

PROPERTIES

METHODS

ARTIFACT DIRECTORY

Contract expects to find the outputs from compiling a contract in the artifact_dir(). The required files:

  • <contract>.abi - ABI for the compiled contract. Created by solc.exe.

  • <contract>.addr - blockchain address of deployed contract. Created by deploy() at first-ever deployment of contract and updated on subsequent deploy().

  • <contract>.bin - Binary for the compiled contract. Created by solc.exe.

The environment variable, SIMPLETH_ARTIFACTS_DIR, should be set with the filepath to the directory holding these files.

If the environment variable is not found, the default directory is, ., the current working directory.

__init__(name: str) None

Create instance for the named contract.

Parameters

name (str) – contract name

Return type

None

Raises

SimplethError

  • if name is misspelled or has not been compiled.

Example
>>> from simpleth import Contract
>>> Contract('Test')   
<simpleth.Contract object at 0x0000028A7262B580>

Note

Case does not matter for name. If the Solidity file is Example.sol, either Contract('Example') or Contract('example') will work.

property abi: List

Return the contract ABI (Application Binary Interface).

Return type

list

Returns

list with signature of all contract functions

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> c.abi    
[{'inputs': [{'internalType': 'int256', 'name':  ...snip... } ]
property address: str

Return blockchain address of the deployed contract.

Return type

str

Returns

blockchain address of the contract

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.address    
'0x0F802Cf8C7929C5E0CC140314d1501e21b18a6A8'

Note

Returns empty string if no connect() was done.

property artifact_dir: str

Return path to artifact directory for the contract.

Return type

str

Returns

path to artifact directory

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.artifact_dir     
'C:\path\to\your\artifact\directory'
property blockchain: Any

Return web3.py blockchain object.

This can be used to access Blockchain methods and attributes

Return type

object

Returns

Blockchain object

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.blockchain    
<simpleth.Blockchain object at 0x000001E867C698A0>
property bytecode: str

Return contract bytecode.

Return type

str

Returns

bytecode of contract

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.bytecode    
'6080604052602a60015534801561001557600080  ...snip...

Note

Contract bytecode is not the same as the contract deployed_code. The bytecode is larger and includes the instructions to deploy the contract.

property deployed_code: Any

Return contract bytecode as deployed on blockchain.

Return type

str

Returns

contract code as deployed on chain.

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.deployed_code    
'0x608060405234801561001057600080fd5b50600436106100ea576

Note

deployed_code contains the bytes that are on the blockchain. This is the same as the bytecode without its additional code to deploy.

TBD

Play with this a bit. After doing a lot of hand-testing to create examples and debug, I had Test already deployed that would run storeNums() but showed deployed_code == ‘x0’. Did a fresh deploy() and all worked.

property event_names: List[str]

Return the event names defined in the contract.

Return type

list

Returns

names of the events defined in the contract

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.event_names    
['NumsStored', 'TestConstructed', 'TypesStored']
property functions: List[str]

Return the functions in the contract.

Return type

list

Returns

signatures of all functions.

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.functions    
['getContractSize(address)', 'getNum(uint8)',  ...snip... ]

Note

The list of functions includes all transactions, all public functions, and all getters for public state variables.

property name: str

Return the name of the contract.

Return type

str

Returns

contract name

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> c.name
'Test'
property size: int

Return deployed contract size.

Return type

int

Returns

size of the contract, in bytes

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.size    
4218

Note

This is the number of bytes required to store the contract on the blockchain. It is the same as len(c.deployed_code).

property web3_contract: Any

Return web3.py contract object.

This can be used to access methods provided by web3. It is typically not needed for basic use of simpleth.

Return type

object

Returns

web3._utils.datatypes.Contract object

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.web3_contract    
<web3._utils.datatypes.Contract object at 0x000001E867CFABF0>
property web3e: Any

Return module to process web3 exceptions.

This is used by simpleth internals to handle web3 exceptions. It is typically not needed for basic use of simpleth.

Return type

module

Returns

web3 exception module

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.web3_contract    
<module 'web3.exceptions' ... >
call_fcn(fcn_name: str, *fcn_args: Optional[Union[int, str, float, list, bool]]) Union[int, str, list, float, bool]

Return results from calling a contract function.

Contract functions are those that do not alter state variables. They are defined in the Solidity code as public view or public pure.

Parameters
  • fcn_name (str) – name of a function in the Solidity contract

  • fcn_args (int | float | str | None) – argument(s) required by the function (optional, default: None)

Raises

SimplethError

  • if fcn_name is bad or a connect() is needed (C-010-010)

  • if fcn_args are the wrong type or number (C-010-020)

  • if contract has done a selfdestruct() or needs a fresh deploy() (C-010-030)

  • if fcn_args had out of bounds array index (C-010-040)

Return type

int | float | string | list

Returns

value returned from the Solidity function

Example
>>> from simpleth import Blockchain, Contract
>>> c = Contract('test')
>>> u = Blockchain().address(0)
>>> # r keeps doctest from dealing with returned contract address
>>> r = c.deploy(u, 42)
>>> c.call_fcn('getNum', 2)
2
>>> c.call_fcn('getNums')
[0, 1, 2]

Note

fcn_name must match the spelling and capitalization of the function as specified in the Solidity contract.

connect(address: Optional[str] = None) str

Enable the use of a deployed contract.

After instantiating a deployed Contract object you must do a connect() to make it possible to use the methods for the contract. It is akin to doing a file open() to use a file.

Parameters

address (str) – address of the contract (optional, default: None)

Return type

str

Returns

address of the contract

Raises

SimplethError

  • if address arg was invalid (C-150-010)

Example
>>> from simpleth import Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> c.name
'Test'

Note

  • Use deploy() to install a contract onto the blockchain. Thereafter, use connect() to use that contract.

  • You may have multiple instances of the contract on the blockchain. connect() will use the most recently deployed version.

  • connect(address)() is intended only for use when a contract uses the Solidity operator, new to deploy the contract. The contract’s new address is not in the .addr file for connect() to find. So, that new address is supplied directly to connect().

deploy(sender: str, *constructor_args: Union[int, float, str, list, bool], gas_limit: int = 6000000, max_priority_fee_gwei: Union[float, int] = 2, max_fee_gwei: Union[float, int] = 102) Any

Deploy the contract onto the blockchain.

This installs the contract onto the blockchain and makes it ready for immediate use. You only need to deploy the contract once. Subsequent sessions only require a connect() to use the deployed contract.

Parameters
  • sender (str) – address of account requesting deploy()

  • constructor_args (int | float | string | list | None) – argument(s) for the contract constructor (optional, default: None)

  • gas_limit (int) – maximum amount of gas units allowed for deploy (optional, default: GAS_LIMIT)

  • max_priority_fee_gwei (int) – maximum sender will pay from account balance as a tip for a miner to mine this transaction, in gwei (optional, default: MAX_PRIORITY_FEE_GWEI)

  • max_fee_gwei (int) – maximum sender will pay to have this transaction mined, in gwei (optional, default: MAX_FEE_GWEI)

Return type

T_RECEIPT

Returns

transaction receipt

Raises

SimplethError

  • if unable to get artifact info and create contract class (C-030-010)

  • if sender address is bad (C-030-020)

  • if constructor_args are wrong type or number (C-030-030)

  • if deploy() ran out of gas (C-030-040)

  • if gas_limit exceeded the block limit (C-030-040)

  • if sender address is a contract (C-030-040)

Example
>>> from simpleth import Contract, Blockchain
>>> c = Contract('Test')
>>> user = Blockchain().accounts[0]
>>> r = c.deploy(user,42)
get_gas_estimate(sender: str, trx_name: str, *args: Optional[Union[int, str, float, list, bool]]) int

Return the units of gas needed to run a transaction.

Does not run the transaction. It estimates the gas that will be required to run the transaction with the given args.

Parameters
  • sender (str) – account address sending the transaction for estimating

  • trx_name (str) – name of the transaction

  • args (Any) – transaction arguments (optional, default: None)

Return type

int

Returns

estimated number of gas units to run the transaction

Raises

SimplethError

  • if trx_name is bad (C-040-010)

  • if args are bad; either wrong type or number (C-040-020)

  • if contract has not yet been deployed on a new chain (C-040-030)

  • if args has an out-of-bounds index value (C-040-040)

  • if sender is bad (C-040-050)

  • if connect() is needed (C-040-060)

  • if sender or one or more args is missing (C-040-070)

Example
>>> from simpleth import Contract
>>> from simpleth import Blockchain
>>> c = Contract('Test')
>>> addr = c.connect()
>>> b = Blockchain()
>>> user = b.accounts[0]
>>> c.get_gas_estimate(user, 'storeNums', 1, 2, 3)   
38421
get_trx_receipt(trx_hash: Any) Any

Return the receipt after a transaction has been mined.

This is used after submit_trx() to get the mining receipt. Returns None if the transaction has not yet been mined.

Does not check for a valid trx_hash. Returns None for a bad trx_hash.

Parameters

trx_hash (str) – transaction hash from submit_trx()

Return type

T_RECEIPT

Returns

web3 transaction receipt

Example
>>> from simpleth import Contract, Blockchain
>>> c = Contract('Test')
>>> addr = c.connect()
>>> b = Blockchain()
>>> user = b.accounts[0]
>>> t_hash = c.submit_trx(user, 'storeNums', 7, 8, 9)
>>> c.get_trx_receipt(t_hash)    
{'address': None, 'gas_used': 83421,  ...snip... }

See also

get_trx_receipt_wait(trx_hash: Any, timeout: Union[int, float] = 120, poll_latency: Union[int, float] = 0.1) Any

Wait for transaction to be mined and then return the receipt for that transaction.

This is used after submit_trx() to get the results of the transaction. Will block the caller and wait until either the transaction is mined or timeout is reached. The return will be None if it times out.

Setting timeout and poll_latency gives the caller flexiblity in the frequency of checking for the transaction completion and the length of time to keep checking before timing out.

Does not check for a valid trx_hash. Returns None for a bad trx_hash.

Parameters
  • trx_hash (str) – transaction hash

  • timeout (int | float) – maximum number of seconds to wait for mining to finish (optional, default: TIMEOUT)

  • poll_latency (int | float) – number of seconds between checking for transaction completion (optional, default: POLL_LATENCY)

Return type

T_RECEIPT

Returns

transaction receipt

Raises

SimplethError

  • if timeout is not float or int (C-050-010)

  • if poll_latency is not float or int (C-050-020)

Example
>>> from simpleth import Blockchain, Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> b = Blockchain()
>>> user = b.accounts[0]
>>> t_hash = c.submit_trx(user, 'storeNums', 7, 8, 9)
>>> r = c.get_trx_receipt_wait(t_hash)
>>> print(r)    
Address        = None
    ...

Note

See also

get_var(var_name: str, *args: Any) Optional[Union[int, str, float, list, bool]]

Return the value of a contract variable.

The variable must be declared as public in the Solidity contract.

Parameters
  • var_name (str) – name of the contract variable

  • args (int) – args for the variable, typically an index value into an array (optional, default: None)

Return type

int | string | float | list | None

Returns

value of the variable

Raises

SimplethError

  • if var_name is bad (C-060-010)

  • if contract has done a selfdestruct() or not yet deployed on a new chain (C-060-020)

  • if var_name is an array but args did not specify an index value (C-060-030)

  • if var_name is not an array yet args specifies an index value (C-060-030)

  • if args specifies an out of bound index value (C-060-040)

  • if a connect() is needed (C-060-050)

Example
>>> from simpleth import Blockchain, Contract
>>> u = Blockchain().address(0)
>>> c = Contract('test')
>>> r = c.deploy(u, 42)
>>> c.get_var('initNum')
42

Note

Uses the built-in Solidity public getter.

run_trx(sender: str, trx_name: str, *args: Any, gas_limit: int = 6000000, max_priority_fee_gwei: Union[int, float] = 2, max_fee_gwei: Union[int, float] = 102, value_wei: int = 0, timeout: Union[int, float] = 120, poll_latency: Union[int, float] = 0.1) Any

Submit a transaction to be mined and return the receipt.

This is the method typically used for running transactions.

run_trx() is a combination of submit_trx() and get_trx_receipt_wait(). The caller uses a single method to submit a transaction to the blockchain and get back the results of the transaction after it is mined.

The caller is blocked until run_trx() returns or times out.

Returns None if it times out waiting for the mining to be completed. Try running again with higher value for timeout. Or, consider using submit_trx() along with either get_trx_receipt() or get_trx_receipt_wait() to give you more flexibility and control.

Parameters
  • sender (str) – address of account sending the transaction

  • trx_name (str) – name of transaction

  • args (int | float | string | list) – argument(s) required by the transaction (optional, default: None)

  • gas_limit (int) – max gas sender will allow for this transaction, in units of gas (optional, default: GAS_LIMIT)

  • max_priority_fee_gwei (int | float) – max amount of Ether, in gwei, the sender will pay as a tip (optional, default: MAX_PRIORITY_FEE_GWEI)

  • max_fee_gwei (int | float) – max amount of Ether, in gwei, the sender will pay for the transaction (optional, default: MAX_FEE_GWEI)

  • value_wei (int) – amount of Ether, in wei, to be sent with the transaction (optional, default: 0)

  • timeout (int | float) – maximum number of seconds to wait for mining to finish (optional, default: TIMEOUT)

  • poll_latency (int | float) – number of seconds between checking for transaction completion (optional, default: POLL_LATENCY)

Return type

T_RECEIPT

Returns

web3 transaction receipt

Raises

SimplethError

  • if unable to submit the transaction; no hash was returned (C-070-010)

  • submit_trx() and get_receipt_wait() will raise exceptions due to errors in arguments or contract logic.

Example
>>> from simpleth import Blockchain, Contract
>>> c = Contract('Test')
>>> addr = c.connect()
>>> b = Blockchain()
>>> user = b.accounts[0]
>>> results = c.run_trx(user,'storeNums',2,4,6)
>>> print(results)    
Address        = None
     ...

See also

Description section for submit_trx() for an explanation about fees.

submit_trx(sender: str, trx_name: str, *args: Any, gas_limit: int = 6000000, max_priority_fee_gwei: Union[int, float] = 2, max_fee_gwei: Union[int, float] = 102, value_wei: int = 0) Any

Send a contract transaction to be mined.

This is used to request a contract carry out a transaction.

This method returns immediately. It does not check to see if transaction was mined nor if it was successful. You can follow up with either get_trx_results() or get_trx_results_wait() to check for the completion of the transaction.

About the fees:

  • max_fee_gwei = Base Fee + max_priority_fee

  • The Base Fee is set by the network and is adjusted after each block based on transaction volume. Paying the Base Fee is mandatory. Base Fee is in gwei and is paid for each unit of gas used by the transaction.

  • The Priority Fee is the tip you can offer to the miners to attract their attention to your transaction, denominated in gwei, and paid for every unit of gas used by the transaction. It is also call a ‘tip’. Paying the Priority Fee is optional but might be a near necessity if the network is busy with a high transaction volume. In that case, miners will be processing transactions with tips and ignoring low- or no-tip transactions.

  • max_fee_gwei is the maximum you will spend and max_priority_fee is the most you will offer a miner. If the Base Fee being charged by the network is higher than expected, your Priority Fee may be cut.

  • A blog post on fees has a more thorough explanation plus a recommended Max Fee to use:

    Double the current Base Fee and add the most you would like to tip, i.e.:
    
    max_fee_gwei = (2 * current Base Fee) + max_priority_fee_gwei
    
Parameters
  • sender (str) – address of account sending the transaction

  • trx_name (str) – name of transaction

  • args (int | float | str | None) – argument(s) required by the transaction (optional, default: None)

  • gas_limit (int) – maximum gas sender will allow for this transaction, in units of gas (optional, default is GAS_LIMIT)

  • max_priority_fee_gwei (int | float) – maximum amount of Ether, in gwei, the sender will pay as a tip (optional, default: MAX_PRIORITY_FEE_GWEI)

  • max_fee_gwei (int | float) – max amount of Ether, in gwei, the sender will pay for the transaction (optional, default: MAX_FEE_GWEI)

  • value_wei (int) – amount of Ether, in wei, to be sent with the transaction (optional, default: 0)

Return type

str

Returns

trx_hash the transaction hash that identifies this transaction on the blockchain

Raises

SimplethError

  • if trx_name is not in the contract (C-080-010)

  • if args are missing, wrong number of args, or wrong type (C-080-020)

  • if contract has not yet been deployed on a new chain (C-080-030)

  • if sender is a bad address (C-080-040)

  • if max_priority_fee_gwei is greater than max_fee_gwei (C-080-050)

  • if connect() is needed (C-080-060)

  • if sender or trx_name are missing (C-080-070)

  • if transaction was reverted when it ran in the VM (C-080-080) due to:

    • trx_name modifier() failed

    • trx_name require() failed

    • trx_name assert() failed

    • trx_name issued a revert()

    • args caused a divide-by-zero in the transaction

    • args caused an out-of-bounds array index

    • gas_limit was lower than the base fee

    • gas_limit was higher than the block gas limit

    • max_fee_gwei was a float

    • max_priority_fee_gwei was a float

    • trx_name called another trx, and that called trx failed

    • value_wei was specified but trx_name is not payable

    • sender is not valid for sending a trx

Example
>>> from simpleth import Blockchain, Contract
>>> c = Contract('Test')
>>> b = Blockchain()
>>> addr = c.connect()
>>> user = b.accounts[0]
>>> c.submit_trx(user, 'storeNums', 4, 5, 6)    
HexBytes('0x6fc9deaf6052504a8  ..snip.. 50af2cb320278b476')

Note

  • These are Type 2 transactions which conform to EIP-1559 (aka London Fork). They use the new max fee and max priority fee fields instead of a gas price field.

  • trx_hash is the transaction hash that can be used to check for the transaction outcome in get_trx_receipt() or get_trx_receipt_wait()

  • trx_name must match the spelling and capitalization of a function in the Solidity contract.

  • value is Ether that is sent to the transaction. It is a payment from the sender to the contract. The transaction should be defined as a payable function in the Solidity contract or the contract will need a payable fallback function in order to accept the payment.

See also

class simpleth.Convert

Conversion methods for Ether denominations and time values

METHODS

convert_ether(amount: Union[int, float], from_denomination: str, to_denomination: str) Any

Convert the amount from one Ether denomination to another.

Parameters
  • amount (int | float) – amount to be converted

  • from_denomination (str) – unit of denomination of amount

  • to_denomination (str) – unit of denomination of result

Return type

Decimal

Returns

converted amount

Raises

SimplethError

  • if from_denomination is bad (V-010-010)

  • if to_denomination is bad (V-010-020)

Example
>>> from simpleth import Convert
>>> c = Convert()
>>> c.convert_ether(100, 'wei', 'ether')
Decimal('1.00E-16')
>>> c.convert_ether(100, 'ether', 'wei')
Decimal('100000000000000000000')
>>> int(c.convert_ether(25, 'ether', 'gwei'))
25000000000

Note

web3.py has two conversion methods: to_wei() and from_wei(). This function is more flexible and does not require a Blockchain object to use.

See also

denominations_to_wei() for valid strings to use for from_denomination and to_denomination.

static denominations_to_wei() Dict[str, int]

Return denominations and their value in units of wei.

Return type

dict

Returns

  • key is the name of an Ether denomination

  • value is the amount in wei for one of that denomination

Example
>>> from simpleth import Convert
>>> c = Convert()
>>> c.convert_ether(100, 'wei', 'ether')
Decimal('1.00E-16')
>>> c.convert_ether(100, 'ether', 'wei')
Decimal('100000000000000000000')
>>> int(c.convert_ether(25, 'ether', 'gwei'))
25000000000
>>> c.denominations_to_wei()['finney']
1000000000000000
>>> import math
>>> for key, value in c.denominations_to_wei().items():
...     print(f'{key:10} = 10**{int(math.log10(value)):<2} = {value:<41,} wei')
...
wei        = 10**0  = 1                                         wei
kwei       = 10**3  = 1,000                                     wei
babbage    = 10**3  = 1,000                                     wei
femtoether = 10**3  = 1,000                                     wei
mwei       = 10**6  = 1,000,000                                 wei
lovelace   = 10**6  = 1,000,000                                 wei
picoether  = 10**6  = 1,000,000                                 wei
gwei       = 10**9  = 1,000,000,000                             wei
shannon    = 10**9  = 1,000,000,000                             wei
nanoether  = 10**9  = 1,000,000,000                             wei
nano       = 10**9  = 1,000,000,000                             wei
szabo      = 10**12 = 1,000,000,000,000                         wei
microether = 10**12 = 1,000,000,000,000                         wei
micro      = 10**12 = 1,000,000,000,000                         wei
finney     = 10**15 = 1,000,000,000,000,000                     wei
milliether = 10**15 = 1,000,000,000,000,000                     wei
milli      = 10**15 = 1,000,000,000,000,000                     wei
ether      = 10**18 = 1,000,000,000,000,000,000                 wei
kether     = 10**21 = 1,000,000,000,000,000,000,000             wei
grand      = 10**21 = 1,000,000,000,000,000,000,000             wei
mether     = 10**24 = 1,000,000,000,000,000,000,000,000         wei
gether     = 10**27 = 1,000,000,000,000,000,000,000,000,000     wei
tether     = 10**30 = 1,000,000,000,000,000,000,000,000,000,000 wei

Note

These are the denominations recognized by convert_ether().

See also

web3.py page on Converting currency denominations

static epoch_time() float

Return current time in epoch seconds.

Return type

float

Returns

current time, in epoch seconds

Example
>>> from simpleth import Convert
>>> Convert().epoch_time()    
1638825195.6231368
static local_time_string(t_format: str = '%Y-%m-%d %H:%M:%S') str

Return current local time as a time string.

Parameters
  • t_format – format of outputted time using strftime codes (optional, default: TIME_FORMAT)

  • t_format – str

Return type

str

Returns

current time

Raises

SimplethError

  • if t_format is bad (V-020-010)

Example
>>> from simpleth import Convert
>>> c = Convert()
>>> c.local_time_string()    
'2021-12-06 15:35:28'
>>> c.local_time_string('%A %I:%M:%S %p')    
'Monday 03:36:48 PM'

See also

Python page on time format codes

static to_local_time_string(epoch_sec: Union[int, float], t_format: str = '%Y-%m-%d %H:%M:%S') str

Convert epoch seconds into local time string.

Parameters
  • epoch_sec (int | float) – epoch time, in seconds

  • t_format – format of outputted time using strftime codes (optional, default: TIME_FORMAT)

  • t_format – str

Return type

str

Returns

local time equivalent to epoch seconds

Raises

SimplethError

  • if t_format is bad (V-030-010)

Example
>>> from simpleth import Convert
>>> c = Convert()
>>> epoch = c.epoch_time()
>>> epoch    
1638825248.9298458
>>> c.to_local_time_string(epoch)    
'2021-12-06 15:14:08'
>>> c.to_local_time_string(epoch, '%A %I:%M:%S %p')   
'Monday 03:14:08 PM'

See also

Python page on time format codes

class simpleth.EventSearch(contract: Contract, event_name: str, event_args: Optional[dict] = None)

Search for an event emitted a by contract.

Returns the event info for each occurrence of an event within a set of blocks. The search can be narrowed by also specifying one, or more, pairs of event args along with desired values.

PROPERTIES

METHODS

  • get_new() - return event info from newly mined blocks; looks forward.

  • get_old() - return event info from specified range of previously mined blocks; looks backward.

See also

web3.py API documentation for more powerful filters. Blockchain.eth can be used to access the methods described.

__init__(contract: Contract, event_name: str, event_args: Optional[dict] = None) None

Create instance to search for the event emitted by the contract.

Parameters
  • contract (object) – Contract object

  • event_name (str) – name of event defined in the contract

  • event_args (dict | None) – event arg(s) and value(s) to search for. Specified as a dictionary with each item having an event arg name as a string for the key and the value to search for being the dictionary value. Multiple entries are allowed. They are ANDed. (optional, default: None)

Raises

SimplethError

  • if event_name is not found in the contract (E-010-010)

  • if event_args is not a dictionary (E-010-020)

  • if event_args has an unknown or misspelled event argument name (E-010-030)

  • if event_args has an event value with the wrong type. (E-010-040)

Example
>>> from simpleth import Contract, EventSearch
>>> c = Contract('Test')
>>> addr = c.connect()
>>> e1 = EventSearch(c, 'NumsStored')
>>> e2 = EventSearch(c, 'NumsStored', {'num0': 10})
>>> e3 = EventSearch(c, 'NumsStored', {'num0': 10, 'num1': 20})
>>> e1    
<simpleth.EventSearch object at 0x00000207818D9F00>
>>> e2    
<simpleth.EventSearch object at 0x000001C676C6BFD0>
>>> e3    
<simpleth.EventSearch object at 0x000001C67460D900>

Note

Using event_args:

  • If event_args is not specified, get_new() and get_old() will search for events just using the event_name.

  • If events_args is specified, get_new() and get_old() will narrow the search to events that match the value(s) specified for event args.

  • When specifying event_args, any number of dictionary entries are allowed.

  • When multiple event_args dictionary items are specified, the search will AND them together. There is no way to specify an OR. (To do an OR you could create mutliple EventSearch objects, each with one of the values for the args you want, and run both searches and combine the resulting event lists.)

  • An empty dictionary will search for the event_name only; same as not specifying that empty dictionary.

  • An event name should only be specified once. If you specify it multiple times, only the last entry is used; for example, {‘num0’: 10, ‘num0’: 20} is the same as {‘num0’: 20}.

  • You can have multiple EventSearch() objects at one time for a spcific event, for example: e_all = EventSearch(c, ‘NumsStored’) along with e_num0_10 - EventSearch(c, ‘NumsStored, {‘num0’: 10})). You can then use any number of get_new() and get_old() with both of them.

property event_args: Optional[dict]

Return the event parameter names and values used for the search.

Return type

dict

Returns

event args used for the search, if any were specified.

Example
>>> from simpleth import Contract, EventSearch
>>> c = Contract('Test')
>>> addr = c.connect()
>>> e = EventSearch(c, 'NumsStored', {'num2': 2})
>>> e    
<simpleth.EventSearch object at 0x00000207818D9F00>
>>> e.event_args    
{'num2': 2}
property event_name: str

Return the name of the event used for the search.

Return type

str

Returns

event name used for the search

Example
>>> from simpleth import Contract, EventSearch
>>> c = Contract('Test')
>>> addr = c.connect()
>>> e = EventSearch(c, 'NumsStored')
>>> e    
<simpleth.EventSearch object at 0x00000207818D9F00>
>>> e.event_name
'NumsStored'
get_new() List

Search newly mined blocks for the specific event.

The first call checks for the event in the blocks mined since Event() was created. Each subsequent call checks for the event in the blocks mined since the previous call.

If EventSearch specifed event_args, the search will be narrowed to events matching the event_name having the specified event args with event values.

Return type

list

Returns

  • list with one item for each event emitted since the previous call.

  • empty list if no events were emitted since the previous call.

Example
>>> from simpleth import Contract, Blockchain, EventSearch
>>> c = Contract('Test')
>>> address = c.connect()
>>> u = Blockchain().address(0)
>>> e = EventSearch(c, 'NumsStored')
>>> e.get_new()
[]
>>> # r keeps doctest from dealing with returned contract address
>>> r = c.run_trx(u, 'storeNums', 10, 20, 30)
>>> r = c.run_trx(u, 'storeNums', 100, 200, 300)
>>> len(e.get_new())
2
>>> e.get_new()
[]
>>> receipt = c.run_trx(u, 'storeNums', 101, 201, 301)
>>> e.get_new()    
[{'block_number': 2733,
   'args': {
      'timestamp': 1650915279, 'num0': 101, 'num1': 201, 'num2': 301
      },
   'trx_hash': '0x45345fb27043b978875d13 ... 8c80708c0d813cd'}]

See also

Contract.events for the list of events emitted by this contract.

get_old(from_block: Optional[int] = None, to_block: Optional[int] = None) List

Search previously mined blocks for a specific event.

If EventSearch specifed event_args, the search will be narrowed to events matching the event_name having the specified event args with event values in the range of mined blocks in the args specified in this call to get_old().

Parameters
  • from_block (int | None) – starting block to search mined blocks (optional, default: None)

  • to_block (int | None) – ending block to search mined blocks (optional, default: None)

Raises

SimplethError

  • if from_block is not integer or None (E-030-010)

  • if to_block is not integer or None (E-030-020)

  • if to_block is specified without a from_block (E-030-030)

  • if from_block, by itself, is greater than zero (E-030-040)

  • if a negative from_block goes beyond the length of the chain (E-030-050)

  • if to_block is specified and from_block is negative (E-030-060)

  • if from_block is greater than to_block (E-030-070)

  • if from_block is greater than Blockchain().block_number (E-030-080)

  • if to_block is greater than Blockchain().block_number (E-030-090)

Return type

list

Returns

one item for each event found; empty list if no events found

Example
>>> from simpleth import Blockchain, Contract, EventSearch
>>> c = Contract('Test')
>>> addr = c.connect()
>>> u = Blockchain().address(0)
>>> e = EventSearch(c, 'NumsStored')
>>> # r keeps doctest from dealing with returned contract addr
>>> r = c.run_trx(u, 'storeNums', 1, 2, 3)
>>> r = c.run_trx(u, 'storeNums', 5, 6, 7)
>>> r = c.run_trx(u, 'storeNums', 8, 9, 10)
>>> e.get_old()    
[{
    'block_number': 2738,
    'args': {
        'timestamp': 1650916533,
        'num0': 8,
        'num1': 9,
        'num2': 10
    },
    'trx_hash': '0xf3629545d ... 3982ad3e2d07d9'
}]
>>> len(e.get_old(-1))
2
>>> len(e.get_old(2736, 2737))    
2

Note

Using from_block and to_block:

  • get_old() searches the most recently mined block.

  • get_old(0) also searches the most recently mined block.

  • get_old(-x) searches the most recently mined blocks; where ‘-1’ will search the two most recently mined block, ‘-2’ will search the three most recently mined blocks, etc.

  • get_old(m,n) searches block ‘m’ to block ‘n’.

  • To search one specific block, use get_old(<block>, <block>). get_old(<block>) is not valid.

See also

Contract.events for the list of valid events emitted by this contract.

class simpleth.Results(contract: Contract, receipt: Any)

Data class created after a transaction is mined making most of the transaction information easily accessible.

A Results object is created with a Contract object and a transaction receipt returned from one of:

By accessing the result object returned from one of these methods, the following properties provide the outcome details.

PROPERTIES

METHODS

  • __str__() - allows print(<result>) to output most properties

OTHER ATTRIBUTES For debugging or using the web3 data formatting the following attributes are available:

  • _contract - Contract() object passed in as arg to Results()

  • web3_contract_object - web3 object passed in as arg to Results()

  • web3_event_logs - web3 format of the event log(s) generated by the transaction

  • web3_function_object - web3 object for the Solidity function that ran the transaction.

  • web3_receipt - web3 format of the transaction receipt data. Same information as receipt() but web3 uses AttributeDict and HexBytes.

  • web3_transaction - web3 format of the transaction data. Same information as transaction() but web3 uses AttributeDict and HexBytes.

One of the easiest ways to use Results is to print the result as shown below.

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[2]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> trx_receipt = c.run_trx(user, 'storeNums', 30, 20, 10)
>>> trx_results = Results(c, trx_receipt)
>>> print(trx_results)    
Block number     = 6262
Block time epoch = 1652804401
Contract name    = Test
Contract address = 0x52dBBE6A483a2Bf9a4F09264d9BFA842f01497d8
Trx name         = storeNums
Trx args         = {'_num0': 30, '_num1': 20, '_num2': 10}
Trx sender       = 0x02F6903D426Be890BA4F882eD19cF6780ecdfA5b
Trx value wei    = 0
Trx hash         = 0x9596762933eff964b4577f4a5e533f7ff67eb11ef04e616a55f3f3eede03f38d
Gas price wei    = 20000000000
Gas used         = 34564
Event name[0]    = NumsStored
Event args[0]    = {'timestamp': 1652804401, 'num0': 30, 'num1': 20, 'num2': 10}
>>> trx_results.block_number    
6262
>>>

RAISES

  • SimplethError if constructor params are bad (R-010-010)

  • SimplethError if unable to gather data for events (internal error that should not happen) (R-010-020, R-010-030, R-010-040)

__init__(contract: Contract, receipt: Any) None

Create data object with the result of a transaction.

Parameters
  • contract (object) – Contract containing the transaction

  • receipt (T_RECEIPT) – transaction receipt created after the transaction was mined

property block_number: int

Return block number of block containing the transaction.

Return type

int

Returns

number of block with transaction

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.block_number    
142
property block_time_epoch: int

Return time block with transaction was mined, in epoch seconds.

Return type

int

Returns

time, in epoch seconds, when block was mined.

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.block_time_epoch    
1638751644
property contract: Contract

Return Contract object for the transaction.

This is the contract parameter used for __init__().

Return type

obj

Returns

simpleth Contract() object

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.contract    
<simpleth.Contract object at 0x000001246CE5CA60>
property contract_address: str

Return address of the transaction’s contract.

Return type

str

Returns

address of contract

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.contract_address    
'0xD34dB707D084fdd1D99Cf9Af77896283a083c470'
property contract_name: str

Return name of the contract issuing the transaction.

Return type

str

Returns

name of contract

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.contract_name
'Test'
property event_args: list

Return args for the event emitted by the transaction.

Return type

list

Returns

list containing one dict for each event emitted; the key is the arg name and the value is the value of the arg

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.event_args      
[{'timestamp': 1652307149, 'num0': 10, 'num1': 10, 'num2': 10}]

Note

The event name that emitted these args is found in event_names(). Use the same index into list to get the event name.

property event_logs: list

Return event logs resulting from transaction.

This differs from the web3.py event logs in three ways:

  1. web3 returns the log as a list of tuples, each tuple has one event emitted.

  2. web3 returns the tuple item as an AttributeDict. This uses dicts. Likewise, within an event there are AttributeDicts and this uses dicts instead.

  3. web3 returns hashes as HexBytes and this uses strings.

Return type

list

Returns

one dict per event emitted

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.event_logs          
[{'args': {'num0': 10, 'num1': 20, 'num2': 20}, 'event': 'NumsStored'
property event_names: list

Return names of the event emitted by the transaction.

Return type

list

Returns

list of strings of the names of each event emitted

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.event_names
['NumsStored']

Note

The event args that were emitted for this event are found in event_args(). Use the same index into list to get the event args.

property gas_price_wei: int

Return price, in wei, charged for each unit of gas used by the transaction.

Return type

int

Returns

gas price, in wei

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.gas_price_wei    
20000000000
property gas_used: int

Return units of gas used by the transaction.

Return type

int

Returns

units of gas used to run transaction

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.gas_used    
25863
property transaction: Any

Return the transaction info kept by web3 eth.

Return type

dict

Returns

transaction info

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.transaction    
{'hash': '0x81d725c47a94e71aa40561ff96da8d99ce105a1327239a867099bb0e480e492b',
property trx_args: dict

Return arguments passed into the transaction.

Return type

dict

Returns

key is param name; value is arg value passed to transaction

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.trx_args
{'_num0': 10, '_num1': 10, '_num2': 10}
property trx_hash: Any

Return transaction hash for the mined transaction.

Return type

str

Returns

hash that identifies this transaction on blockchain.

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.trx_hash    
'0x0e36d22f42dbf641cef1e9f26daeb00f28a4850fccde39fb11886a980b8f59d6'
property trx_name: str

Return name of the transaction.

Return type

str

Returns

name of transaction

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.trx_name
'storeNums'
property trx_receipt: Any

Return the transaction receipt.

trx_receipt that is returned is a dict that does not use AttributeDict nor HexBytes. The web3 formatted receipt that uses those data types is available as the attribute, web3_receipt.

Return type

dict

Returns

receipt after transaction was mined.

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.trx_receipt    
{'transactionHash': HexBytes('0x0e36d22f42dbf641cef1e9f26daeb00f2 ... ')}
property trx_sender: str

Return the adddress of account that sent the transaction.

Return type

int

Returns

gas price, in wei

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNums',10,10,10)
>>> trx_result = Results(c, receipt)
>>> trx_result.trx_sender     
'0xB7fc6B28ea0c1c0d4ec54143A552aF67260905cF'
property trx_value_wei: int

Return amount of Ether, in wei, sent with the transaction.

Return type

int

Returns

amount of Ether, in wei, sent with the transaction

Example
>>> from simpleth import Blockchain, Contract, Results
>>> b = Blockchain()
>>> user = b.accounts[8]
>>> c = Contract('Test')
>>> addr = c.connect()
>>> receipt = c.run_trx(user,'storeNumsAndPay',10,10,10,value_wei=10)
>>> trx_result = Results(c, receipt)
>>> trx_result.trx_value_wei
10
exception simpleth.SimplethError(message: str, code: str = '', revert_description: str = '')

Simple Ethereum Error exception class.

It is used by Contract, Convert, Blockchain, Results, and EventSearch to throw exceptions for errors resulting from interacting with Solidity contracts and the Ethereum blockchain.

The web3 API throws many types of exceptions and its methods are not consistent in which they throw. SimplethError catches almost all of these (when new ones are found, they are added) and reports the details. This means you only have to have a try/except with just SimplethError instead of having half-dozen Python exceptions in the except.

Besides, passing back the details from the original Python exception, SimplethError offers hints as to the cause of the problem. Some exceptions, esp. the ones caused by an error with the Solidity contract, can be rather mysterious, esp. to someone just starting out with Ethereum. The hints may quickly point you to the cause.

At the time of the early version of simpleth (circa 2020), the exceptions being thrown had very little explanation and could be difficult to locate the cause. More recent versions of web3.py are adding good descriptions of the error in their exception Message parameter. If all web3.py exceptions add helpful messages, one of the big reasons for SimplethError is fixed and time to consider doing away with it.

__init__(message: str, code: str = '', revert_description: str = '') None

Create error exception.

Parameters
  • message (str) – error message with a description of error

  • code (str) – unique identifier of this error (optional, default: ‘’)

  • revert_description – reason from a transaction revert() or require() (optional, default: ‘’)

Example
>>> from simpleth import SimplethError
>>> try:
...     raise SimplethError('test')
... except SimplethError as e:
...     print(e)
...
test
>>>
>>> try:
...     raise SimplethError(
...         'test message',
...         code='TEST-010-020',
...         revert_description='Sender was not owner'
...         )
... except SimplethError as e:
...     print(f'e                = {e}')
...     print(f'code             = {e.code}')
...     print(f'revert           = {e.revert_description}')
...     excp = e
...
e                = [TEST-010-020] test message
code             = TEST-010-020
revert           = Sender was not owner
>>>
>>> from simpleth import Blockchain, Contract
>>> u = Blockchain().address(0)
>>> t=Contract('Test')
>>> t.connect()      
'0x02051679af2Bd7A276085212fcBe98ebeF747FDb'
>>> try:             
...     t.run_trx(u, 'throwRevertWithMessage', 'Sender was not owner')
... except SimplethError as e:
...     print(f'e     = {e}')
...     print(f'code  = {e.code}')
...     print(f'revert_description = {e.revert_description}')
...     excp = e
...
e     = [C-080-080] ERROR in Test().submit_trx(throwRevertWithMessage).
ValueError says: VM Exception while processing transaction: revert Sender was not owner
HINT1:  Did you fail to pass a transaction require()?
...snip...
code  = C-080-080
revert_description = Sender was not owner
>>> excp.exc_info       
(<class 'ValueError'>, ValueError({'message': 'VM Exception ...snip....

Note

  • code can serve several purposes:

    • It can be easily tested in unit tests to make sure a test case is causing a specific error.

    • It makes it easy to search simpleth doumentation for a comment about the cause of a specific SimplEthException.

    • It makes it easy to search simpleth code for the line of code that raised a specific SimplEthException.

  • The format for code:

    <c>-<method>-<id>

    Where:

    • <c> is (mostly) the first character of the class:

      • B for Blockchain class

      • C for Contract class

      • E for Event class

      • R for Results class

      • V for Convert class

    • <method> is a 3-digit sequence number for the method in the class.

    • <id> is a 3-digit sequence number for the exception in the method.

TBD

make exc_info, message, and code private, so they do not appear in doc.

exc_info: Any

Exception instance variable with exception info: (type, value, traceback)

message: str

Exception instance variable with message

revert_description: str

Exception instance variable with revert() or require() reason from transaction

code: str

Exception instance variable with code