def transact_with_contract_function(address, web3, function_name=None, transaction=None, contract_abi=None, fn_abi=None, *args, **kwargs): """ Helper function for interacting with a contract function by sending a transaction. This is copied from web3 `transact_with_contract_function` so we can use `personal_sendTransaction` when possible. """ transact_transaction = prepare_transaction( address, web3, fn_identifier=function_name, contract_abi=contract_abi, transaction=transaction, fn_abi=fn_abi, fn_args=args, fn_kwargs=kwargs, ) passphrase = None key_file = None if transaction and 'passphrase' in transaction: passphrase = transaction['passphrase'] transact_transaction.pop('passphrase') if 'keyfile' in transaction: key_file = transaction['keyfile'] transact_transaction.pop('keyfile') # Restrict transactions to raw transactions for now (security first) # if not (passphrase and key_file): # raise AssertionError( # 'password and key file are required for signing transactions locally.' # ) if passphrase and key_file: raw_tx = Wallet(web3, key_file, passphrase).sign_tx(transact_transaction) logging.debug( f'sending raw tx: function: {function_name}, tx hash: {raw_tx.hex()}' ) txn_hash = web3.eth.sendRawTransaction(raw_tx) elif passphrase: txn_hash = web3.sendTransaction(transact_transaction, passphrase) else: txn_hash = web3.eth.sendTransaction(transact_transaction) return txn_hash
def transact_with_contract_function( address, web3, function_name=None, transaction=None, contract_abi=None, fn_abi=None, *args, **kwargs, ): """ Helper function for interacting with a contract function by sending a transaction. This is copied from web3 `transact_with_contract_function` so we can use `personal_sendTransaction` when possible. """ transact_transaction = prepare_transaction( address, web3, fn_identifier=function_name, contract_abi=contract_abi, transaction=transaction, fn_abi=fn_abi, fn_args=args, fn_kwargs=kwargs, ) passphrase = None account_key = None if transaction and "passphrase" in transaction: passphrase = transaction["passphrase"] transact_transaction.pop("passphrase") if "account_key" in transaction: account_key = transaction["account_key"] transact_transaction.pop("account_key") if account_key: raw_tx = Wallet(web3, private_key=account_key).sign_tx(transact_transaction) logging.debug( f"sending raw tx: function: {function_name}, tx hash: {raw_tx.hex()}" ) txn_hash = web3.eth.sendRawTransaction(raw_tx) elif passphrase: txn_hash = web3.personal.sendTransaction(transact_transaction, passphrase) else: txn_hash = web3.eth.sendTransaction(transact_transaction) wait_for_tx(txn_hash, web3, 5) return txn_hash
def transact_with_contract_function( address: str, web3: Web3, block_confirmations: int, transaction_timeout: int, function_name: Optional[str] = None, transaction: Optional[dict] = None, contract_abi: Optional[list] = None, fn_abi: Optional[dict] = None, *args, **kwargs, ) -> HexBytes: """ Helper function for interacting with a contract function by sending a transaction. This is copied from web3 `transact_with_contract_function` with a few additions: 1. If `account_key` in transaction dict, sign and send transaction via `web3.eth.send_raw_transaction` 2. Otherwise, send via `web3.eth.send_transaction` 3. Retry failed transactions (when txn_receipt.status indicates failure) 4. Network-dependent timeout """ transact_transaction = prepare_transaction( address, web3, fn_identifier=function_name, contract_abi=contract_abi, transaction=transaction, fn_abi=fn_abi, fn_args=args, fn_kwargs=kwargs, ) account_key = None if transaction and "account_key" in transaction: account_key = transaction["account_key"] transact_transaction.pop("account_key") if account_key: raw_tx = Wallet( web3, private_key=account_key, block_confirmations=Integer(block_confirmations), transaction_timeout=Integer(transaction_timeout), ).sign_tx(transact_transaction) logging.debug( f"sending raw tx: function: {function_name}, tx hash: {raw_tx.hex()}" ) txn_hash = web3.eth.send_raw_transaction(raw_tx) else: txn_hash = web3.eth.send_transaction(transact_transaction) chain_id = get_chain_id(web3) block_number_poll_interval = BLOCK_NUMBER_POLL_INTERVAL[chain_id] wait_for_transaction_receipt_and_block_confirmations( web3, txn_hash, block_confirmations, block_number_poll_interval, transaction_timeout, ) return txn_hash