Exemplo n.º 1
0
def fill_transaction_defaults(web3: "Web3", transaction: TxParams) -> TxParams:
    """
    if web3 is None, fill as much as possible while offline
    """
    defaults = {}
    for key, default_getter in TRANSACTION_DEFAULTS.items():
        if key not in transaction:
            if key == 'gasPrice' and any_in_dict(DYNAMIC_FEE_TXN_PARAMS,
                                                 transaction):
                # if dynamic fee txn params present, do not set a default 'gasPrice' if missing
                continue

            if callable(default_getter):
                if web3 is not None:
                    default_val = default_getter(web3, transaction)
                else:
                    raise ValueError("You must specify %s in the transaction" %
                                     key)

            else:
                default_val = default_getter
            defaults[key] = default_val

    if 'type' not in transaction and any_in_dict(DYNAMIC_FEE_TXN_PARAMS,
                                                 transaction):
        # default transaction type to '2' if dynamic fee txn params are present
        defaults['type'] = '0x2'

    return merge(defaults, transaction)
Exemplo n.º 2
0
def fill_transaction_defaults(web3: "Web3", transaction: TxParams) -> TxParams:
    """
    if web3 is None, fill as much as possible while offline
    """
    strategy_based_gas_price = web3.eth.generate_gas_price(transaction)
    is_dynamic_fee_transaction = (
        not strategy_based_gas_price and
        ('gasPrice' not in transaction  # default to dynamic fee transaction
         or any_in_dict(DYNAMIC_FEE_TXN_PARAMS, transaction)))

    defaults = {}
    for key, default_getter in TRANSACTION_DEFAULTS.items():
        if key not in transaction:
            if (is_dynamic_fee_transaction and key == 'gasPrice'
                    or not is_dynamic_fee_transaction
                    and key in DYNAMIC_FEE_TXN_PARAMS):
                # do not set default max fees if legacy txn or gas price if dynamic fee txn
                continue

            if callable(default_getter):
                if web3 is None:
                    raise ValueError(
                        "You must specify a '%s' value in the transaction" %
                        key)
                default_val = default_getter(web3, transaction)
            else:
                default_val = default_getter

            defaults[key] = default_val
    return merge(defaults, transaction)
Exemplo n.º 3
0
def validate_transaction_params(transaction: TxParams, latest_block: BlockData,
                                strategy_based_gas_price: Wei) -> TxParams:
    # gas price strategy explicitly set:
    if (strategy_based_gas_price is not None and 'gasPrice' not in transaction
            and none_in_dict(DYNAMIC_FEE_TXN_PARAMS, transaction)):
        transaction = assoc(transaction, 'gasPrice',
                            hex(strategy_based_gas_price))

    # legacy and dynamic fee tx variables used:
    if "gasPrice" in transaction and any_in_dict(DYNAMIC_FEE_TXN_PARAMS,
                                                 transaction):
        raise TransactionTypeMismatch()
    # dynamic fee transaction - canonical case:
    elif all_in_dict(DYNAMIC_FEE_TXN_PARAMS, transaction):
        if int(str(transaction["maxFeePerGas"]), 16) < int(
                str(transaction["maxPriorityFeePerGas"]), 16):
            raise InvalidTransaction(
                "maxFeePerGas must be >= maxPriorityFeePerGas")
    # dynamic fee txn - no max fee:
    elif 'maxFeePerGas' not in transaction and 'maxPriorityFeePerGas' in transaction:
        base_fee = latest_block['baseFeePerGas']
        priority_fee = int(str(transaction['maxPriorityFeePerGas']), 16)
        max_fee_per_gas = priority_fee + 2 * base_fee
        transaction = assoc(transaction, 'maxFeePerGas', hex(max_fee_per_gas))
    # dynamic fee transaction - no priority fee:
    elif 'maxFeePerGas' in transaction and 'maxPriorityFeePerGas' not in transaction:
        raise InvalidTransaction(
            "maxPriorityFeePerGas must be defined in a 1559 transaction.")

    # should be a fully formed (legacy or dynamic fee) tx or no fee values were specified
    return transaction
Exemplo n.º 4
0
def prepare_replacement_transaction(web3: "Web3",
                                    original_transaction: TxData,
                                    replacement_transaction: TxParams,
                                    gas_multiplier: float = 1.125) -> TxParams:
    if original_transaction['blockHash'] is not None:
        raise ValueError(
            f'Supplied transaction with hash {original_transaction["hash"]!r} '
            'has already been mined')
    if 'nonce' in replacement_transaction and (
            replacement_transaction['nonce'] != original_transaction['nonce']):
        raise ValueError(
            'Supplied nonce in new_transaction must match the pending transaction'
        )

    if 'nonce' not in replacement_transaction:
        replacement_transaction = assoc(replacement_transaction, 'nonce',
                                        original_transaction['nonce'])

    if any_in_dict(DYNAMIC_FEE_TXN_PARAMS, replacement_transaction):
        # for now, the client decides if a dynamic fee txn can replace the existing txn or not
        pass

    elif 'gasPrice' in replacement_transaction and original_transaction[
            'gasPrice'] is not None:
        if replacement_transaction['gasPrice'] <= original_transaction[
                'gasPrice']:
            raise ValueError(
                'Supplied gas price must exceed existing transaction gas price'
            )

    else:
        generated_gas_price = web3.eth.generate_gas_price(
            replacement_transaction)
        minimum_gas_price = int(
            math.ceil(original_transaction['gasPrice'] * gas_multiplier))
        if generated_gas_price and generated_gas_price > minimum_gas_price:
            replacement_transaction = assoc(replacement_transaction,
                                            'gasPrice', generated_gas_price)
        else:
            replacement_transaction = assoc(replacement_transaction,
                                            'gasPrice', minimum_gas_price)

    return replacement_transaction