Data hooks
Adapter hooks that fetch and shape site, pool, dashboard, and chart data
@tetherto/mdk-react-adapter
TanStack Query–backed hooks that fetch live data from the MDK backend and project it into view-model shapes ready for MDK foundation components. These hooks sit in the adapter layer so that tag names, aggregate field keys, and unit conversions stay out of the devkit component layer.
All hooks require <MdkProvider> to be mounted in the tree.
At a glance
| Sub-group | Hooks |
|---|---|
| Alerts | useCurrentAlertDevices, useHistoricalAlerts |
| Auth and token | useAuthToken, useTokenPolling |
| Chart data | useConsumptionChartData, useHashrateChartData, usePowerModeTimelineData |
| Dashboard | useDashboardDateRange, useDashboardExport, useDashboardTimeRange |
| Incidents | useActiveIncidents |
| Pool data | usePoolRows, usePoolStats |
| Site data | useSiteConsumption, useSiteConsumptionChartData, useSiteContainerCapacity, useSiteEfficiency, useSiteHashrate, useSiteMinerCounts, useSiteMinerStats, useSitePowerMeter, useSitesOverviewData |
Prerequisites
- Wrap your app in
<MdkProvider> - Complete the @tetherto/mdk-react-devkit installation and add the dependency
Import
import {
useActiveIncidents,
useAuthToken,
useConsumptionChartData,
useCurrentAlertDevices,
useDashboardDateRange,
useDashboardExport,
useDashboardTimeRange,
useHashrateChartData,
useHistoricalAlerts,
usePoolRows,
usePoolStats,
usePowerModeTimelineData,
useSiteConsumption,
useSiteConsumptionChartData,
useSiteContainerCapacity,
useSiteEfficiency,
useSiteHashrate,
useSiteMinerCounts,
useSiteMinerStats,
useSitePowerMeter,
useSitesOverviewData,
useTokenPolling,
} from '@tetherto/mdk-react-adapter'Site data
useSitesOverviewData
Projects raw site-overview container rows and pool stats into a <PoolManagerSitesOverview />-ready shape. Each container receives its per-container hashrate in MH/s, an attached pool-stats row, and a mining / offline status derived from the underlying snapshot.
import { useSitesOverviewData } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
units | Required | ContainerUnit[] | none | Required. Raw container rows from the site overview query. |
poolStats | Required | ContainerPoolStat[] | none | Required. Per-container pool stat rows keyed by container id. |
isLoading | Required | boolean | none | Required. Combined loading state from the upstream queries. |
tailLogItem | Required | SitesOverviewTailLogItem | none | Required. Latest tail-log row from a stat-1m miner query; pass _head(_head(rawResponse)). |
Returns
| Member | Type | Description |
|---|---|---|
units | ProcessedContainerUnit[] | Processed containers with hashrateMhs, status, and poolStats attached. |
isLoading | boolean | Passes through the combined loading state from the options. |
Example
import { useSitesOverviewData } from '@tetherto/mdk-react-adapter'
import { PoolManagerSitesOverview } from '@tetherto/mdk-react-devkit/foundation'
function SiteOverview({ rawUnits, rawPoolStats, loading, latestTailLog }) {
const { units, isLoading } = useSitesOverviewData({
units: rawUnits,
poolStats: rawPoolStats,
isLoading: loading,
tailLogItem: latestTailLog,
})
return <PoolManagerSitesOverview units={units} isLoading={isLoading} />
}useSiteConsumption
Projects the freshest power sample from the dashboard's existing tail-log query into a scalar MW value for the header stats strip (<HeaderConsumptionBox />). Delegates fetching to useSiteConsumptionChartData.
import { useSiteConsumption } from '@tetherto/mdk-react-adapter'Options
Accepts the same UseConsumptionChartDataParams object as useSiteConsumptionChartData.
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
timeline | Required | string | none | Required. Stat key suffix, e.g. '5m'. |
start | Optional | number | none | Lower time bound (ms epoch). |
end | Optional | number | none | Upper time bound (ms epoch). |
tag | Optional | string | 't-miner' | Thing tag. Use 't-powermeter' for transformer-level readings. |
powerAttribute | Optional | string | 'power_w_sum_aggr' | Aggregate field name to read from the tail-log row. |
refetchInterval | Optional | number | 60000 | Polling interval in ms. Pass 0 to disable. |
Returns
| Member | Type | Description |
|---|---|---|
valueMw | number | undefined | Latest aggregate value in MW; undefined while loading or with no data. |
valueW | number | undefined | Raw backend value in watts. |
isLoading | boolean | Loading state from the upstream query. |
useSiteConsumptionChartData
TanStack Query hook that fetches site consumption tail-log samples and returns a <LineChartCard>-ready ChartCardData payload. Applies site-powermeter defaults and converts watts to MW.
import { useSiteConsumptionChartData } from '@tetherto/mdk-react-adapter'Options
Same UseConsumptionChartDataParams as useSiteConsumption.
Returns
A TanStack UseQueryResult whose data field is ChartCardData — the object accepted by <LineChartCard data={...} />.
Example
import { useSiteConsumptionChartData } from '@tetherto/mdk-react-adapter'
import { LineChartCard } from '@tetherto/mdk-react-devkit/foundation'
function ConsumptionChart() {
const { data, isLoading } = useSiteConsumptionChartData({ timeline: '5m' })
return <LineChartCard data={data} isLoading={isLoading} />
}useSiteContainerCapacity
Reads the aggregated nominal miner capacity across all site containers from the 5-minute tail-log aggregate, giving the denominator shown in the header (e.g. the "2,188" in "MOS / 2,188").
import { useSiteContainerCapacity } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
refetchInterval | Optional | number | 300000 | Polling interval in ms. Pass 0 to disable. |
Returns
| Member | Type | Description |
|---|---|---|
value | number | undefined | Total nominal miner slots across all site containers; undefined while loading. |
isLoading | boolean | Loading state. |
useSiteEfficiency
Derives site efficiency in W/TH/s by dividing the latest site consumption by the latest hashrate. Both upstream hooks are called internally; pass powerW to override the consumption source (e.g. to use a power-meter reading instead).
import { useSiteEfficiency } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
timeline | Required | string | none | Required. Stat key suffix forwarded to both upstream hooks. |
start | Optional | number | none | Lower time bound (ms epoch). |
end | Optional | number | none | Upper time bound (ms epoch). |
tag | Optional | string | none | Thing tag override forwarded to the consumption hook. |
powerAttribute | Optional | string | none | Aggregate field override forwarded to the consumption hook. |
refetchInterval | Optional | number | none | Polling interval in ms forwarded to both upstream hooks. |
powerW | Optional | number | none | When provided, skips the internal useSiteConsumption call and uses this watts value as the numerator directly. Pair with useSitePowerMeter().valueW for meter-level efficiency. |
Returns
| Member | Type | Description |
|---|---|---|
valueWthS | number | undefined | Watts per TH/s; undefined while loading or when hashrate is zero. |
isLoading | boolean | true while either upstream hook is loading. |
useSiteHashrate
TanStack Query hook that reads the latest aggregate hashrate from the site tail-log and returns both a PH/s display value and the raw MH/s backend value.
import { useSiteHashrate } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
timeline | Required | string | none | Required. Stat key suffix, e.g. '5m'. |
start | Optional | number | none | Lower time bound (ms epoch). |
end | Optional | number | none | Upper time bound (ms epoch). |
refetchInterval | Optional | number | 60000 | Polling interval in ms. Pass 0 to disable. |
Returns
| Member | Type | Description |
|---|---|---|
valuePhs | number | undefined | Latest aggregate value in PH/s; undefined while loading or with no data. |
valueMhs | number | undefined | Latest aggregate value in MH/s (raw backend unit). |
isLoading | boolean | Loading state. |
useSiteMinerCounts
Polls the device list for miners and aggregates them into online / offline / error counts. Uses the last.status field on each device row.
import { useSiteMinerCounts } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
refetchInterval | Optional | number | none | Polling interval in ms. |
Returns
| Member | Type | Description |
|---|---|---|
total | number | Total miner device count. |
online | number | Miners with status online or on. |
offline | number | Miners not online and not in error. |
error | number | Miners with status error or alert. |
useSiteMinerStats
Polls the stat-rtd realtime aggregate for the live miner stat summary — the MOS total, online/offline breakdown, and active pool worker count shown in the header.
import { useSiteMinerStats } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
refetchInterval | Optional | number | none | Polling interval in ms. |
Returns
| Member | Type | Description |
|---|---|---|
mosTotal | number | Count of miners that reported hashrate in the last minute (the MOS denominator). |
online | number | Miners online or with minor errors (green column). |
offline | number | Offline or sleeping miners. |
notMining | number | Miners not currently mining. |
isLoading | boolean | Loading state. |
useSitePowerMeter
Reads the current power-meter reading in watts from the site-level device tagged t-powermeter. Returns a MW conversion alongside the raw watts value.
import { useSitePowerMeter } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
tag | Optional | string | 't-powermeter' | Device tag to filter by. |
refetchInterval | Optional | number | none | Polling interval in ms. |
Returns
| Member | Type | Description |
|---|---|---|
valueMw | number | undefined | Latest power-meter reading in MW; undefined when no device or no data. |
valueW | number | undefined | Raw value in watts. |
isLoading | boolean | Loading state. |
Pool data
usePoolRows
TanStack Query hook that fetches per-pool stats and transforms them into PoolRow[] objects shaped for the pool manager table. Hashrate is normalised from raw H/s to PH/s.
import { usePoolRows } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
refetchInterval | Optional | number | 120000 | Polling interval in ms. Pass 0 to disable. |
Returns
A TanStack UseQueryResult whose data is PoolRow[].
| Member | Type | Description |
|---|---|---|
id | string | Stable React key derived from poolType. |
name | string | Display name in Moria style — minerpool-{poolType}-shelf-0. |
poolType | string | Raw pool type string, e.g. 'f2pool', 'ocean'. |
revenue24hBtc | number | undefined | 24 h revenue in BTC if reported. |
hashrateHs | number | undefined | Hashrate in raw H/s. |
hashratePhsDisplay | number | undefined | Hashrate in PH/s for display. |
details | PoolDetail[] | Array of label/value pairs for the expanded row. |
usePoolStats
TanStack Query hook that fetches per-pool stats and aggregates them into site-level totals — total workers, online workers, mismatch count, and aggregate hashrate in PH/s.
import { usePoolStats } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
refetchInterval | Optional | number | 120000 | Polling interval in ms. Pass 0 to disable. |
Returns
| Member | Type | Description |
|---|---|---|
total | number | Total miners reported across all configured pools. |
online | number | Pool-reported active workers. |
mismatch | number | Difference between configured and active workers. |
hashratePhs | number | undefined | Aggregate pool hashrate in PH/s; undefined while loading or with no data. |
hashrateHs | number | undefined | Aggregate pool hashrate in raw H/s. |
isLoading | boolean | Loading state. |
Dashboard
useDashboardDateRange
Owns the single source of truth for the dashboard's date-range picker: a start / end ms-epoch pair with setters and a reset helper that restores the default 24-hour window.
import { useDashboardDateRange } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
initial | Optional | { start: number; end: number } | last 24 h | Initial date range. Defaults to the last 24 hours ending now. |
Returns
| Member | Type | Description |
|---|---|---|
start | number | Lower bound (ms epoch). |
end | number | Upper bound (ms epoch). |
setRange | function | Replace the current range. |
reset | function | Convenience: restore the default 24-hour window ending now. |
Example
import { useDashboardDateRange } from '@tetherto/mdk-react-adapter'
import { DateRangePicker } from '@tetherto/mdk-react-devkit/foundation'
function DashboardHeader() {
const { start, end, setRange, reset } = useDashboardDateRange()
return <DateRangePicker start={start} end={end} onChange={setRange} onReset={reset} />
}useDashboardExport
Reads cached query data for hashrate, consumption, incidents, and pool stats from the TanStack Query client and exposes exportCsv, exportJson, and a unified export(format) callable. Does not trigger refetches — the export represents exactly what is currently displayed.
import { useDashboardExport } from '@tetherto/mdk-react-adapter'Options
Accepts a UseDashboardExportOptions object containing DashboardQueryRange fields (timeline, start, end, tag) needed to reconstruct the query keys.
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
timeline | Required | string | none | Required. Stat key suffix used to locate the cached chart queries. |
start | Optional | number | none | Lower time bound (ms epoch). |
end | Optional | number | none | Upper time bound (ms epoch). |
tag | Optional | string | none | Thing tag override. |
Returns
| Member | Type | Description |
|---|---|---|
exportCsv | function | Triggers a browser file-download of the dashboard data as CSV. |
exportJson | function | Triggers a browser file-download as JSON. |
export | function | Unified callable — export('csv') or export('json'). |
useDashboardTimeRange
Tiny piece of scoped state for the dashboard's timeline selector. Owns the current timeline string and the canonical option list. Chart hooks (useHashrateChartData, useSiteConsumptionChartData, etc.) consume timeline as a prop.
import { useDashboardTimeRange } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
initial | Optional | string | '5m' | Initial timeline value. |
options | Optional | TimelineOption[] | canonical list | Custom option list; defaults to the canonical set from getTimelineOptions. |
Returns
| Member | Type | Description |
|---|---|---|
timeline | string | Currently selected timeline string, e.g. '5m'. |
options | TimelineOption[] | Available options, ready for <TimelineSelector options={...} />. |
setTimeline | function | Setter for the current timeline. |
Example
import { useDashboardTimeRange, useSiteHashrate } from '@tetherto/mdk-react-adapter'
import { TimelineSelector } from '@tetherto/mdk-react-devkit/foundation'
function DashboardControls() {
const { timeline, options, setTimeline } = useDashboardTimeRange()
const { valuePhs } = useSiteHashrate({ timeline })
return (
<>
<TimelineSelector options={options} value={timeline} onChange={setTimeline} />
<span>{valuePhs?.toFixed(2)} PH/s</span>
</>
)
}Chart data
useConsumptionChartData
TanStack Query hook returning raw consumption tail-log samples. Most dashboards should use the higher-level useSiteConsumptionChartData, which wraps this hook and returns a <LineChartCard>-ready payload.
import { useConsumptionChartData } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
timeline | Required | string | none | Required. Stat key suffix, e.g. '1m', '5m'. |
start | Optional | number | none | Lower time bound (ms epoch). |
end | Optional | number | none | Upper time bound (ms epoch). |
tag | Optional | string | 't-miner' | Thing tag. Use 't-powermeter' for transformer-level consumption. |
powerAttribute | Optional | string | 'power_w_sum_aggr' | Aggregate field name to read. |
refetchInterval | Optional | number | 60000 | Polling interval in ms. Pass 0 to disable. |
Returns
A TanStack UseQueryResult<TailLogEntry[][], Error> — raw tail-log matrix before projection.
useHashrateChartData
TanStack Query hook combining the site tail-log hashrate series with the per-pool hashrate history into a single ChartCardData payload for <LineChartCard />. Handles unit conversion from both MH/s (tail-log) and raw H/s (pool API) into PH/s for display.
import { useHashrateChartData } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
timeline | Required | string | none | Required. Stat key suffix, e.g. '5m'. |
start | Optional | number | none | Lower time bound (ms epoch). |
end | Optional | number | none | Upper time bound (ms epoch). |
refetchInterval | Optional | number | none | Polling interval in ms. |
Returns
A TanStack UseQueryResult whose data is ChartCardData — ready for <LineChartCard data={...} />.
usePowerModeTimelineData
TanStack Query hook returning power-mode and status samples shaped for <PowerModeTimelineChart data={...} />.
import { usePowerModeTimelineData } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
timeline | Required | string | none | Required. Stat key suffix, e.g. '1m'. |
start | Optional | number | none | Lower time bound (ms epoch). |
end | Optional | number | none | Upper time bound (ms epoch). |
tag | Optional | string | none | Thing tag override. |
refetchInterval | Optional | number | none | Polling interval in ms. |
Returns
A TanStack UseQueryResult<PowerModeTimelineEntry[], Error>.
Auth and token
useAuthToken
Reads ?authToken=… from window.location.search, persists it into the headless authStore, and strips the parameter from the URL via history.replaceState so the token never lingers in the address bar. Router-agnostic by design. Returns the current token from the store so callers can gate navigation on authentication.
import { useAuthToken } from '@tetherto/mdk-react-adapter'Returns
| Type | Description |
|---|---|
string | null | Current auth token from the authStore, or null when no token is present. |
Example
import { useAuthToken } from '@tetherto/mdk-react-adapter'
import { Navigate, Outlet } from 'react-router-dom'
function ProtectedRoute() {
const token = useAuthToken()
return token ? <Outlet /> : <Navigate to="/signin" replace />
}useTokenPolling
Polls the backend token-refresh endpoint at a fixed interval (default 250 s) and writes the new token back into the authStore. Fires the optional onSessionEnded callback on a 401 or 500, which MDK UI Shell uses to redirect back to /signin.
import { useTokenPolling } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
intervalMs | Optional | number | 250000 | Polling interval in ms. Backend token TTL defaults to 5 min (300 s); 250 s gives comfortable headroom. |
enabled | Optional | boolean | true when token present | Pass false to pause polling (e.g. on the sign-in page). |
onSessionEnded | Optional | function | none | Called on 401 or 500; use to navigate to the sign-in page. |
Example
import { useTokenPolling } from '@tetherto/mdk-react-adapter'
import { useNavigate } from 'react-router-dom'
function App() {
const navigate = useNavigate()
useTokenPolling({ onSessionEnded: () => navigate('/signin') })
return <Outlet />
}Incidents
useActiveIncidents
TanStack Query hook returning the list of currently-firing alerts, shaped for <ActiveIncidentsCard items={...} />. Queries devices that have a non-null last.alerts field and maps them via the mapDevicesToIncidents utility.
import { useActiveIncidents } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
refetchInterval | Optional | number | 20000 | Polling interval in ms. Matches Moria's production cadence. Pass 0 to disable. |
formatDate | Optional | function | ISO string | Date formatter applied to the row body timestamp. |
Returns
A TanStack UseQueryResult<IncidentRow[], Error>.
Example
import { useActiveIncidents } from '@tetherto/mdk-react-adapter'
import { ActiveIncidentsCard } from '@tetherto/mdk-react-devkit/foundation'
function IncidentsFeed() {
const { data: items = [], isLoading } = useActiveIncidents({ refetchInterval: 20_000 })
return <ActiveIncidentsCard items={items} isLoading={isLoading} />
}Alerts
Data hooks that back the full alerts surface: useCurrentAlertDevices feeds the <CurrentAlerts> / <Alerts> table with raw device rows; useHistoricalAlerts fetches and shapes the historical-alerts log for <HistoricalAlerts>. Both require <MdkProvider> in the tree.
See also useActiveIncidents in the Incidents section, which hits the same list-things endpoint but maps results to the dashboard card's IncidentRow[] shape.
useCurrentAlertDevices
TanStack Query hook returning the raw devices that currently carry one or more alerts, as the nested ListThingsDevice[][] envelope the devkit <Alerts> / <CurrentAlerts> table expects. Unlike useActiveIncidents, this hook leaves the payload unshaped so the table can derive its own filter tokens and per-row status. Both hit /auth/list-things; this hook requests a wider field set and uses a distinct cache key.
import { useCurrentAlertDevices } from '@tetherto/mdk-react-adapter'
import type { UseCurrentAlertDevicesOptions } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
refetchInterval | Optional | number | 20000 | Polling interval in ms. Matches the default production polling cadence. Pass 0 to disable. |
filterTags | Optional | string[] | none | Alerts search chips. Folded into the backend list-things selector — triggers a re-fetch that narrows the dataset server-side. |
Returns
A TanStack UseQueryResult<ListThingsDevice[][], Error>.
Example
import { useCurrentAlertDevices } from '@tetherto/mdk-react-adapter'
import { CurrentAlerts } from '@tetherto/mdk-react-devkit/foundation'
function AlertsTable({ filterTags }) {
const { data, isLoading } = useCurrentAlertDevices({ filterTags })
return <CurrentAlerts devices={data ?? []} isLoading={isLoading} filterTags={filterTags} />
}useHistoricalAlerts
TanStack Query hook for the historical-alerts log. Fetches the [start, end] range as successive history-log windows, merges results by uuid, and shapes rows for the devkit <HistoricalAlerts> table via mapHistoryLogToAlerts. Range changes abort the in-flight chunk loop through the query's AbortSignal.
By default the entire range is fetched in a single request. Pass a smaller intervalMs (e.g. ONE_DAY_MS) only for wide ranges where the backend would otherwise cap or slow a single query — that splits the fetch into sequential 24-hour windows.
import { useHistoricalAlerts } from '@tetherto/mdk-react-adapter'
import type { UseHistoricalAlertsOptions } from '@tetherto/mdk-react-adapter'Options
| Option | Status | Type | Default | Description |
|---|---|---|---|---|
start | Required | number | none | Lower bound of the look-back window (ms epoch). |
end | Required | number | none | Upper bound of the look-back window (ms epoch). |
intervalMs | Optional | number | whole range | Per-request window size in ms. Defaults to the whole range in one request; set a smaller value to chunk wide ranges into sequential fetches. |
enabled | Optional | boolean | true when range valid | Pass false to force-disable the query. Defaults to enabled when start and end are finite and end > start. |
Returns
A TanStack UseQueryResult<HistoricalAlert[], Error>.
Example
import { useHistoricalAlerts } from '@tetherto/mdk-react-adapter'
import { HistoricalAlerts } from '@tetherto/mdk-react-devkit/foundation'
function AlertHistory({ start, end, filterTags, localFilters, onDateRangeChange }) {
const { data: alerts = [], isLoading } = useHistoricalAlerts({ start, end })
return (
<HistoricalAlerts
alerts={alerts}
isLoading={isLoading}
filterTags={filterTags}
localFilters={localFilters}
dateRange={{ start, end }}
onDateRangeChange={onDateRangeChange}
/>
)
}Behaviour notes
- Wide ranges fan out into many requests. The MDK UI Shell page caps the default window at 14 days; pass a tighter
[start, end]or setintervalMsto limit per-request payload size. - The hook removes duplicate rows by
uuidafter merging chunks, before passing them tomapHistoryLogToAlerts.