Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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