def extract_valid_transaction_params(transaction_params: TxData) -> TxParams:
    extracted_params = cast(
        TxParams, {
            key: transaction_params[key]
            for key in VALID_TRANSACTION_PARAMS if key in transaction_params
        })
    # There is always a gasPrice now on eth_getTransaction call for pending transactions, including
    # dynamic fee transactions. For dynamic fee transactions, we need to pull the gasPrice value
    # back out of the extracted params if it is equal to the expected value (maxFeePerGas). If
    # we don't, the modified transaction will include a gasPrice as well as dynamic fee values in
    # the eth_sendTransaction call and cause a conflict.
    if all_in_dict(DYNAMIC_FEE_TXN_PARAMS, extracted_params):
        if extracted_params['gasPrice'] == extracted_params['maxFeePerGas']:
            extracted_params.pop('gasPrice')

    if extracted_params.get('data') is not None:
        if transaction_params.get('input') is not None:
            if extracted_params['data'] != transaction_params['input']:
                msg = 'failure to handle this transaction due to both "input: {}" and'
                msg += ' "data: {}" are populated. You need to resolve this conflict.'
                err_vals = (transaction_params['input'],
                            extracted_params['data'])
                raise AttributeError(msg.format(*err_vals))
            else:
                return extracted_params
        else:
            return extracted_params
    elif extracted_params.get('data') is None:
        if transaction_params.get('input') is not None:
            return assoc(extracted_params, 'data', transaction_params['input'])
        else:
            return extracted_params
    else:
        raise Exception(
            "Unreachable path: transaction's 'data' is either set or not set")
def extract_valid_transaction_params(transaction_params: TxData) -> TxParams:
    extracted_params = cast(
        TxParams, {
            key: transaction_params[key]
            for key in VALID_TRANSACTION_PARAMS if key in transaction_params
        })

    if extracted_params.get('data') is not None:
        if transaction_params.get('input') is not None:
            if extracted_params['data'] != transaction_params['input']:
                msg = 'failure to handle this transaction due to both "input: {}" and'
                msg += ' "data: {}" are populated. You need to resolve this conflict.'
                err_vals = (transaction_params['input'],
                            extracted_params['data'])
                raise AttributeError(msg.format(*err_vals))
            else:
                return extracted_params
        else:
            return extracted_params
    elif extracted_params.get('data') is None:
        if transaction_params.get('input') is not None:
            return assoc(extracted_params, 'data', transaction_params['input'])
        else:
            return extracted_params
    else:
        raise Exception(
            "Unreachable path: transaction's 'data' is either set or not set")
def test_check_successful_tx_successful_case() -> None:
    web3_mock = Mock()
    gas = 30000
    receipt = TxReceipt({"blockNumber": 300, "status": 1, "gasUsed": gas - 10})  # type: ignore
    web3_mock.eth.get_transaction_receipt.return_value = receipt
    txinfo = TxData({"gas": Wei(gas)})
    web3_mock.eth.get_transaction.return_value = txinfo
    txid = HexBytes("abcdef")
    assert check_successful_tx(web3=web3_mock, txid=txid) == (receipt, txinfo)
    web3_mock.eth.get_transaction_receipt.assert_called_with(txid)
    web3_mock.eth.get_transaction.assert_called_with(txid)