@klever/connect-core
Core types, constants, utilities, and error handling for the Klever Connect SDK.
Installation
npm install @klever/connect-core
Overview
This package provides the foundational building blocks used across the Klever Connect SDK:
- Branded Types — Type-safe value handling with compile-time guarantees
- Constants — Blockchain parameters (asset IDs, precision, limits, timeouts)
- Format Utilities — Parse and format amounts between human-readable and smallest units
- Error Classes — Standardized error handling with context and recovery suggestions
- Logger System — Lightweight, configurable logging with multiple levels
- Environment Detection — Runtime environment identification (browser, Node.js, React Native)
- Validation Functions — Address validation and type guards
- Network Types — Network configuration and endpoint definitions
Quick Start
Format and Parse Amounts
import { parseKLV, formatKLV, parseUnits, formatUnits } from '@klever/connect-core'
// Parse user input to blockchain units
const amount = parseKLV('1.5') // 1500000n (1.5 KLV in smallest units)
// Format blockchain units for display
const display = formatKLV(1500000n) // '1.5'
// Generic parsing with custom decimals
const customAmount = parseUnits('100', 18) // 100000000000000000000n
const customDisplay = formatUnits(100000000000000000000n, 18) // '100'
Validate Addresses
import { isKleverAddress, isValidAddress, createKleverAddress } from '@klever/connect-core'
// Quick regex-based validation
if (isKleverAddress(address)) {
console.log('Valid format')
}
// Full bech32 validation
if (isValidAddress(address)) {
console.log('Valid Klever address')
}
// Create validated address
const validatedAddress = createKleverAddress('klv1qqqqqqqqqqqqqpgq...')
Use Branded Types
import { KleverAddress, AssetAmount, createAssetAmount } from '@klever/connect-core'
// Type-safe function signatures
function transfer(to: KleverAddress, amount: AssetAmount) {
// TypeScript ensures only validated addresses and amounts are passed
}
const recipient = createKleverAddress('klv1abc...')
const amount = createAssetAmount(1000000n)
transfer(recipient, amount)
API Reference
Format Utilities
parseKLV(amount: string | number): bigint
Parse KLV amount from human-readable string to smallest units.
parseKLV('1') // 1000000n (1 KLV)
parseKLV('1.5') // 1500000n (1.5 KLV)
parseKLV(2) // 2000000n (2 KLV)
parseKLV('0.000001') // 1n (smallest KLV unit)
formatKLV(amount: bigint | string | number): string
Format KLV amount from smallest units to human-readable string.
formatKLV(1000000n) // '1'
formatKLV(1500000n) // '1.5'
formatKLV('2000000') // '2'
parseUnits(value: string | number, decimals?: number): bigint
Parse a human-readable string to its smallest unit with custom decimals (default: 6).
parseUnits('1') // 1000000n
parseUnits('1.5') // 1500000n
parseUnits('0.000001') // 1n
parseUnits('100', 3) // 100000n
// Throws on invalid input
parseUnits('1.1234567', 6) // Error: Too many decimal places (max 6)
formatUnits(value: bigint | string | number, decimals?: number): string
Format a value from its smallest unit to a human-readable string (default: 6 decimals).
formatUnits(1000000n) // '1'
formatUnits(1500000n) // '1.5'
formatUnits(1234567n) // '1.234567'
formatUnits(500n) // '0.0005'
formatUnits(1000, 3) // '1'
Branded Types
Branded types provide compile-time type safety without runtime overhead.
Available Branded Types
import type {
KleverAddress, // Validated Klever address (klv1..., 62 chars)
TransactionHash, // Validated transaction hash (64 hex chars)
AssetAmount, // Asset amount in smallest units
AssetID,
BlockHeight,
BlockHash,
Nonce,
PublicKey,
PrivateKey,
Signature,
HexString,
Base58String,
} from '@klever/connect-core'
Branded Type Creators
import {
createKleverAddress, // Throws if address is invalid
createTransactionHash, // Throws if hash is invalid
createAssetAmount, // Throws if amount is negative
formatAssetAmount,
parseAssetAmount,
} from '@klever/connect-core'
const address = createKleverAddress('klv1qqqqqqqqqqqqqpgq...')
const hash = createTransactionHash('1234567890abcdef...')
const amount1 = createAssetAmount(1000000n) // From bigint
const amount2 = createAssetAmount('1000000') // From string
const amount3 = createAssetAmount(1000000) // From number
formatAssetAmount(createAssetAmount(1500000n)) // '1.5'
parseAssetAmount('1.5') // 1500000n as AssetAmount
Type Guards and Validators
import {
isKleverAddress, // Quick regex-based validation
isValidAddress, // Full bech32 validation
isTransactionHash, // Validates 64 hex characters
} from '@klever/connect-core'
if (isKleverAddress(input)) {
// input is now typed as KleverAddress
}
if (isValidAddress('klv1qqqqqqqqqqqqqpgq...')) {
// Full bech32 check
}
if (isTransactionHash(input)) {
// input is now typed as TransactionHash
}
Constants
import {
// Asset
KLV_ASSET_ID, // 'KLV'
KFI_ASSET_ID, // 'KFI'
KLV_PRECISION, // 6
KFI_PRECISION, // 6
KLV_MULTIPLIER, // 1000000
KFI_MULTIPLIER, // 1000000
// Address
ADDRESS_PREFIX, // 'klv'
ADDRESS_LENGTH, // 62
// Transaction
BASE_TX_SIZE, // 250 bytes
MAX_MESSAGE_SIZE, // 102400 bytes (100 KB)
SIGNATURE_LENGTH, // 64 bytes
MAX_TX_SIZE, // 32768 bytes (32 KB)
// Staking
MIN_SELF_DELEGATION, // 1000000000000n (1M KLV)
UNBONDING_TIME, // 1814400 seconds (21 days)
MAX_DELEGATORS_PER_VALIDATOR, // 10000
// Block
BLOCK_TIME, // 4 seconds
BLOCKS_PER_EPOCH, // 5400 blocks (~6 hours)
BLOCKS_PER_YEAR, // 7884000 blocks
EPOCH_DURATION, // 21600 seconds (6 hours)
// API
DEFAULT_PAGE_SIZE, // 100
MAX_PAGE_SIZE, // 1000
DEFAULT_TIMEOUT, // 30000 ms
DEFAULT_CONFIRMATIONS, // 1
// WebSocket
WS_RECONNECT_DELAY, // 1000 ms
WS_MAX_RECONNECT_ATTEMPTS, // 5
WS_PING_INTERVAL, // 30000 ms
} from '@klever/connect-core'
Error Classes
All error classes extend BaseError with standardized structure and context.
import {
NetworkError,
TransactionError,
WalletError,
ValidationError,
ContractError,
AuthenticationError,
RetryableError,
RecoverableError,
AggregateError,
errorBoundary,
} from '@klever/connect-core'
// NetworkError — network requests fail
throw new NetworkError('Failed to connect to node', { url, statusCode: 500 })
// TransactionError — transaction operations fail
throw new TransactionError('Transaction validation failed', { txHash: tx.hash })
// WalletError — wallet operations fail
throw new WalletError('Wallet not connected', { walletType: 'klever' })
// ValidationError — input validation fails
throw new ValidationError(`Invalid address: ${address}`, { address, expected: 'klv1...' })
// ContractError — smart contract operations fail
throw new ContractError('Contract call failed', { contract: address, method: 'transfer' })
// RetryableError — with exponential backoff hints
throw new RetryableError(
'Service temporarily unavailable',
ErrorCode.NetworkUnavailable,
{ service: 'node' },
{ retryAfter: 5000, maxRetries: 3 },
)
// RecoverableError — with user-facing suggestions
throw new RecoverableError(
'Insufficient balance',
ErrorCode.InvalidAmount,
['Top up your account', 'Use a smaller amount'],
{ balance: '100', required: '1000' },
)
// AggregateError — combines multiple errors
throw new AggregateError(failures, 'Multiple operations failed')
// errorBoundary — wrapper with fallback and transform
const result = await errorBoundary(async () => await riskyOperation(), {
fallback: defaultValue,
onError: (error) => console.error('Failed:', error),
transform: (error) => new CustomError('Wrapped error', { cause: error }),
})
Logger System
import { createLogger, getGlobalLogger, setGlobalLoggerOptions } from '@klever/connect-core'
// Create module-specific logger
const logger = createLogger('MyModule', {
level: 'debug', // 'debug' | 'info' | 'warn' | 'error' | 'silent'
timestamp: true,
colors: true,
})
logger.debug('Detailed debug info')
logger.info('Operation started')
logger.warn('Low memory warning')
logger.error('Operation failed', error)
// Child logger
const childLogger = logger.child('SubModule')
childLogger.info('Message from MyModule:SubModule')
// Global logger (recommended)
const logger2 = getGlobalLogger('MyModule')
// Configure globally
setGlobalLoggerOptions({
level: process.env.NODE_ENV === 'production' ? 'warn' : 'debug',
timestamp: true,
})
Pre-configured Loggers
import {
coreLogger, // Core SDK operations
providerLogger, // Provider/network operations
walletLogger, // Wallet operations
transactionLogger, // Transaction operations
contractLogger, // Smart contract operations
} from '@klever/connect-core'
Environment Detection
import {
detectEnvironment, // Returns 'browser' | 'node' | 'react-native' | 'unknown'
isBrowser,
isNode,
isReactNative,
} from '@klever/connect-core'
const env = detectEnvironment()
if (env === 'browser') {
// Use browser-specific APIs
} else if (env === 'node') {
// Use Node.js-specific APIs
}
Network Types
import type { Network, NetworkURI, NetworkConfig } from '@klever/connect-core'
// NetworkURI — endpoint URIs
const uris: NetworkURI = {
api: 'https://api.mainnet.klever.finance',
node: 'https://node.mainnet.klever.finance',
ws: 'wss://ws.mainnet.klever.finance',
explorer: 'https://kleverscan.org',
}
// NetworkConfig — flexible configuration
const config1: NetworkConfig = 'mainnet' // Named network
const config2: NetworkConfig = { api: 'https://custom.com' } // Custom URIs
const config3: NetworkConfig = { // Full object
name: 'custom',
chainId: 'my-chain',
config: { api: 'https://api.mychain.com' },
isTestnet: true,
nativeCurrency: { name: 'MyToken', symbol: 'MTK', decimals: 6 },
}
Common Use Cases
Parse and Validate User Input
import { parseKLV, isKleverAddress, ValidationError } from '@klever/connect-core'
function prepareTransfer(toAddress: string, amountStr: string) {
if (!isKleverAddress(toAddress)) {
throw new ValidationError('Invalid recipient address', { address: toAddress })
}
const amount = parseKLV(amountStr)
if (amount <= 0n) {
throw new ValidationError('Amount must be positive', { amount: amountStr })
}
return {
to: createKleverAddress(toAddress),
amount: createAssetAmount(amount),
}
}
Error Handling with Context
import { NetworkError, errorBoundary } from '@klever/connect-core'
async function fetchWithRetry(url: string): Promise<Response> {
return errorBoundary(
async () => {
const response = await fetch(url)
if (!response.ok) {
throw new NetworkError('HTTP request failed', {
url,
status: response.status,
statusText: response.statusText,
})
}
return response
},
{
transform: (error) =>
error instanceof NetworkError
? error
: new NetworkError('Unexpected error', { url }, error as Error),
},
)
}