MDK Logo
ReferenceUI KitReactUI Kit foundationComponentsDashboards

CostContent

Renders the data-driven portion of the Cost page in a 2x2 Mosaic grid: - (1,1) Production Cost / Price - (1,2) Avg All-in Cost - (2,1) Operations vs Energy C…

Renders the data-driven portion of the Cost page in a 2x2 Mosaic grid:

  • (1,1) Production Cost / Price - (1,2) Avg All-in Cost - (2,1) Operations vs Energy Cost - (2,2) Headline metric tiles (stacked)

Exported alongside Cost so consumers who want to embed the cost rendering inside their own page chrome (custom header, layout, navigation) can mount CostContent directly without the default title / "Set Monthly Cost" link.

import { CostContent } from "@tetherto/mdk-react-devkit";
PropStatusTypeDefaultDescription
metricsRequiredCostSummaryDisplayMetrics | null
costLogRequiredreadonly CostTimeSeriesEntry[]
btcPriceLogRequiredreadonly BtcPriceTimeSeriesEntry[]
totalsRequiredCostSummaryMonetaryTotals | null
isLoadingOptionalboolean | undefined
errorOptionalunknown
dateRangeRequiredFinancialDateRange | null
avgAllInCostDataOptionalreadonly AvgAllInCostDataPoint[] | undefinedOptional revenue/cost time-series for the Avg All-in Cost panel.

Usage

Composite financial reporting page for a single mining site. Renders a page header, a period selector slot, and a 2×2 grid of charts and metric tiles driven by the cost-summary view model.

Notes

  • Use buildCostSummaryViewModel to transform the raw API response into the props this component expects.
  • avgAllInCostData comes from a separate endpoint (useAvgAllInPowerCostData in the OSS app) — omit it to hide the Avg All-in Cost panel.
  • For a custom page layout (different header, navigation), mount CostContent directly instead and supply your own chrome.
  • Multi-site aggregation is out of scope for this component; mount one Cost per site and compose them yourself.

Examples

import { AvgAllInCostChart } from '@tetherto/mdk-react-devkit'export const AvgAllInCostChartExample = () => (  <div className="mdk-example-row">    <AvgAllInCostChart dateRange={null} isLoading={false} />  </div>)
import { CostCharts } from '@tetherto/mdk-react-devkit'export const CostChartsExample = () => (  <div className="mdk-example-row">    <CostCharts costLog={[]} btcPriceLog={[]} totals={null} dateRange={null} isLoading={false} />  </div>)
import { CostContent } from '@tetherto/mdk-react-devkit'export const CostContentExample = () => (  <div className="mdk-example-row">    <CostContent      metrics={null}      costLog={[]}      btcPriceLog={[]}      totals={null}      dateRange={null}      isLoading={false}    />  </div>)
import { CostMetrics } from '@tetherto/mdk-react-devkit'export const CostMetricsExample = () => (  <div className="mdk-example-row">    <CostMetrics metrics={{ allIn: 42.5, energy: 38.0, operations: 4.5 } as never} />  </div>)
/** * Runnable example for Cost. * All imports must come from "@tetherto/mdk-react-devkit/domain". */import {  type AvgAllInCostDataPoint,  buildCostSummaryViewModel,  Cost,  type CostSummaryLogEntry,  type CostSummaryResponse,  type FinancialDateRange,  PERIOD,  TimeframeControls,  type TimeframeControlsOnRangeChange,} from '@tetherto/mdk-react-devkit/domain'import { endOfMonth } from 'date-fns/endOfMonth'import { startOfMonth } from 'date-fns/startOfMonth'import { useMemo, useState } from 'react'const buildInitialDateRange = (): FinancialDateRange => ({  start: startOfMonth(new Date('2025-01-01T00:00:00.000Z')).getTime(),  end: endOfMonth(new Date('2025-12-31T00:00:00.000Z')).getTime(),  period: PERIOD.MONTHLY,})const monthTs = (month: number): number => Date.UTC(2025, month - 1, 15, 12)const buildLogEntry = (input: {  month: number  consumptionMWh: number  energyCostsUSD: number  operationalCostsUSD: number  btcPrice: number}): CostSummaryLogEntry => {  const totalCostsUSD = input.energyCostsUSD + input.operationalCostsUSD  return {    ts: monthTs(input.month),    consumptionMWh: input.consumptionMWh,    energyCostsUSD: input.energyCostsUSD,    operationalCostsUSD: input.operationalCostsUSD,    totalCostsUSD,    allInCostPerMWh: totalCostsUSD / input.consumptionMWh,    energyCostPerMWh: input.energyCostsUSD / input.consumptionMWh,    btcPrice: input.btcPrice,  }}const MOCK_LOG: CostSummaryLogEntry[] = [  {    month: 1,    consumptionMWh: 1_180,    energyCostsUSD: 14_200,    operationalCostsUSD: 7_100,    btcPrice: 64_500,  },  {    month: 2,    consumptionMWh: 1_320,    energyCostsUSD: 15_900,    operationalCostsUSD: 7_950,    btcPrice: 67_800,  },  {    month: 3,    consumptionMWh: 1_410,    energyCostsUSD: 17_400,    operationalCostsUSD: 8_600,    btcPrice: 71_200,  },  {    month: 4,    consumptionMWh: 1_290,    energyCostsUSD: 15_500,    operationalCostsUSD: 7_650,    btcPrice: 65_900,  },  {    month: 5,    consumptionMWh: 1_360,    energyCostsUSD: 16_800,    operationalCostsUSD: 8_200,    btcPrice: 68_400,  },  {    month: 6,    consumptionMWh: 1_470,    energyCostsUSD: 18_500,    operationalCostsUSD: 9_100,    btcPrice: 72_500,  },].map(buildLogEntry)const MOCK_SUMMARY: CostSummaryResponse = {  log: MOCK_LOG,  summary: {    totalEnergyCostsUSD: MOCK_LOG.reduce((s, e) => s + e.energyCostsUSD, 0),    totalOperationalCostsUSD: MOCK_LOG.reduce((s, e) => s + e.operationalCostsUSD, 0),    totalCostsUSD: MOCK_LOG.reduce((s, e) => s + e.totalCostsUSD, 0),    totalConsumptionMWh: MOCK_LOG.reduce((s, e) => s + e.consumptionMWh, 0),    avgAllInCostPerMWh:      MOCK_LOG.reduce((s, e) => s + e.totalCostsUSD, 0) /      MOCK_LOG.reduce((s, e) => s + e.consumptionMWh, 0),    avgEnergyCostPerMWh:      MOCK_LOG.reduce((s, e) => s + e.energyCostsUSD, 0) /      MOCK_LOG.reduce((s, e) => s + e.consumptionMWh, 0),    avgBtcPrice: MOCK_LOG.reduce((s, e) => s + e.btcPrice, 0) / MOCK_LOG.length,  },}const MOCK_AVG_ALL_IN: AvgAllInCostDataPoint[] = MOCK_LOG.map((e) => ({  ts: e.ts,  revenueUSDPerMWh: (e.allInCostPerMWh ?? 0) * 1.28,  costUSDPerMWh: e.allInCostPerMWh ?? 0,}))export const CostExample = () => {  const [dateRange, setDateRange] = useState<FinancialDateRange>(buildInitialDateRange)  const viewModel = useMemo(() => buildCostSummaryViewModel({ data: MOCK_SUMMARY }), [])  const handleRangeChange: TimeframeControlsOnRangeChange = (range, options) => {    setDateRange({      start: range[0].getTime(),      end: range[1].getTime(),      period: (options.period ?? dateRange.period) as FinancialDateRange['period'],    })  }  return (    <Cost      metrics={viewModel.metrics}      costLog={viewModel.costLog}      btcPriceLog={viewModel.btcPriceLog}      totals={viewModel.totals}      dateRange={dateRange}      avgAllInCostData={MOCK_AVG_ALL_IN}      controls={        <TimeframeControls          isMonthSelectVisible          isWeekSelectVisible={false}          dateRange={{ start: dateRange.start, end: dateRange.end }}          onRangeChange={handleRangeChange}        />      }    />  )}
import { OperationsEnergyChart } from '@tetherto/mdk-react-devkit'export const OperationsEnergyChartExample = () => (  <div className="mdk-example-row">    <OperationsEnergyChart totals={null} isLoading={false} />  </div>)
import { ProductionCostChart } from '@tetherto/mdk-react-devkit'export const ProductionCostChartExample = () => (  <div className="mdk-example-row">    <ProductionCostChart costLog={[]} btcPriceLog={[]} dateRange={null} isLoading={false} />  </div>)