MDK Logo

Utilities

Helper functions exported by @tetherto/mdk-core-ui (formatting, validation, conversions) and @tetherto/mdk-foundation-ui (settings persistence)

This page documents helper functions exported by the MDK packages.

  • Core utilities ships 15 utility modules with functions for formatting, dates, validation, conversions, class-name merging, and more
  • Foundation utilities currently ships a single public utility module (settings-utils) for parsing, validating, and exporting settings JSON

Core utilities

Helper functions exported by @tetherto/mdk-core-ui for formatting, dates, validation, conversions, and class-name merging.

Prerequisites

Import

@tetherto/mdk-core-ui
import {
  formatNumber,
  formatHashrate,
  formatDate,
  formatRelativeTime,
  cn,
  isEmpty,
  isValidEmail,
} from '@tetherto/mdk-core-ui'

Formatting utilities

formatNumber

@tetherto/mdk-core-ui

Format numbers with locale formatting and configurable options.

import { formatNumber, FALLBACK } from '@tetherto/mdk-core-ui'

formatNumber(1234.567)                          // "1,234.57"
formatNumber(null)                              // "-"
formatNumber(1234, { minimumFractionDigits: 2 }) // "1,234.00"
formatNumber(undefined, {}, 'N/A')              // "N/A"

formatHashrate

@tetherto/mdk-core-ui

Format hashrate values with rounding.

import { formatHashrate } from '@tetherto/mdk-core-ui'

formatHashrate(150.456)  // "150.46"
formatHashrate(null)     // "-"

formatCurrency

@tetherto/mdk-core-ui

Format currency values.

import { formatCurrency } from '@tetherto/mdk-core-ui'

formatCurrency(1234.56, 'USD')      // "$1,234.56"
formatCurrency(0.00012345, 'BTC')   // "₿0.00012345"

getPercentFormattedNumber

@tetherto/mdk-core-ui

Format numbers as percentages.

import { getPercentFormattedNumber } from '@tetherto/mdk-core-ui'

getPercentFormattedNumber(0.75)      // "75%"
getPercentFormattedNumber(0.1234, 1) // "12.3%"

formatValueUnit

@tetherto/mdk-core-ui

Format value-unit objects.

import { formatValueUnit } from '@tetherto/mdk-core-ui'

formatValueUnit(150, 'TH/s')  // "150 TH/s"

Date utilities

formatDate

@tetherto/mdk-core-ui

Format dates with customizable patterns.

import { formatDate } from '@tetherto/mdk-core-ui'

formatDate(new Date())                              // "Jan 15, 2025"
formatDate(1705334400000, { format: 'yyyy-MM-dd' }) // "2025-01-15"

formatRelativeTime

@tetherto/mdk-core-ui

Format dates as relative time strings.

import { formatRelativeTime } from '@tetherto/mdk-core-ui'

formatRelativeTime(new Date(Date.now() - 3600000))  // "1h ago"
formatRelativeTime(new Date(Date.now() - 86400000)) // "1d ago"

formatChartDate

@tetherto/mdk-core-ui

Format timestamps for chart display.

import { formatChartDate } from '@tetherto/mdk-core-ui'

formatChartDate(1705334400)        // "Jan 15"
formatChartDate(1705334400, true)  // "Jan 15, 2025"

isValidTimestamp

@tetherto/mdk-core-ui

Check if a timestamp is valid.

import { isValidTimestamp } from '@tetherto/mdk-core-ui'

isValidTimestamp(1705334400000)  // true
isValidTimestamp('invalid')      // false

parseMonthLabelToDate

@tetherto/mdk-core-ui

Parse month labels to Date objects.

import { parseMonthLabelToDate } from '@tetherto/mdk-core-ui'

parseMonthLabelToDate('01-26')    // Date(2026, 0, 1)
parseMonthLabelToDate('03-2025')  // Date(2025, 2, 1)

getPastDateFromDate

@tetherto/mdk-core-ui

Get a date in the past.

import { getPastDateFromDate } from '@tetherto/mdk-core-ui'

getPastDateFromDate({ dateTs: Date.now(), days: 7 })  // 7 days ago

Validation utilities

isEmpty

@tetherto/mdk-core-ui

Check if a value is empty.

import { isEmpty } from '@tetherto/mdk-core-ui'

isEmpty(null)       // true
isEmpty('')         // true
isEmpty([])         // true
isEmpty({})         // true
isEmpty('hello')    // false
isEmpty([1, 2, 3])  // false

isValidEmail

@tetherto/mdk-core-ui

Validate email addresses.

import { isValidEmail } from '@tetherto/mdk-core-ui'

isValidEmail('user@example.com')  // true
isValidEmail('invalid')           // false

isValidUrl

@tetherto/mdk-core-ui

Validate URLs.

import { isValidUrl } from '@tetherto/mdk-core-ui'

isValidUrl('https://example.com')  // true
isValidUrl('not-a-url')            // false

isNil

@tetherto/mdk-core-ui

Check if value is null or undefined.

import { isNil } from '@tetherto/mdk-core-ui'

isNil(null)       // true
isNil(undefined)  // true
isNil(0)          // false
isNil('')         // false

isPlainObject

@tetherto/mdk-core-ui

Check if value is a plain object.

import { isPlainObject } from '@tetherto/mdk-core-ui'

isPlainObject({})           // true
isPlainObject({ a: 1 })     // true
isPlainObject([])           // false
isPlainObject(new Date())   // false

Class name utilities

cn

@tetherto/mdk-core-ui

Merge class names using clsx and tailwind-merge.

import { cn } from '@tetherto/mdk-core-ui'

cn('px-4', 'py-2')                    // "px-4 py-2"
cn('text-red', isError && 'bg-red')   // conditional classes
cn('p-4', { 'hidden': !visible })     // object syntax

Conversion utilities

toMW / toMWh

@tetherto/mdk-core-ui

Convert watts to megawatts.

import { toMW, toMWh } from '@tetherto/mdk-core-ui'

toMW(1000000)   // 1
toMWh(1000000)  // 1

toPHS

@tetherto/mdk-core-ui

Convert raw hashrate to PH/s.

import { toPHS } from '@tetherto/mdk-core-ui'

toPHS(1000000000000000)  // 1

convertMpaToBar

@tetherto/mdk-core-ui

Convert pressure units.

import { convertMpaToBar } from '@tetherto/mdk-core-ui'

convertMpaToBar(0.1)  // 1

unitToKilo

@tetherto/mdk-core-ui

Convert to kilo units.

import { unitToKilo } from '@tetherto/mdk-core-ui'

unitToKilo(1000)  // 1

Number utilities

percentage

@tetherto/mdk-core-ui

Calculate percentage.

import { percentage } from '@tetherto/mdk-core-ui'

percentage(25, 100)  // 25
percentage(1, 4)     // 25

getPercentChange

@tetherto/mdk-core-ui

Calculate percentage change.

import { getPercentChange } from '@tetherto/mdk-core-ui'

getPercentChange(110, 100)  // 10
getPercentChange(90, 100)   // -10

convertUnits

@tetherto/mdk-core-ui

Convert between SI-prefix units.

import { convertUnits } from '@tetherto/mdk-core-ui'

convertUnits(1, 'k', 'M')           // 0.001
convertUnits(1000, 'decimal', 'k')  // 1

safeNumber

@tetherto/mdk-core-ui

Safely convert to number.

import { safeNumber } from '@tetherto/mdk-core-ui'

safeNumber('123')      // 123
safeNumber('invalid')  // 0
safeNumber(null)       // 0

String utilities

toTitleCase

@tetherto/mdk-core-ui

Convert string to Title Case.

import { toTitleCase } from '@tetherto/mdk-core-ui'

toTitleCase('hello world')  // "Hello World"

formatMacAddress

@tetherto/mdk-core-ui

Format MAC addresses.

import { formatMacAddress } from '@tetherto/mdk-core-ui'

formatMacAddress('aa:bb:cc:dd:ee:ff')  // "AA:BB:CC:DD:EE:FF"

safeString

@tetherto/mdk-core-ui

Safely convert to string.

import { safeString } from '@tetherto/mdk-core-ui'

safeString(123)    // "123"
safeString(null)   // ""

Time utilities

secondsToMs

@tetherto/mdk-core-ui

Convert seconds to milliseconds.

import { secondsToMs } from '@tetherto/mdk-core-ui'

secondsToMs(60)  // 60000

breakTimeIntoIntervals

@tetherto/mdk-core-ui

Split time range into intervals.

import { breakTimeIntoIntervals } from '@tetherto/mdk-core-ui'

breakTimeIntoIntervals(start, end, 3600000)  // Array of 1-hour intervals

timeRangeWalker

@tetherto/mdk-core-ui

Generator for iterating through time ranges.

import { timeRangeWalker } from '@tetherto/mdk-core-ui'

for (const interval of timeRangeWalker(start, end, duration)) {
  // Process each interval
}

Color utilities

hexToRgba

@tetherto/mdk-core-ui

Convert hex color to rgba.

import { hexToRgba } from '@tetherto/mdk-core-ui'

hexToRgba('#72F59E', 0.5)  // "rgba(114, 245, 158, 0.5)"

Array utilities

getNestedValue

@tetherto/mdk-core-ui

Get nested value by dot-path.

import { getNestedValue } from '@tetherto/mdk-core-ui'

getNestedValue({ a: { b: 1 } }, 'a.b')  // 1

getWeightedAverage

@tetherto/mdk-core-ui

Calculate weighted average.

import { getWeightedAverage } from '@tetherto/mdk-core-ui'

getWeightedAverage(items, 'value', 'weight')

circularArrayAccess

@tetherto/mdk-core-ui

Create infinite cycling generator.

import { circularArrayAccess } from '@tetherto/mdk-core-ui'

const colors = circularArrayAccess(['red', 'green', 'blue'])
colors.next().value  // 'red'
colors.next().value  // 'green'
colors.next().value  // 'blue'
colors.next().value  // 'red' (cycles)

Foundation utilities

Helpers exported by @tetherto/mdk-foundation-ui for filtering, formatting, validating, parsing, and exporting settings data.

Prerequisites

Import

@tetherto/mdk-foundation-ui
import {
  filterUsers,
  formatRoleLabel,
  formatLastActive,
  validateSettingsJson,
  parseSettingsFile,
  exportSettingsToFile,
} from '@tetherto/mdk-foundation-ui'

Settings utilities

filterUsers

@tetherto/mdk-foundation-ui

Filter a SettingsUser[] list by email substring (case-insensitive) and exact role match. Used by the user-management table search.

import { filterUsers } from '@tetherto/mdk-foundation-ui'

filterUsers({
  users,
  email: 'alice',   // partial, case-insensitive match on user.email
  role: 'admin',    // exact match on user.role; pass null to skip
})
ParameterTypeDescription
usersSettingsUser[]Source list
emailstring | null | undefinedSubstring filter on email (case-insensitive). Skipped when falsy.
rolestring | null | undefinedExact role match. Skipped when falsy.

formatRoleLabel

@tetherto/mdk-foundation-ui

Convert a snake case role identifier to a human-readable Title Case label.

import { formatRoleLabel } from '@tetherto/mdk-foundation-ui'

formatRoleLabel('site_manager')           // "Site Manager"
formatRoleLabel('reporting_tool_manager') // "Reporting Tool Manager"
formatRoleLabel('admin')                  // "Admin"

formatLastActive

@tetherto/mdk-foundation-ui

Format a timestamp string as MM/DD/YYYY - HH:MM. Returns '-' when the input is missing or invalid.

import { formatLastActive } from '@tetherto/mdk-foundation-ui'

formatLastActive('2025-01-15T14:30:00Z')  // "01/15/2025 - 14:30"
formatLastActive(undefined)               // "-"
formatLastActive('not-a-date')            // "-"

validateSettingsJson

@tetherto/mdk-foundation-ui

Type-guard that checks whether an unknown value is a valid SettingsExportData. Returns true if the value is an object that contains at least one of headerControls, featureFlags, or timestamp.

import { validateSettingsJson } from '@tetherto/mdk-foundation-ui'

if (validateSettingsJson(parsed)) {
  // parsed is now narrowed to SettingsExportData
}

parseSettingsFile

@tetherto/mdk-foundation-ui

Read a File containing settings JSON, validate it, and resolve to SettingsExportData. Rejects on invalid JSON, an invalid format, or a file read error.

import { parseSettingsFile } from '@tetherto/mdk-foundation-ui'

try {
  const settings = await parseSettingsFile(file)
  applySettings(settings)
} catch (err) {
  notifyError('Could not import settings', err.message)
}
ThrowsReason
Invalid settings file format. Please ensure the file is a valid settings export.The JSON parsed but didn't match the SettingsExportData shape.
Failed to parse JSON file. Please ensure the file is valid JSON.The file contents weren't valid JSON.
Failed to read file.The browser couldn't read the file.

exportSettingsToFile

@tetherto/mdk-foundation-ui

Serialize SettingsExportData to JSON, package it as a downloadable Blob, and trigger a browser download. Returns the generated filename (e.g., miningos-settings-2025-01-15T14-30-00-000Z.json).

import { exportSettingsToFile } from '@tetherto/mdk-foundation-ui'

const filename = exportSettingsToFile({
  headerControls: { poolMiners: true, consumption: false },
  featureFlags: { betaCharts: true },
  timestamp: new Date().toISOString(),
  version: '1.0.0',
})

On this page