Skip to content

jmcore.fee_quantization

jmcore.fee_quantization

Maker fee quantization grid and helpers.

Takers can round each selected maker's fee up to the closest value on this small, shared public grid. This prevents an off-grid advertised fee from becoming a distinctive realized payment while preserving each maker's offered fee type and independent fee amount (see issue #508).

This module defines the grid and rounding primitives. The taker-side policy lives in the taker package; the orderbook watcher uses the same grid in its JSON payload.

Attributes

QUANT_ABS: tuple[int, ...] = (0, 100, 200, 500, 1000, 2000, 5000, 10000) module-attribute

QUANT_REL: tuple[Decimal, ...] = tuple(Decimal(v) for v in ('0.00002', '0.00005', '0.0001', '0.0002', '0.0005', '0.001', '0.002', '0.005', '0.01', '0.02', '0.05', '0.1')) module-attribute

Functions:

quantize_abs_down(abs_fee: int) -> int | None

Return the largest absolute grid value <= abs_fee.

Returns None only when abs_fee is negative (no grid value fits); the grid includes 0 so any non-negative fee resolves to a quantum.

Source code in jmcore/src/jmcore/fee_quantization.py
60
61
62
63
64
65
66
67
68
69
70
71
72
def quantize_abs_down(abs_fee: int) -> int | None:
    """Return the largest absolute grid value ``<= abs_fee``.

    Returns ``None`` only when ``abs_fee`` is negative (no grid value fits);
    the grid includes ``0`` so any non-negative fee resolves to a quantum.
    """
    best: int | None = None
    for q in QUANT_ABS:
        if q <= abs_fee:
            best = q
        else:
            break
    return best

quantize_abs_up(abs_fee: int) -> int | None

Return the smallest absolute grid value >= abs_fee.

Returns None when abs_fee exceeds the largest grid value.

Source code in jmcore/src/jmcore/fee_quantization.py
87
88
89
90
91
92
93
94
95
def quantize_abs_up(abs_fee: int) -> int | None:
    """Return the smallest absolute grid value ``>= abs_fee``.

    Returns ``None`` when ``abs_fee`` exceeds the largest grid value.
    """
    for q in QUANT_ABS:
        if q >= abs_fee:
            return q
    return None

quantize_rel_down(rel_fee: str | float | Decimal) -> Decimal | None

Return the largest grid value <= rel_fee.

Returns None when rel_fee is below the smallest grid value, meaning no quantum fits under the configured limit and quantization cannot apply.

Source code in jmcore/src/jmcore/fee_quantization.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def quantize_rel_down(rel_fee: str | float | Decimal) -> Decimal | None:
    """Return the largest grid value ``<= rel_fee``.

    Returns ``None`` when ``rel_fee`` is below the smallest grid value, meaning
    no quantum fits under the configured limit and quantization cannot apply.
    """
    d = Decimal(str(rel_fee))
    best: Decimal | None = None
    for q in QUANT_REL:
        if q <= d:
            best = q
        else:
            break
    return best

quantize_rel_up(rel_fee: str | float | Decimal) -> Decimal | None

Return the smallest grid value >= rel_fee.

Returns None when rel_fee exceeds the largest grid value.

Source code in jmcore/src/jmcore/fee_quantization.py
75
76
77
78
79
80
81
82
83
84
def quantize_rel_up(rel_fee: str | float | Decimal) -> Decimal | None:
    """Return the smallest grid value ``>= rel_fee``.

    Returns ``None`` when ``rel_fee`` exceeds the largest grid value.
    """
    d = Decimal(str(rel_fee))
    for q in QUANT_REL:
        if q >= d:
            return q
    return None

rel_quantum_to_sats(rel_quantum: Decimal, cj_amount: int) -> int

Convert a relative quantum to satoshis for a given CoinJoin amount.

Uses banker's rounding (ROUND_HALF_EVEN) to match :func:jmcore.bitcoin.calculate_relative_fee.

Source code in jmcore/src/jmcore/fee_quantization.py
 98
 99
100
101
102
103
104
def rel_quantum_to_sats(rel_quantum: Decimal, cj_amount: int) -> int:
    """Convert a relative quantum to satoshis for a given CoinJoin amount.

    Uses banker's rounding (ROUND_HALF_EVEN) to match
    :func:`jmcore.bitcoin.calculate_relative_fee`.
    """
    return int((Decimal(cj_amount) * rel_quantum).quantize(Decimal(1), rounding=ROUND_HALF_EVEN))