@ghostchain1/utils
v0.1.0
Published
Shared utility functions for GhostChain applications
Readme
@ghostchain1/utils
Shared utility functions for all GhostChain applications. Consolidates common patterns to eliminate code duplication across the monorepo.
Features
- Class Name Utility (
cn): Intelligent class name merging with Tailwind conflict resolution - Hash & Address Formatting: Truncate hashes, format addresses
- Time & Date Formatting: Relative time (age), absolute dates, durations
- Blockchain Value Formatting: Wei/Gwei/Eth conversion, gas formatting, token amounts
- Number Formatting: Thousands separators, compact notation (K/M/B), percentages, bytes
- Blockchain-Specific: Block numbers, transaction statuses, layer colors, status badges
- Validation Helpers: Address, tx hash, block hash validators
Installation
pnpm add @ghostchain1/utilsUsage
Class Name Utility
import { cn } from "@ghostchain1/utils";
// Basic usage
cn("px-4 py-2", "bg-blue-500");
// => 'px-4 py-2 bg-blue-500'
// Conditional classes
cn("base-class", { active: isActive, disabled: !enabled });
// Tailwind conflict resolution (px-4 overrides px-2)
cn("px-2 py-2", "px-4");
// => 'py-2 px-4'
// In components
<button
className={cn(
"px-4 py-2 rounded-lg transition-colors",
isActive && "bg-accent text-white",
isDisabled && "opacity-50 cursor-not-allowed",
)}
>
Click me
</button>;Hash & Address Formatting
import { truncateHash, formatAddress } from "@ghostchain1/utils";
truncateHash("0x1234567890abcdef1234567890abcdef12345678");
// => '0x123456…345678'
truncateHash("0x1234567890abcdef1234567890abcdef12345678", 6, 4);
// => '0x1234…5678'
formatAddress("1234567890abcdef1234567890abcdef12345678");
// => '0x1234567890abcdef1234567890abcdef12345678'Time & Date Formatting
import { formatAge, formatDate, formatDuration } from "@ghostchain1/utils";
const timestamp = Math.floor(Date.now() / 1000) - 300;
formatAge(timestamp);
// => '5m ago'
formatDate(1704067200);
// => 'Jan 1, 2024, 12:00 AM'
formatDuration(3665);
// => '1h 1m 5s'Blockchain Value Formatting
import { formatEth, formatGwei, formatGas, formatTokenAmount } from "@ghostchain1/utils";
formatEth("1500000000000000000"); // Wei to ETH
// => '1.5000'
formatEth("1500000000000000000", 2); // Custom decimals
// => '1.50'
formatGwei("50000000000"); // Wei to Gwei
// => '50.00'
formatGas("45000000000"); // Auto-unit gas
// => '45.00 Gwei'
formatTokenAmount("1000000", 6, 2); // USDC (6 decimals)
// => '1.00'Number Formatting
import { formatNumber, formatCompact, formatPercent, formatBytes } from "@ghostchain1/utils";
formatNumber(1234567);
// => '1,234,567'
formatCompact(1500000);
// => '1.5M'
formatPercent(0.4567); // Ratio (0-1)
// => '45.67%'
formatPercent(45.67, 2, false); // Raw percentage
// => '45.67%'
formatBytes(1536);
// => '1.50 KB'Blockchain-Specific
import { formatBlockNumber, formatTxStatus, layerColor, statusColor } from '@ghostchain1/utils';
formatBlockNumber(12345678);
// => '12,345,678'
formatTxStatus(1);
// => 'Success'
formatTxStatus(0);
// => 'Failed'
// Layer badge classes
<span className={cn('px-2 py-1 rounded text-xs', layerColor('l2'))}>
L2
</span>
// => 'bg-blue-500/20 text-blue-300 border-blue-500/30'
// Status badge classes
<span className={cn('px-2 py-1 rounded text-xs', statusColor('success'))}>
Success
</span>
// => 'bg-green-500/20 text-green-300 border-green-500/30'Validation Helpers
import { isValidAddress, isValidTxHash, isValidBlockHash } from "@ghostchain1/utils";
isValidAddress("0x1234567890abcdef1234567890abcdef12345678");
// => true
isValidTxHash("0x" + "a".repeat(64));
// => true
isValidBlockHash("0x" + "b".repeat(64));
// => trueAPI Reference
Class Name
cn(...inputs: ClassValue[]): string— Merge class names with Tailwind conflict resolution
Hash & Address
truncateHash(hash: string, leading?: number, trailing?: number): string— Truncate hash with ellipsistruncateAddress(address: string, leading?: number, trailing?: number): string— Alias for truncateHashformatAddress(address: string): string— Ensure address has 0x prefix
Time & Date
formatAge(timestamp: number): string— Relative time (e.g., '5m ago')formatDate(timestamp: number, options?: Intl.DateTimeFormatOptions): string— Absolute dateformatDuration(seconds: number): string— Duration string (e.g., '2h 30m')
Blockchain Values
formatEth(weiStr: string, decimals?: number): string— Wei to ETHformatGwei(weiStr: string, decimals?: number): string— Wei to GweiformatGas(gas: string | number): string— Auto-unit gas formattingformatTokenAmount(amount: string, decimals?: number, displayDecimals?: number): string— Generic token formatting
Numbers
formatNumber(n: number | string): string— Add thousands separatorsformatCompact(n: number, decimals?: number): string— Compact notation (K/M/B/T)formatPercent(value: number, decimals?: number, isRatio?: boolean): string— PercentageformatBytes(bytes: number, decimals?: number): string— Byte size
Blockchain-Specific
formatBlockNumber(blockNumber: string | number): string— Format block numberformatTxStatus(status: number | string): string— Human-readable tx statuslayerColor(layer: string): string— Tailwind classes for layer badgesstatusColor(status: string): string— Tailwind classes for status badges
Validation
isValidAddress(address: string): boolean— Validate Ethereum address formatisValidTxHash(hash: string): boolean— Validate transaction hash formatisValidBlockHash(hash: string): boolean— Validate block hash format
Migration from Local Utils
Before:
// apps/explorer-ui/src/lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function formatAge(timestamp: number): string {
// ... implementation
}After:
// Remove local utils file, import from shared package
import { cn, formatAge, formatEth } from "@ghostchain1/utils";Benefits
- Eliminates Duplication: 10+ duplicate
cn()implementations removed - Consistent Behavior: Same formatting logic across all apps
- Type Safety: Full TypeScript types exported
- Tree Shakeable: Import only what you need
- Tested: Comprehensive test coverage
- Documented: JSDoc comments for IDE autocomplete
Related Packages
@ghostchain1/tailwind-config— Shared Tailwind preset@ghostchain1/brand— Design tokens and themes@ghostchain1/ui-components— Shared React components
License
MIT
