Skip to content

Commit

Permalink
Add mempool.space Next Block sensors
Browse files Browse the repository at this point in the history
  • Loading branch information
TheHolyRoger committed Jan 10, 2024
1 parent 848b3b8 commit be997dc
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 4 deletions.
3 changes: 2 additions & 1 deletion Version
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ Version: 0.3.0 20230426 - Rename to Cryptoinfo Advanced
Version: 0.3.1 20230426 - Fixes for HACS/HASS requirements
Version: 0.3.2 20230507 - Add total unknown hash control sensor to chain control, mempool total fee calculated.
Version: 0.3.3 20230521 - Fix a few errors during updates.
Version: 0.3.4 20240110 - Add mempool.space fees sensors.
Version: 0.3.4 20240110 - Add mempool.space fees sensors.
Version: 0.3.5 20240110 - Add mempool.space Next Block sensors.
2 changes: 1 addition & 1 deletion custom_components/cryptoinfo_advanced/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.3.4"
__version__ = "0.3.5"
10 changes: 10 additions & 0 deletions custom_components/cryptoinfo_advanced/const/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@
ATTR_MEMPOOL_FEES_60MIN = "mempool_fees_60min"
ATTR_MEMPOOL_FEES_ECO = "mempool_fees_eco"
ATTR_MEMPOOL_FEES_MINIMUM = "mempool_fees_minimum"
ATTR_MEMPOOL_NEXT_BLOCK_SIZE = "mempool_next_block_size"
ATTR_MEMPOOL_NEXT_BLOCK_SIZE_CALC = "mempool_next_block_size_calc"
ATTR_MEMPOOL_NEXT_BLOCK_TX_COUNT = "mempool_next_block_tx_count"
ATTR_MEMPOOL_NEXT_BLOCK_TOTAL_FEE = "mempool_next_block_total_fee"
ATTR_MEMPOOL_NEXT_BLOCK_TOTAL_FEE_CALC = "mempool_next_block_total_fee_calc"
ATTR_MEMPOOL_NEXT_BLOCK_MEDIAN_FEE = "mempool_next_block_median_fee"
ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_MIN = "mempool_next_block_fee_range_min"
ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_MAX = "mempool_next_block_fee_range_max"
ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_COMBINED = "mempool_next_block_fee_range_combined"

PROPERTY_POOL_CONTROL_REMAINING = "remaining_percentage"

Expand All @@ -99,6 +108,7 @@
API_ENDPOINT_NOMP_POOL_STATS = "https://{0}/api/stats"
API_ENDPOINT_MEMPOOL_STATS = "{0}mempool"
API_ENDPOINT_MEMPOOL_FEES = "{0}v1/fees/recommended"
API_ENDPOINT_MEMPOOL_NEXT_BLOCKS = "{0}v1/fees/mempool-blocks"

DAY_SECONDS = 60 * 60 * 24

Expand Down
117 changes: 117 additions & 0 deletions custom_components/cryptoinfo_advanced/crypto_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@
ATTR_MEMPOOL_FEES_60MIN,
ATTR_MEMPOOL_FEES_ECO,
ATTR_MEMPOOL_FEES_MINIMUM,
ATTR_MEMPOOL_NEXT_BLOCK_SIZE,
ATTR_MEMPOOL_NEXT_BLOCK_SIZE_CALC,
ATTR_MEMPOOL_NEXT_BLOCK_TX_COUNT,
ATTR_MEMPOOL_NEXT_BLOCK_TOTAL_FEE,
ATTR_MEMPOOL_NEXT_BLOCK_TOTAL_FEE_CALC,
ATTR_MEMPOOL_NEXT_BLOCK_MEDIAN_FEE,
ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_COMBINED,
ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_MIN,
ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_MAX,
ATTR_MEMPOOL_TX_COUNT,
ATTR_MEMPOOL_TOTAL_FEE,
ATTR_MEMPOOL_TOTAL_FEE_CALC,
Expand All @@ -76,6 +85,7 @@
API_ENDPOINT_CHAIN_BLOCK_TIME,
API_ENDPOINT_NOMP_POOL_STATS,
API_ENDPOINT_MEMPOOL_FEES,
API_ENDPOINT_MEMPOOL_NEXT_BLOCKS,
API_ENDPOINT_MEMPOOL_STATS,
CONF_DIFF_MULTIPLIER,
CONF_BLOCK_TIME_MINUTES,
Expand Down Expand Up @@ -199,6 +209,12 @@ def __init__(
self._mempool_fees_60min = None
self._mempool_fees_eco = None
self._mempool_fees_minimum = None
self._mempool_next_block_size = None
self._mempool_next_block_tx_count = None
self._mempool_next_block_total_fee = None
self._mempool_next_block_median_fee = None
self._mempool_next_block_fee_range_min = None
self._mempool_next_block_fee_range_max = None

@property
def is_child_sensor(self):
Expand Down Expand Up @@ -372,6 +388,24 @@ def mempool_total_fee_calc(self, unit_of_measurement):

return round(float(self._mempool_total_fee) / currency_to_multiplier(unit_of_measurement), 4)

def mempool_next_block_size_calc(self, unit_of_measurement):
if self._mempool_next_block_size is None:
return None

return round(float(self._mempool_next_block_size) / unit_to_multiplier(unit_of_measurement), 4)

def mempool_next_block_total_fee_calc(self, unit_of_measurement):
if self._mempool_next_block_total_fee is None:
return None

return round(float(self._mempool_next_block_total_fee) / currency_to_multiplier(unit_of_measurement), 4)

def mempool_next_block_fee_range_combined(self, unit_of_measurement):
if self._mempool_next_block_fee_range_min is None or self._mempool_next_block_fee_range_max is None:
return None

return f"{self._mempool_next_block_fee_range_min:.0f} - {self._mempool_next_block_fee_range_max:.0f}"

@property
def all_time_high_distance(self):
if self._all_time_high is None or self.state is None:
Expand Down Expand Up @@ -446,6 +480,14 @@ def get_extra_state_attrs(self, full_attr_force=False):
output_attrs[ATTR_MEMPOOL_FEES_ECO] = self._mempool_fees_eco
output_attrs[ATTR_MEMPOOL_FEES_MINIMUM] = self._mempool_fees_minimum

if full_attr_force or self._fetch_type == CryptoInfoAdvDataFetchType.MEMPOOL_NEXT_BLOCK:
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_SIZE] = self._mempool_next_block_size
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_TX_COUNT] = self._mempool_next_block_tx_count
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_TOTAL_FEE] = self._mempool_next_block_total_fee
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_MEDIAN_FEE] = self._mempool_next_block_median_fee
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_MIN] = self._mempool_next_block_fee_range_min
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_MAX] = self._mempool_next_block_fee_range_max

return output_attrs

@property
Expand Down Expand Up @@ -514,6 +556,23 @@ def get_extra_sensor_attrs(self, full_attr_force=False, child_sensor=None):
if child_sensor is None or child_sensor.attribute_key == ATTR_MEMPOOL_AVERAGE_FEE_PER_TX:
output_attrs[ATTR_MEMPOOL_AVERAGE_FEE_PER_TX] = self.mempool_average_fee_per_tx

if full_attr_force or self._fetch_type == CryptoInfoAdvDataFetchType.MEMPOOL_NEXT_BLOCK:

if child_sensor is None or child_sensor.attribute_key == ATTR_MEMPOOL_NEXT_BLOCK_SIZE_CALC:
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_SIZE_CALC] = self.mempool_next_block_size_calc(
child_sensor.unit_of_measurement if child_sensor is not None else None
)

if child_sensor is None or child_sensor.attribute_key == ATTR_MEMPOOL_NEXT_BLOCK_TOTAL_FEE_CALC:
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_TOTAL_FEE_CALC] = self.mempool_next_block_total_fee_calc(
child_sensor.unit_of_measurement if child_sensor is not None else None
)

if child_sensor is None or child_sensor.attribute_key == ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_COMBINED:
output_attrs[ATTR_MEMPOOL_NEXT_BLOCK_FEE_RANGE_COMBINED] = self.mempool_next_block_fee_range_combined(
child_sensor.unit_of_measurement if child_sensor is not None else None
)

if full_attr_force or self._fetch_type == CryptoInfoAdvDataFetchType.PRICE_MAIN:

if child_sensor is None or child_sensor.attribute_key == ATTR_ALL_TIME_HIGH_DISTANCE:
Expand Down Expand Up @@ -757,6 +816,18 @@ def _extract_data_mempool_fees_full(self, json_data):
def _extract_data_mempool_fees_primary(self, api_data):
return int(api_data["fastestFee"])

def _extract_data_mempool_next_block_full(self, json_data):
return json_data

def _extract_data_mempool_next_block_primary(self, api_data):
return int(api_data[0]["nTx"])

def _extract_data_mempool_next_block_special(self, json_data):
if isinstance(json_data, list) and len(json_data) >= 2:
return list([json_data[0]["feeRange"][0], json_data[0]["feeRange"][-1]])

return None

async def _fetch_price_data_main(self, api_data=None):
if not self._fetch_type == CryptoInfoAdvDataFetchType.PRICE_MAIN:
raise ValueError()
Expand Down Expand Up @@ -1023,6 +1094,37 @@ async def _fetch_mempool_fees(self, api_data=None):

return self.data

async def _fetch_mempool_next_block(self, api_data=None):
self.check_valid_config()

mempool_data, api_data = await self._async_api_fetch(
api_data,
API_ENDPOINT_MEMPOOL_NEXT_BLOCKS.format(API_BASE_URL_MEMPOOLSPACE),
self._extract_data_mempool_next_block_full,
self._extract_data_mempool_next_block_primary
)

if mempool_data is not None:
fee_ranges = self._extract_data_mempool_next_block_special(api_data)

if fee_ranges is None:
raise ValueError()

self._update_all_properties(
state=int(mempool_data),
mempool_next_block_size=int(api_data[0]["blockSize"]),
mempool_next_block_tx_count=int(api_data[0]["nTx"]),
mempool_next_block_total_fee=int(api_data[0]["totalFees"]),
mempool_next_block_median_fee=int(api_data[0]["medianFee"]),
mempool_next_block_fee_range_min=int(fee_ranges[0]),
mempool_next_block_fee_range_max=int(fee_ranges[1]),
)

else:
raise ValueError()

return self.data

def _render_fetch_args(self):
if self._fetch_args is None:
return None
Expand Down Expand Up @@ -1106,6 +1208,12 @@ def _update_all_properties(
mempool_fees_60min=None,
mempool_fees_eco=None,
mempool_fees_minimum=None,
mempool_next_block_size=None,
mempool_next_block_tx_count=None,
mempool_next_block_total_fee=None,
mempool_next_block_median_fee=None,
mempool_next_block_fee_range_min=None,
mempool_next_block_fee_range_max=None,
available=True,
):
self._state = state
Expand Down Expand Up @@ -1139,6 +1247,12 @@ def _update_all_properties(
self._mempool_fees_60min = mempool_fees_60min
self._mempool_fees_eco = mempool_fees_eco
self._mempool_fees_minimum = mempool_fees_minimum
self._mempool_next_block_size = mempool_next_block_size
self._mempool_next_block_tx_count = mempool_next_block_tx_count
self._mempool_next_block_total_fee = mempool_next_block_total_fee
self._mempool_next_block_median_fee = mempool_next_block_median_fee
self._mempool_next_block_fee_range_min = mempool_next_block_fee_range_min
self._mempool_next_block_fee_range_max = mempool_next_block_fee_range_max
self._attr_available = available

self._update_child_sensors()
Expand Down Expand Up @@ -1220,6 +1334,9 @@ async def _async_update(self):
elif self._fetch_type == CryptoInfoAdvDataFetchType.MEMPOOL_FEES:
api_data = await self._fetch_mempool_fees(api_data)

elif self._fetch_type == CryptoInfoAdvDataFetchType.MEMPOOL_NEXT_BLOCK:
api_data = await self._fetch_mempool_next_block(api_data)

else:
api_data = await self._fetch_price_data_main(api_data)

Expand Down
3 changes: 3 additions & 0 deletions custom_components/cryptoinfo_advanced/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class CryptoInfoAdvDataFetchType:
NOMP_POOL_STATS = CryptoInfoAdvFetchProp("nomp_pool_stats")
MEMPOOL_STATS = CryptoInfoAdvFetchProp("mempool_stats")
MEMPOOL_FEES = CryptoInfoAdvFetchProp("mempool_fees")
MEMPOOL_NEXT_BLOCK = CryptoInfoAdvFetchProp("mempool_next_block")


class CryptoInfoAdvEntityManager:
Expand Down Expand Up @@ -108,6 +109,7 @@ def fetch_types(self):
CryptoInfoAdvDataFetchType.NOMP_POOL_STATS,
CryptoInfoAdvDataFetchType.MEMPOOL_STATS,
CryptoInfoAdvDataFetchType.MEMPOOL_FEES,
CryptoInfoAdvDataFetchType.MEMPOOL_NEXT_BLOCK,
]

@property
Expand Down Expand Up @@ -165,6 +167,7 @@ def fetch_mempool_types(self):
return [
CryptoInfoAdvDataFetchType.MEMPOOL_STATS,
CryptoInfoAdvDataFetchType.MEMPOOL_FEES,
CryptoInfoAdvDataFetchType.MEMPOOL_NEXT_BLOCK,
]

def get_extra_sensor_fetch_type_from_str(self, parent_sensor, attribute_key):
Expand Down
2 changes: 1 addition & 1 deletion custom_components/cryptoinfo_advanced/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/TheHolyRoger/hass-cryptoinfo/issues",
"requirements": [],
"version": "0.3.4"
"version": "0.3.5"
}
2 changes: 1 addition & 1 deletion custom_components/cryptoinfo_advanced/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def unit_to_multiplier(unit_of_measurement):

def currency_to_multiplier(currency):
coin = str(currency).lower() if currency is not None else ""
if coin in ["btc", "bitcoin"]:
if coin in ["btc", "bitcoin", "bitcoins", "₿"]:
return 1e8
else:
return 1
20 changes: 20 additions & 0 deletions example/configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,26 @@ sensor:
id: "BTC Mempool Fees - Minimum"
unit_of_measurement: "sats"

- platform: cryptoinfo_advanced
id: "BTC Next Block - Total TX"
cryptocurrency_name: "btc"
unit_of_measurement: "tx"
update_frequency: 1
api_mode: "mempool_next_block"
extra_sensors:
- property: mempool_next_block_size_calc
id: "BTC Next Block - Size"
unit_of_measurement: "MB"
- property: mempool_next_block_total_fee_calc
id: "BTC Next Block - Total Fees"
unit_of_measurement: ""
- property: mempool_next_block_median_fee
id: "BTC Next Block - Median Fee"
unit_of_measurement: "sat/vB"
- property: mempool_next_block_fee_range_combined
id: "BTC Next Block - Fee Range"
unit_of_measurement: "sat/vB"



# ROGER NOMP Pool stats - API: NOMP (Any NOMP based pool)
Expand Down

0 comments on commit be997dc

Please sign in to comment.