@satianurag/hiero-mirror-client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["losslessParse","mapKey","mapTimestampRange","mapKey","mapKey","mapTimestampRange","mapStateChange"],"sources":["../src/errors/HieroError.ts","../src/errors/HieroNotFoundError.ts","../src/errors/HieroParseError.ts","../src/errors/HieroRateLimitError.ts","../src/errors/HieroServerError.ts","../src/errors/HieroValidationError.ts","../src/errors/factory.ts","../src/errors/HieroNetworkError.ts","../src/errors/HieroTimeoutError.ts","../src/http/etag-cache.ts","../src/http/json-parser.ts","../src/http/rate-limiter.ts","../src/http/retry.ts","../src/http/url-builder.ts","../src/http/client.ts","../src/mappers/common.ts","../src/mappers/account.ts","../src/mappers/token.ts","../src/pagination/paginator.ts","../src/resources/accounts.ts","../src/resources/balances.ts","../src/mappers/block.ts","../src/resources/blocks.ts","../src/mappers/contract.ts","../src/resources/contracts.ts","../src/mappers/network.ts","../src/resources/network.ts","../src/mappers/schedule.ts","../src/resources/schedules.ts","../src/mappers/transaction.ts","../src/resources/tokens.ts","../src/mappers/topic.ts","../src/pagination/stream.ts","../src/resources/topics.ts","../src/resources/transactions.ts","../src/client.ts","../src/errors/HieroCapabilityError.ts","../src/index.ts"],"sourcesContent":["/**\n * Base error class for all Hiero Mirror Client errors.\n *\n * Modeled after Stripe's error hierarchy — every SDK error extends this class,\n * enabling `instanceof HieroError` to catch all SDK-specific errors.\n *\n * @public\n */\nexport class HieroError extends Error {\n /** HTTP status code, if the error originated from an HTTP response. */\n readonly statusCode?: number;\n\n /** The raw response body, if available. */\n readonly rawBody?: string;\n\n constructor(\n message: string,\n options?: { statusCode?: number; rawBody?: string; cause?: unknown },\n ) {\n super(message, { cause: options?.cause });\n this.name = 'HieroError';\n this.statusCode = options?.statusCode;\n this.rawBody = options?.rawBody;\n\n // Fix prototype chain for instanceof checks (TypeScript + ES5 target issue)\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n statusCode: this.statusCode,\n };\n }\n}\n","import { HieroError } from './HieroError.js';\n\n/**\n * Thrown when the server returns HTTP 404 (Not Found) for a specific entity.\n *\n * @public\n */\nexport class HieroNotFoundError extends HieroError {\n /** The entity ID that was not found, if available. */\n readonly entityId?: string;\n\n constructor(message: string, options?: { entityId?: string; rawBody?: string }) {\n super(message, { statusCode: 404, rawBody: options?.rawBody });\n this.name = 'HieroNotFoundError';\n this.entityId = options?.entityId;\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n entityId: this.entityId,\n };\n }\n}\n","import { HieroError } from './HieroError.js';\n\n/**\n * Thrown when the response body cannot be parsed as JSON,\n * or when the response Content-Type is unexpected (e.g., `text/html`\n * for Unicode parameter errors — EC153).\n *\n * @public\n */\nexport class HieroParseError extends HieroError {\n /** The raw body text that could not be parsed. */\n readonly body: string;\n\n constructor(message: string, options: { body: string; statusCode?: number; cause?: unknown }) {\n super(message, { statusCode: options.statusCode, rawBody: options.body, cause: options.cause });\n this.name = 'HieroParseError';\n this.body = options.body;\n }\n}\n","import { HieroError } from './HieroError.js';\n\n/**\n * Thrown when the server returns HTTP 429 (Too Many Requests).\n *\n * @public\n */\nexport class HieroRateLimitError extends HieroError {\n /** Seconds to wait before retrying, parsed from `Retry-After` header. */\n readonly retryAfter?: number;\n\n constructor(message: string, options?: { retryAfter?: number; rawBody?: string }) {\n super(message, { statusCode: 429, rawBody: options?.rawBody });\n this.name = 'HieroRateLimitError';\n this.retryAfter = options?.retryAfter;\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n retryAfter: this.retryAfter,\n };\n }\n}\n","import { HieroError } from './HieroError.js';\n\n/**\n * Thrown when the server returns an HTTP 5xx error.\n *\n * @public\n */\nexport class HieroServerError extends HieroError {\n constructor(message: string, options?: { statusCode?: number; rawBody?: string }) {\n super(message, { statusCode: options?.statusCode ?? 500, rawBody: options?.rawBody });\n this.name = 'HieroServerError';\n }\n}\n","import { HieroError } from './HieroError.js';\n\n/**\n * Thrown when the server returns HTTP 400 or 415, or when client-side\n * input validation fails before the request is sent.\n *\n * @public\n */\nexport class HieroValidationError extends HieroError {\n /** The specific parameter that caused the validation error, if known. */\n readonly parameter?: string;\n\n constructor(\n message: string,\n options?: { statusCode?: number; parameter?: string; rawBody?: string },\n ) {\n super(message, { statusCode: options?.statusCode ?? 400, rawBody: options?.rawBody });\n this.name = 'HieroValidationError';\n this.parameter = options?.parameter;\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n parameter: this.parameter,\n };\n }\n}\n","import { HieroError } from './HieroError.js';\nimport { HieroNotFoundError } from './HieroNotFoundError.js';\nimport { HieroParseError } from './HieroParseError.js';\nimport { HieroRateLimitError } from './HieroRateLimitError.js';\nimport { HieroServerError } from './HieroServerError.js';\nimport { HieroValidationError } from './HieroValidationError.js';\n\n/**\n * Mirror Node error response shape:\n * `{ _status: { messages: [{ message: string, detail?: string, data?: unknown }] } }`\n */\ninterface MirrorNodeErrorBody {\n _status?: {\n messages?: Array<{\n message?: string;\n detail?: string;\n data?: unknown;\n }>;\n };\n}\n\n/**\n * Attempts to extract the error message from the Mirror Node's custom error shape.\n * Falls back to a generic message if parsing fails.\n *\n * @internal\n */\nfunction extractErrorMessage(body: unknown): string {\n if (typeof body === 'object' && body !== null) {\n const mirrorBody = body as MirrorNodeErrorBody;\n const firstMessage = mirrorBody._status?.messages?.[0];\n if (firstMessage) {\n const parts = [firstMessage.message];\n if (firstMessage.detail) {\n parts.push(firstMessage.detail);\n }\n return parts.filter(Boolean).join(': ');\n }\n }\n return 'Unknown error';\n}\n\n/**\n * Attempts to extract a parameter name from Mirror Node error messages.\n * Messages like \"Invalid parameter: limit\" → returns \"limit\".\n *\n * @internal\n */\nfunction extractParameter(message: string): string | undefined {\n const match = /Invalid parameter:\\s*(.+)/i.exec(message);\n return match?.[1]?.trim();\n}\n\n/**\n * Creates the appropriate error subclass from an HTTP response.\n *\n * Maps HTTP status codes to error subclasses:\n * - 400 → `HieroValidationError`\n * - 404 → `HieroNotFoundError`\n * - 415 → `HieroValidationError` (wrong Content-Type, EC52)\n * - 429 → `HieroRateLimitError`\n * - 5xx → `HieroServerError`\n * - Other → `HieroError`\n *\n * @internal\n */\nexport function createErrorFromResponse(\n statusCode: number,\n body: unknown,\n rawBody: string,\n headers?: Headers,\n): HieroError {\n const message = extractErrorMessage(body);\n\n switch (true) {\n case statusCode === 400:\n case statusCode === 415: {\n return new HieroValidationError(message, {\n statusCode,\n parameter: extractParameter(message),\n rawBody,\n });\n }\n\n case statusCode === 404: {\n return new HieroNotFoundError(message, { rawBody });\n }\n\n case statusCode === 429: {\n let retryAfter: number | undefined;\n const retryAfterHeader = headers?.get('retry-after');\n if (retryAfterHeader) {\n const parsed = Number.parseInt(retryAfterHeader, 10);\n if (!Number.isNaN(parsed)) {\n retryAfter = parsed;\n }\n }\n return new HieroRateLimitError(message, { retryAfter, rawBody });\n }\n\n case statusCode >= 500: {\n return new HieroServerError(message, { statusCode, rawBody });\n }\n\n default: {\n return new HieroError(message, { statusCode, rawBody });\n }\n }\n}\n\n/**\n * Creates an error from a non-JSON response body (e.g., HTML error pages from EC153).\n *\n * @internal\n */\nexport function createParseError(\n rawBody: string,\n statusCode?: number,\n cause?: unknown,\n): HieroParseError {\n return new HieroParseError('Failed to parse response body as JSON', {\n body: rawBody,\n statusCode,\n cause,\n });\n}\n","import { HieroError } from './HieroError.js';\n\n/**\n * Thrown when a network-level error occurs: DNS resolution failure,\n * connection refused, socket hangup, etc.\n *\n * @public\n */\nexport class HieroNetworkError extends HieroError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, { cause: options?.cause });\n this.name = 'HieroNetworkError';\n }\n}\n","import { HieroError } from './HieroError.js';\n\n/**\n * Thrown when a request exceeds the configured timeout (AbortController).\n *\n * @public\n */\nexport class HieroTimeoutError extends HieroError {\n /** The timeout duration in milliseconds that was exceeded. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, options?: { cause?: unknown }) {\n super(`Request timed out after ${timeoutMs}ms`, { cause: options?.cause });\n this.name = 'HieroTimeoutError';\n this.timeoutMs = timeoutMs;\n }\n}\n","/**\n * In-memory ETag cache for conditional HTTP requests.\n *\n * - Stores `{etag, body}` per normalized URL\n * - Sends `If-None-Match` on subsequent requests\n * - Returns cached body on 304 Not Modified\n * - Updates on 200 OK\n *\n * EC145: All Mirror Node ETags are weak (W/\"...\").\n *\n * @internal\n * @packageDocumentation\n */\n\nexport interface ETagEntry {\n etag: string;\n body: unknown;\n}\n\n/**\n * Simple in-memory ETag cache.\n *\n * Keys are normalized URLs (no trailing slashes).\n */\nexport class ETagCache {\n private readonly store = new Map<string, ETagEntry>();\n\n /**\n * Look up a cached ETag for the given URL.\n *\n * @returns The cached ETag string, or `undefined` if not cached.\n */\n getETag(url: string): string | undefined {\n return this.store.get(this.normalizeKey(url))?.etag;\n }\n\n /**\n * Look up the cached response body for the given URL.\n *\n * @returns The cached body, or `undefined` if not cached.\n */\n getCachedBody(url: string): unknown | undefined {\n return this.store.get(this.normalizeKey(url))?.body;\n }\n\n /**\n * Store or update a cache entry.\n */\n set(url: string, etag: string, body: unknown): void {\n this.store.set(this.normalizeKey(url), { etag, body });\n }\n\n /**\n * Remove a cache entry.\n */\n delete(url: string): void {\n this.store.delete(this.normalizeKey(url));\n }\n\n /**\n * Clear all cached entries.\n */\n clear(): void {\n this.store.clear();\n }\n\n /**\n * Number of entries in the cache.\n */\n get size(): number {\n return this.store.size;\n }\n\n /**\n * Normalize a URL for use as a cache key.\n *\n * EC43: Removes trailing slashes.\n */\n private normalizeKey(url: string): string {\n return url.replace(/\\/+$/, '');\n }\n}\n","/**\n * Safe JSON parser that prevents int64 precision loss.\n *\n * **Primary:** TC39 Stage 4 `context.source` reviver (Node 22+, modern browsers as of March 2026).\n * **Fallback:** `lossless-json` library (4KB, for Node 18-20 without `context.source`).\n *\n * Numbers exceeding `Number.MAX_SAFE_INTEGER` are returned as strings.\n * Decimals (e.g., `0.1`) remain as numbers.\n *\n * @internal\n */\n\nimport { parse as losslessParse } from 'lossless-json';\n\n/** Maximum response body size (10MB) before parsing is rejected. */\nconst MAX_RESPONSE_SIZE = 10 * 1024 * 1024;\n\n/**\n * Feature-detect `context.source` support (TC39 Stage 4, Nov 2025).\n * Evaluated once at module load time.\n */\nconst HAS_CONTEXT_SOURCE: boolean = (() => {\n try {\n let seen = false;\n JSON.parse('1', (_key: string, _value: unknown, context?: { source?: string }) => {\n if (context?.source !== undefined) {\n seen = true;\n }\n });\n return seen;\n } catch {\n return false;\n }\n})();\n\n/**\n * Reviver function for `JSON.parse` that uses TC39 `context.source` to detect\n * unsafe integers and return them as strings.\n *\n * Rules:\n * - Integers exceeding MAX_SAFE_INTEGER → return raw source string\n * - Safe integers → return as number\n * - Decimals (non-integer numbers like 0.1) → return as number\n * - All other types → pass through unchanged\n */\nfunction safeReviver(_key: string, value: unknown, context?: { source?: string }): unknown {\n if (typeof value === 'number' && context?.source !== undefined) {\n // Check if this is an integer (no decimal point in the raw source)\n const source = context.source;\n const isInteger = !source.includes('.') && !source.includes('e') && !source.includes('E');\n\n if (isInteger && !Number.isSafeInteger(value)) {\n return source; // Return raw source string to prevent precision loss\n }\n }\n return value;\n}\n\n/**\n * Fallback parser using `lossless-json` for environments without `context.source`.\n *\n * The lossless-json library parses all numbers as `LosslessNumber` objects,\n * then the reviver converts them back to `number` (if safe) or `string` (if unsafe).\n */\nfunction safeJsonParseFallback(text: string): unknown {\n return losslessParse(text, undefined, (value: string) => {\n const num = Number(value);\n\n // If it's NaN, keep as string\n if (Number.isNaN(num)) {\n return value;\n }\n\n // Decimals: keep as number (e.g., 0.1, 3.14)\n const isInteger = !value.includes('.') && !value.includes('e') && !value.includes('E');\n if (!isInteger) {\n return num;\n }\n\n // Safe integer: keep as number\n if (Number.isSafeInteger(num)) {\n return num;\n }\n\n // Unsafe integer: return as string\n return value;\n });\n}\n\n/**\n * Parses a JSON string safely, preserving precision for large integers.\n *\n * Numbers exceeding `Number.MAX_SAFE_INTEGER` are returned as strings.\n * Decimals remain as JavaScript `number` values.\n *\n * @param text - The raw JSON string to parse\n * @returns The parsed value\n * @throws {Error} If the input exceeds the maximum response size\n * @throws {SyntaxError} If the input is not valid JSON\n *\n * @internal\n */\nexport function safeJsonParse(text: string): unknown {\n if (text.length > MAX_RESPONSE_SIZE) {\n throw new Error(\n `Response body exceeds maximum size of ${MAX_RESPONSE_SIZE} bytes (${text.length} bytes received)`,\n );\n }\n\n if (HAS_CONTEXT_SOURCE) {\n return JSON.parse(text, safeReviver as Parameters<typeof JSON.parse>[1]);\n }\n\n return safeJsonParseFallback(text);\n}\n\n/**\n * Whether the current runtime supports TC39 `context.source` (primary path)\n * or uses the lossless-json fallback.\n *\n * Exposed for testing purposes.\n * @internal\n */\nexport const _internals = {\n HAS_CONTEXT_SOURCE,\n safeJsonParseFallback,\n} as const;\n","/**\n * Token bucket rate limiter for client-side request throttling.\n *\n * Uses a simple token bucket algorithm:\n * - Bucket starts full with `maxTokens` tokens\n * - Each request consumes 1 token\n * - Tokens replenish at `tokensPerSecond` rate\n * - If no tokens available, `acquire()` waits until a token is available\n *\n * Default: 50 requests per second.\n *\n * @internal\n */\nexport class RateLimiter {\n private tokens: number;\n private readonly maxTokens: number;\n private readonly refillRate: number; // tokens per ms\n private lastRefillTime: number;\n\n constructor(tokensPerSecond = 50) {\n this.maxTokens = tokensPerSecond;\n this.tokens = tokensPerSecond;\n this.refillRate = tokensPerSecond / 1000;\n this.lastRefillTime = Date.now();\n }\n\n /**\n * Refills tokens based on elapsed time since last refill.\n */\n private refill(): void {\n const now = Date.now();\n const elapsed = now - this.lastRefillTime;\n const newTokens = elapsed * this.refillRate;\n this.tokens = Math.min(this.maxTokens, this.tokens + newTokens);\n this.lastRefillTime = now;\n }\n\n /**\n * Acquires a token. If no tokens are available, waits until one is.\n *\n * @param signal - Optional abort signal for cancellation\n * @returns Promise that resolves when a token is acquired\n */\n async acquire(signal?: AbortSignal): Promise<void> {\n this.refill();\n\n if (this.tokens >= 1) {\n this.tokens -= 1;\n return;\n }\n\n // Calculate wait time until 1 token is available\n const deficit = 1 - this.tokens;\n const waitMs = Math.ceil(deficit / this.refillRate);\n\n await new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const timer = setTimeout(() => {\n this.refill();\n this.tokens -= 1;\n resolve();\n }, waitMs);\n\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n reject(signal.reason);\n },\n { once: true },\n );\n });\n }\n\n /**\n * Returns the current number of available tokens (for testing).\n *\n * @internal\n */\n get availableTokens(): number {\n this.refill();\n return this.tokens;\n }\n}\n","/**\n * Exponential backoff with jitter for retrying failed requests.\n *\n * Retry rules:\n * - Always retry: 5xx, network errors, 429\n * - Never retry: 400, 401, 403, 404 (client errors are not transient)\n * - 429: Always retry, use `Retry-After` header if present\n *\n * @internal\n */\n\nexport interface RetryOptions {\n /** Maximum number of retries. Default: 2. */\n maxRetries: number;\n /** Base delay in milliseconds. Default: 500ms. */\n baseDelay: number;\n /** Maximum delay cap in milliseconds. Default: 10000ms. */\n maxDelay: number;\n}\n\nexport const DEFAULT_RETRY_OPTIONS: RetryOptions = {\n maxRetries: 2,\n baseDelay: 500,\n maxDelay: 10_000,\n};\n\n/**\n * Determines whether a given HTTP status code is retryable.\n *\n * - 429 (Too Many Requests): always retryable\n * - 5xx (Server Error): retryable\n * - 4xx (Client Error): not retryable (except 429)\n *\n * @internal\n */\nexport function isRetryableStatus(statusCode: number): boolean {\n if (statusCode === 429) return true;\n if (statusCode >= 500) return true;\n return false;\n}\n\n/**\n * Determines whether an error is a retryable network error.\n *\n * @internal\n */\nexport function isRetryableError(error: unknown): boolean {\n if (error instanceof TypeError) {\n // fetch throws TypeError on network failures\n return true;\n }\n // AbortError (timeout) is NOT retryable — the user's abort takes priority\n if (error instanceof DOMException && error.name === 'AbortError') {\n return false;\n }\n return false;\n}\n\n/**\n * Computes the delay before the next retry attempt using exponential backoff\n * with full jitter.\n *\n * Formula: `random(0, min(maxDelay, baseDelay * 2^attempt))`\n *\n * @param attempt - Zero-based attempt number (0 = first retry)\n * @param options - Retry configuration\n * @param retryAfter - Optional `Retry-After` value from 429 response (seconds)\n * @returns Delay in milliseconds\n *\n * @internal\n */\nexport function computeRetryDelay(\n attempt: number,\n options: RetryOptions,\n retryAfter?: number,\n): number {\n // If server provides Retry-After, use it (converted to ms)\n if (retryAfter !== undefined && retryAfter > 0) {\n return retryAfter * 1000;\n }\n\n const exponentialDelay = options.baseDelay * 2 ** attempt;\n const cappedDelay = Math.min(exponentialDelay, options.maxDelay);\n\n // Full jitter: uniform random in [0, cappedDelay]\n return Math.random() * cappedDelay;\n}\n\n/**\n * Sleeps for the specified number of milliseconds.\n * Returns a promise that resolves after the delay, respecting abort signals.\n *\n * @internal\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const timer = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n reject(signal.reason);\n },\n { once: true },\n );\n });\n}\n","import { HieroValidationError } from '../errors/HieroValidationError.js';\n\n/** Maximum URL length before rejection (EC34). */\nconst MAX_URL_LENGTH = 4096;\n\n/**\n * Operator types supported by the Mirror Node API query parameters.\n * Used with `.append()` for multi-value/range queries: `timestamp=gt:1234`.\n */\nexport type QueryOperator = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';\n\n/**\n * A query parameter value with an optional operator prefix.\n */\nexport interface OperatorValue {\n operator: QueryOperator;\n value: string | number;\n}\n\n/**\n * Raw query parameter types accepted by the URL builder.\n */\nexport type QueryParamValue =\n | string\n | number\n | boolean\n | OperatorValue\n | OperatorValue[]\n | undefined\n | null;\n\nexport interface QueryParams {\n [key: string]: QueryParamValue;\n}\n\n/**\n * Mapping of SDK-friendly camelCase parameter names to the dot-notation\n * parameter names expected by the Mirror Node API (EC64).\n */\nconst PARAM_NAME_MAP: Record<string, string> = {\n senderId: 'sender.id',\n receiverId: 'receiver.id',\n accountId: 'account.id',\n tokenId: 'token.id',\n nodeId: 'node.id',\n scheduleId: 'schedule.id',\n nonce: 'nonce',\n};\n\n/**\n * Resolves a parameter name through the camelCase→dot.notation map.\n */\nfunction resolveParamName(name: string): string {\n return PARAM_NAME_MAP[name] ?? name;\n}\n\n/**\n * Builds a complete URL from base URL, path segments, and query parameters.\n *\n * Handles:\n * - Double-slash collapsing (EC115)\n * - Null byte stripping (EC154)\n * - Trailing slash removal (EC43)\n * - Operator query params: `timestamp=gt:1234` (EC10)\n * - Scalar query params: `limit=10` (EC42)\n * - CamelCase→dot.notation parameter name mapping (EC64)\n * - URL length validation (<4KB, EC34)\n * - Omission of undefined/null/\"\" param values (EC119)\n *\n * @param baseUrl - The base URL (e.g., `https://testnet.mirrornode.hedera.com`)\n * @param path - The API path (e.g., `/api/v1/accounts`)\n * @param params - Optional query parameters\n * @returns The fully constructed URL string\n * @throws {HieroValidationError} If the resulting URL exceeds the max length\n *\n * @internal\n */\nexport function buildUrl(baseUrl: string, path: string, params?: QueryParams): string {\n // Strip null bytes (EC154)\n let cleanPath = path.replace(/\\0/g, '');\n\n // Collapse double slashes (EC115) — preserve protocol ://\n cleanPath = cleanPath.replace(/(?<!:)\\/{2,}/g, '/');\n\n // Strip trailing slash (EC43)\n if (cleanPath.length > 1 && cleanPath.endsWith('/')) {\n cleanPath = cleanPath.slice(0, -1);\n }\n\n // Build the URL\n const url = new URL(cleanPath, baseUrl);\n\n // Add query parameters\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n // Skip undefined, null, and empty string values (EC119)\n if (value === undefined || value === null || value === '') {\n continue;\n }\n\n const resolvedKey = resolveParamName(key);\n\n if (typeof value === 'object' && 'operator' in value) {\n // Single operator value: timestamp=gt:1234\n url.searchParams.append(resolvedKey, `${value.operator}:${value.value}`);\n } else if (Array.isArray(value)) {\n // Array of operator values: multiple operator params\n for (const item of value) {\n if (typeof item === 'object' && 'operator' in item) {\n url.searchParams.append(resolvedKey, `${item.operator}:${item.value}`);\n }\n }\n } else {\n // Scalar value: limit=10 (uses set to enforce last-wins, EC42)\n url.searchParams.set(resolvedKey, String(value));\n }\n }\n }\n\n const result = url.toString();\n\n // URL length check (EC34)\n if (result.length > MAX_URL_LENGTH) {\n throw new HieroValidationError(\n `URL exceeds maximum length of ${MAX_URL_LENGTH} characters (${result.length} chars).`,\n { parameter: 'url' },\n );\n }\n\n return result;\n}\n","/**\n * Core HTTP client for the Hiero Mirror Node SDK.\n *\n * Wraps `fetch` with:\n * - Timeout via `AbortController`\n * - Safe JSON parsing (int64 precision)\n * - Error factory integration\n * - Rate limiting\n * - Request deduplication\n * - Retry with exponential backoff\n * - ETag/conditional request support (stubbed for Step 11)\n *\n * @internal\n */\n\nimport { createErrorFromResponse, createParseError } from '../errors/factory.js';\nimport { HieroNetworkError } from '../errors/HieroNetworkError.js';\nimport { HieroTimeoutError } from '../errors/HieroTimeoutError.js';\nimport { ETagCache } from './etag-cache.js';\nimport { safeJsonParse } from './json-parser.js';\nimport { RateLimiter } from './rate-limiter.js';\nimport {\n computeRetryDelay,\n DEFAULT_RETRY_OPTIONS,\n isRetryableError,\n isRetryableStatus,\n type RetryOptions,\n sleep,\n} from './retry.js';\nimport { buildUrl, type QueryParams } from './url-builder.js';\n\nexport interface HttpClientOptions {\n /** Base URL for the mirror node. */\n baseUrl: string;\n /** Request timeout in milliseconds. Default: 30000. */\n timeout?: number;\n /** Retry options. */\n retry?: Partial<RetryOptions>;\n /** Rate limit in requests per second. Default: 50. */\n rateLimitRps?: number;\n /** Optional logger for debug output. */\n logger?: Logger;\n /** Custom fetch implementation (for testing). */\n fetch?: typeof globalThis.fetch;\n}\n\nexport interface Logger {\n debug?: (message: string, ...args: unknown[]) => void;\n info?: (message: string, ...args: unknown[]) => void;\n warn?: (message: string, ...args: unknown[]) => void;\n error?: (message: string, ...args: unknown[]) => void;\n}\n\nexport interface RequestOptions {\n /** Additional headers to send. */\n headers?: Record<string, string>;\n /** Override the default timeout for this request. */\n timeout?: number;\n /** Abort signal for request cancellation. */\n signal?: AbortSignal;\n}\n\nexport interface HttpResponse<T = unknown> {\n /** Parsed response body. */\n data: T;\n /** HTTP status code. */\n status: number;\n /** Response headers. */\n headers: Headers;\n}\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly retryOptions: RetryOptions;\n private readonly rateLimiter: RateLimiter;\n private readonly inflight = new Map<string, Promise<HttpResponse<unknown>>>();\n private readonly etagCache: ETagCache;\n private readonly logger: Logger;\n private readonly fetchFn: typeof globalThis.fetch;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl;\n this.timeout = options.timeout ?? 30_000;\n this.retryOptions = { ...DEFAULT_RETRY_OPTIONS, ...options.retry };\n this.rateLimiter = new RateLimiter(options.rateLimitRps ?? 50);\n this.etagCache = new ETagCache();\n this.logger = options.logger ?? {};\n this.fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /**\n * Performs a GET request with in-flight deduplication.\n *\n * @param path - API path (e.g., `/api/v1/accounts`)\n * @param params - Optional query parameters\n * @param options - Optional request options\n * @returns Parsed response\n */\n async get<T = unknown>(\n path: string,\n params?: QueryParams,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n const url = buildUrl(this.baseUrl, path, params);\n\n // Dedup: if an identical GET is already in-flight, return same promise\n const existing = this.inflight.get(url);\n if (existing) {\n return existing as Promise<HttpResponse<T>>;\n }\n\n // EC145: Inject If-None-Match header for ETag-based conditional requests\n const cachedETag = this.etagCache.getETag(url);\n const mergedOptions: RequestOptions = cachedETag\n ? {\n ...options,\n headers: { ...options?.headers, 'If-None-Match': cachedETag },\n }\n : (options ?? {});\n\n const promise = this.request<T>('GET', url, undefined, mergedOptions);\n this.inflight.set(url, promise as Promise<HttpResponse<unknown>>);\n\n try {\n return await promise;\n } finally {\n this.inflight.delete(url);\n }\n }\n\n /**\n * Performs a POST request.\n *\n * POST requests are NOT deduplicated (they have side effects).\n *\n * @param path - API path\n * @param body - Request body (will be JSON-serialized)\n * @param options - Optional request options\n * @returns Parsed response\n */\n async post<T = unknown>(\n path: string,\n body: unknown,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n const url = buildUrl(this.baseUrl, path);\n return this.request<T>('POST', url, body, options);\n }\n\n /**\n * Core request method with retry, rate limiting, timeout, and error handling.\n */\n private async request<T>(\n method: string,\n url: string,\n body?: unknown,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= this.retryOptions.maxRetries; attempt++) {\n try {\n // Rate limiting\n await this.rateLimiter.acquire(options?.signal);\n\n // Timeout via AbortController\n const timeoutMs = options?.timeout ?? this.timeout;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n // Compose abort signals: user signal + timeout\n if (options?.signal) {\n options.signal.addEventListener('abort', () => controller.abort(options.signal?.reason), {\n once: true,\n });\n }\n\n try {\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Accept-Encoding': 'gzip',\n ...options?.headers,\n };\n\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n this.logger.debug?.(`[HTTP] ${method} ${url}`, { attempt });\n\n const response = await this.fetchFn(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n return await this.handleResponse<T>(response, url, attempt);\n } catch (error) {\n clearTimeout(timeoutId);\n\n // Check if this was a timeout\n if (\n error instanceof DOMException &&\n error.name === 'AbortError' &&\n !options?.signal?.aborted\n ) {\n throw new HieroTimeoutError(timeoutMs);\n }\n\n throw error;\n }\n } catch (error) {\n lastError = error;\n\n // Don't retry on timeout, validation, or user abort\n if (error instanceof HieroTimeoutError) throw error;\n if (options?.signal?.aborted) throw error;\n\n // Check if the error is retryable\n const isRetryable =\n isRetryableError(error) ||\n (error !== null &&\n typeof error === 'object' &&\n 'statusCode' in error &&\n isRetryableStatus((error as { statusCode: number }).statusCode));\n\n if (!isRetryable || attempt >= this.retryOptions.maxRetries) {\n throw error;\n }\n\n // Compute retry delay\n const retryAfter =\n error !== null && typeof error === 'object' && 'retryAfter' in error\n ? (error as { retryAfter?: number }).retryAfter\n : undefined;\n\n const delay = computeRetryDelay(attempt, this.retryOptions, retryAfter);\n this.logger.warn?.(\n `[HTTP] Retry ${attempt + 1}/${this.retryOptions.maxRetries} after ${Math.round(delay)}ms`,\n {\n url,\n },\n );\n\n await sleep(delay, options?.signal);\n }\n }\n\n // Should not reach here, but just in case\n if (lastError instanceof Error) throw lastError;\n throw new HieroNetworkError('Request failed after all retries');\n }\n\n /**\n * Handles the HTTP response: checks content type, parses JSON safely,\n * and throws appropriate errors for non-2xx responses.\n */\n private async handleResponse<T>(\n response: Response,\n url: string,\n _attempt: number,\n ): Promise<HttpResponse<T>> {\n const rawBody = await response.text();\n\n // EC145: 304 Not Modified — return cached body\n if (response.status === 304) {\n const cachedBody = this.etagCache.getCachedBody(url);\n this.logger.debug?.(`[HTTP] 304 Not Modified — returning cached body for ${url}`);\n return {\n data: (cachedBody ?? null) as T,\n status: 304,\n headers: response.headers,\n };\n }\n\n // Check Content-Type before parsing (EC153)\n const contentType = response.headers.get('content-type') ?? '';\n const isJson = contentType.includes('application/json') || contentType.includes('text/json');\n\n if (!response.ok) {\n // Try to parse error body as JSON\n let parsedBody: unknown = null;\n if (isJson && rawBody) {\n try {\n parsedBody = JSON.parse(rawBody);\n } catch {\n // Non-JSON error response (EC153: text/html)\n }\n }\n\n if (parsedBody) {\n const error = createErrorFromResponse(\n response.status,\n parsedBody,\n rawBody,\n response.headers,\n );\n throw error;\n }\n\n // Non-JSON error body\n throw createParseError(rawBody, response.status);\n }\n\n // 204 No Content\n if (response.status === 204 || !rawBody) {\n return {\n data: null as T,\n status: response.status,\n headers: response.headers,\n };\n }\n\n // Parse successful JSON response with safe parser\n if (!isJson) {\n this.logger.warn?.(`[HTTP] Unexpected content-type \"${contentType}\" for ${url}`);\n }\n\n try {\n const data = safeJsonParse(rawBody) as T;\n\n // EC145: Cache ETag from response for future conditional requests\n const etag = response.headers.get('etag');\n if (etag) {\n this.etagCache.set(url, etag, data);\n }\n\n return {\n data,\n status: response.status,\n headers: response.headers,\n };\n } catch (cause) {\n throw createParseError(rawBody, response.status, cause);\n }\n }\n}\n","/**\n * Shared mapper utilities for transforming raw API JSON → SDK types.\n *\n * @internal\n * @packageDocumentation\n */\n\n// ---------------------------------------------------------------------------\n// Base64 decode — cross-platform (no Buffer dependency, EC3/11/18)\n// ---------------------------------------------------------------------------\n\n/**\n * Decodes a Base64 string to a `Uint8Array`.\n *\n * Uses `atob()` which is available in all modern environments\n * (browsers, Node 16+, Deno, Bun).\n */\nexport function decodeBase64(value: string): Uint8Array {\n const binaryString = atob(value);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes;\n}\n\n// ---------------------------------------------------------------------------\n// Hex string decode — UTF-8 (EC24)\n// ---------------------------------------------------------------------------\n\n/**\n * Decodes a hex-encoded string (e.g., `0x57524f4e475f4e4f4e4345`) to UTF-8.\n *\n * EC24: Contract `error_message` fields are hex-encoded.\n *\n * @returns The decoded string, or `null` if the input is not valid hex.\n */\nexport function decodeHexString(hex: string | null): string | null {\n if (hex == null || hex === '') return null;\n\n // Strip `0x` prefix if present\n const raw = hex.startsWith('0x') || hex.startsWith('0X') ? hex.slice(2) : hex;\n\n if (raw.length === 0 || raw.length % 2 !== 0) return null;\n\n try {\n const bytes: number[] = [];\n for (let i = 0; i < raw.length; i += 2) {\n bytes.push(Number.parseInt(raw.substring(i, i + 2), 16));\n }\n return new TextDecoder().decode(new Uint8Array(bytes));\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type coercion — ensure string (EC14/88)\n// ---------------------------------------------------------------------------\n\n/**\n * Coerces a value to a string representation.\n *\n * EC14/88: `decimals` is sometimes returned as a number (list endpoints)\n * and sometimes as a string (detail endpoints). We normalize to string.\n */\nexport function ensureString(value: unknown): string {\n if (value == null) return '0';\n return String(value);\n}\n\n// ---------------------------------------------------------------------------\n// Record helper — type-safe access\n// ---------------------------------------------------------------------------\n\n/**\n * Casts unknown to a record for field extraction.\n *\n * @internal\n */\nexport function asRecord(value: unknown): Record<string, unknown> {\n if (value != null && typeof value === 'object' && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n return {};\n}\n\n/**\n * Extracts a string field with optional fallback.\n */\nexport function str(\n raw: Record<string, unknown>,\n key: string,\n fallback: string | null = null,\n): string | null {\n const v = raw[key];\n if (v == null) return fallback;\n return String(v);\n}\n\n/**\n * Extracts a required string field (returns empty string if missing).\n */\nexport function strReq(raw: Record<string, unknown>, key: string): string {\n return str(raw, key, '') as string;\n}\n\n/**\n * Extracts a number field with optional fallback.\n */\nexport function num(raw: Record<string, unknown>, key: string, fallback = 0): number {\n const v = raw[key];\n if (v == null) return fallback;\n return typeof v === 'number' ? v : Number(v);\n}\n\n/**\n * Extracts a boolean field.\n */\nexport function bool(raw: Record<string, unknown>, key: string, fallback = false): boolean {\n const v = raw[key];\n if (v == null) return fallback;\n return Boolean(v);\n}\n\n/**\n * Extracts an array field.\n */\nexport function arr<T = unknown>(raw: Record<string, unknown>, key: string): T[] {\n const v = raw[key];\n return Array.isArray(v) ? (v as T[]) : [];\n}\n","/**\n * Account response mappers.\n *\n * @internal\n */\n\nimport type {\n AccountBalance,\n AccountDetail,\n AccountSummary,\n AccountTransaction,\n Airdrop,\n CryptoAllowance,\n NftAllowance,\n StakingReward,\n TokenAllowance,\n TokenRelationship,\n} from '../types/accounts.js';\nimport type { HieroKey, TokenBalance } from '../types/common.js';\nimport { arr, asRecord, bool, num, str, strReq } from './common.js';\n\nfunction mapKey(raw: unknown): HieroKey | null {\n if (raw == null) return null;\n const r = asRecord(raw);\n return {\n _type: strReq(r, '_type'),\n key: strReq(r, 'key'),\n } as HieroKey;\n}\n\nfunction mapTokenBalance(raw: unknown): TokenBalance {\n const r = asRecord(raw);\n return {\n token_id: strReq(r, 'token_id'),\n balance: strReq(r, 'balance'),\n };\n}\n\nfunction mapAccountBalance(raw: unknown): AccountBalance {\n const r = asRecord(raw);\n return {\n balance: strReq(r, 'balance'),\n timestamp: strReq(r, 'timestamp'),\n tokens: arr(r, 'tokens').map(mapTokenBalance),\n };\n}\n\nexport function mapAccountSummary(raw: unknown): AccountSummary {\n const r = asRecord(raw);\n return {\n account: strReq(r, 'account'),\n alias: str(r, 'alias'),\n auto_renew_period: str(r, 'auto_renew_period'),\n balance: mapAccountBalance(r.balance),\n created_timestamp: str(r, 'created_timestamp'),\n decline_reward: bool(r, 'decline_reward'),\n deleted: bool(r, 'deleted'),\n ethereum_nonce: strReq(r, 'ethereum_nonce'),\n evm_address: str(r, 'evm_address'),\n expiry_timestamp: str(r, 'expiry_timestamp'),\n key: mapKey(r.key),\n max_automatic_token_associations: num(r, 'max_automatic_token_associations'),\n memo: strReq(r, 'memo'),\n pending_reward: strReq(r, 'pending_reward'),\n receiver_sig_required:\n r.receiver_sig_required == null ? null : bool(r, 'receiver_sig_required'),\n staked_account_id: str(r, 'staked_account_id'),\n staked_node_id: r.staked_node_id == null ? null : num(r, 'staked_node_id'),\n stake_period_start: str(r, 'stake_period_start'),\n };\n}\n\nexport function mapAccountDetail(raw: unknown): AccountDetail {\n const r = asRecord(raw);\n const summary = mapAccountSummary(raw);\n const linksRaw = asRecord(r.links);\n return {\n ...summary,\n transactions: arr(r, 'transactions').map(mapAccountTransaction),\n links: { next: str(linksRaw, 'next') },\n };\n}\n\nfunction mapAccountTransaction(raw: unknown): AccountTransaction {\n const r = asRecord(raw);\n return {\n bytes: str(r, 'bytes'),\n charged_tx_fee: strReq(r, 'charged_tx_fee'),\n consensus_timestamp: strReq(r, 'consensus_timestamp'),\n entity_id: str(r, 'entity_id'),\n max_fee: strReq(r, 'max_fee'),\n memo_base64: strReq(r, 'memo_base64'),\n name: strReq(r, 'name'),\n nft_transfers: arr(r, 'nft_transfers').map((t) => {\n const tr = asRecord(t);\n return {\n is_approval: bool(tr, 'is_approval'),\n receiver_account_id: str(tr, 'receiver_account_id'),\n sender_account_id: str(tr, 'sender_account_id'),\n serial_number: strReq(tr, 'serial_number'),\n token_id: strReq(tr, 'token_id'),\n };\n }),\n node: str(r, 'node'),\n nonce: num(r, 'nonce'),\n parent_consensus_timestamp: str(r, 'parent_consensus_timestamp'),\n result: strReq(r, 'result'),\n scheduled: bool(r, 'scheduled'),\n staking_reward_transfers: arr(r, 'staking_reward_transfers').map((s) => {\n const sr = asRecord(s);\n return { account: strReq(sr, 'account'), amount: strReq(sr, 'amount') };\n }),\n token_transfers: arr(r, 'token_transfers').map((t) => {\n const tr = asRecord(t);\n return {\n account: strReq(tr, 'account'),\n amount: strReq(tr, 'amount'),\n is_approval: bool(tr, 'is_approval'),\n token_id: strReq(tr, 'token_id'),\n };\n }),\n transaction_hash: strReq(r, 'transaction_hash'),\n transaction_id: strReq(r, 'transaction_id'),\n transfers: arr(r, 'transfers').map((t) => {\n const tr = asRecord(t);\n return {\n account: strReq(tr, 'account'),\n amount: strReq(tr, 'amount'),\n is_approval: bool(tr, 'is_approval'),\n };\n }),\n valid_duration_seconds: strReq(r, 'valid_duration_seconds'),\n valid_start_timestamp: strReq(r, 'valid_start_timestamp'),\n };\n}\n\nexport function mapTokenRelationship(raw: unknown): TokenRelationship {\n const r = asRecord(raw);\n return {\n automatic_association: bool(r, 'automatic_association'),\n balance: strReq(r, 'balance'),\n created_timestamp: strReq(r, 'created_timestamp'),\n decimals: String(r.decimals ?? '0'),\n freeze_status: strReq(r, 'freeze_status') as TokenRelationship['freeze_status'],\n kyc_status: strReq(r, 'kyc_status') as TokenRelationship['kyc_status'],\n token_id: strReq(r, 'token_id'),\n };\n}\n\nexport function mapStakingReward(raw: unknown): StakingReward {\n const r = asRecord(raw);\n return {\n account_id: strReq(r, 'account_id'),\n amount: strReq(r, 'amount'),\n timestamp: strReq(r, 'timestamp'),\n };\n}\n\nfunction mapTimestampRange(raw: unknown): { from: string; to: string | null } {\n const r = asRecord(raw);\n return { from: strReq(r, 'from'), to: str(r, 'to') };\n}\n\nexport function mapCryptoAllowance(raw: unknown): CryptoAllowance {\n const r = asRecord(raw);\n return {\n amount: strReq(r, 'amount'),\n amount_granted: strReq(r, 'amount_granted'),\n owner: strReq(r, 'owner'),\n spender: strReq(r, 'spender'),\n timestamp: mapTimestampRange(r.timestamp),\n };\n}\n\nexport function mapTokenAllowance(raw: unknown): TokenAllowance {\n const r = asRecord(raw);\n return {\n amount: strReq(r, 'amount'),\n amount_granted: strReq(r, 'amount_granted'),\n owner: strReq(r, 'owner'),\n spender: strReq(r, 'spender'),\n token_id: strReq(r, 'token_id'),\n timestamp: mapTimestampRange(r.timestamp),\n };\n}\n\nexport function mapNftAllowance(raw: unknown): NftAllowance {\n const r = asRecord(raw);\n return {\n approved_for_all: bool(r, 'approved_for_all'),\n owner: strReq(r, 'owner'),\n spender: strReq(r, 'spender'),\n token_id: strReq(r, 'token_id'),\n timestamp: mapTimestampRange(r.timestamp),\n };\n}\n\nexport function mapAirdrop(raw: unknown): Airdrop {\n const r = asRecord(raw);\n return {\n amount: strReq(r, 'amount'),\n receiver_id: strReq(r, 'receiver_id'),\n sender_id: strReq(r, 'sender_id'),\n serial_number: str(r, 'serial_number'),\n token_id: strReq(r, 'token_id'),\n timestamp: mapTimestampRange(r.timestamp),\n };\n}\n","/**\n * Token response mappers.\n * @internal\n */\n\nimport type { HieroKey } from '../types/common.js';\nimport type {\n CustomFees,\n FixedFee,\n FractionAmount,\n FractionalFee,\n RoyaltyFee,\n TokenBalanceEntry,\n TokenDetail,\n TokenNft,\n TokenSummary,\n} from '../types/tokens.js';\nimport { arr, asRecord, bool, ensureString, num, str, strReq } from './common.js';\n\nfunction mapKey(raw: unknown): HieroKey | null {\n if (raw == null) return null;\n const r = asRecord(raw);\n return { _type: strReq(r, '_type'), key: strReq(r, 'key') } as HieroKey;\n}\n\nfunction mapFractionAmount(raw: unknown): FractionAmount {\n const r = asRecord(raw);\n return { numerator: num(r, 'numerator'), denominator: num(r, 'denominator') };\n}\n\nfunction mapFixedFee(raw: unknown): FixedFee {\n const r = asRecord(raw);\n return {\n all_collectors_are_exempt: bool(r, 'all_collectors_are_exempt'),\n amount: strReq(r, 'amount'),\n collector_account_id: strReq(r, 'collector_account_id'),\n denominating_token_id: str(r, 'denominating_token_id'),\n };\n}\n\nfunction mapFractionalFee(raw: unknown): FractionalFee {\n const r = asRecord(raw);\n return {\n all_collectors_are_exempt: bool(r, 'all_collectors_are_exempt'),\n amount: mapFractionAmount(r.amount),\n collector_account_id: strReq(r, 'collector_account_id'),\n denominating_token_id: str(r, 'denominating_token_id'),\n maximum: str(r, 'maximum'),\n minimum: strReq(r, 'minimum'),\n net_of_transfers: bool(r, 'net_of_transfers'),\n };\n}\n\nfunction mapRoyaltyFee(raw: unknown): RoyaltyFee {\n const r = asRecord(raw);\n return {\n all_collectors_are_exempt: bool(r, 'all_collectors_are_exempt'),\n amount: mapFractionAmount(r.amount),\n collector_account_id: strReq(r, 'collector_account_id'),\n fallback_fee: r.fallback_fee != null ? mapFixedFee(r.fallback_fee) : null,\n };\n}\n\nfunction mapCustomFees(raw: unknown): CustomFees {\n const r = asRecord(raw);\n return {\n created_timestamp: strReq(r, 'created_timestamp'),\n fixed_fees: arr(r, 'fixed_fees').map(mapFixedFee),\n fractional_fees: arr(r, 'fractional_fees').map(mapFractionalFee),\n royalty_fees: arr(r, 'royalty_fees').map(mapRoyaltyFee),\n };\n}\n\nexport function mapTokenSummary(raw: unknown): TokenSummary {\n const r = asRecord(raw);\n return {\n admin_key: mapKey(r.admin_key),\n /** EC14/88: Always string. */\n decimals: ensureString(r.decimals),\n metadata: strReq(r, 'metadata'),\n name: strReq(r, 'name'),\n symbol: strReq(r, 'symbol'),\n token_id: strReq(r, 'token_id'),\n type: strReq(r, 'type') as TokenSummary['type'],\n };\n}\n\nexport function mapTokenDetail(raw: unknown): TokenDetail {\n const r = asRecord(raw);\n const summary = mapTokenSummary(raw);\n return {\n ...summary,\n auto_renew_account: str(r, 'auto_renew_account'),\n auto_renew_period: str(r, 'auto_renew_period'),\n created_timestamp: strReq(r, 'created_timestamp'),\n custom_fees: mapCustomFees(r.custom_fees),\n deleted: bool(r, 'deleted'),\n expiry_timestamp: str(r, 'expiry_timestamp'),\n fee_schedule_key: mapKey(r.fee_schedule_key),\n freeze_default: bool(r, 'freeze_default'),\n freeze_key: mapKey(r.freeze_key),\n initial_supply: strReq(r, 'initial_supply'),\n kyc_key: mapKey(r.kyc_key),\n max_supply: strReq(r, 'max_supply'),\n memo: strReq(r, 'memo'),\n metadata_key: mapKey(r.metadata_key),\n modified_timestamp: strReq(r, 'modified_timestamp'),\n pause_key: mapKey(r.pause_key),\n pause_status: strReq(r, 'pause_status'),\n supply_key: mapKey(r.supply_key),\n supply_type: strReq(r, 'supply_type'),\n total_supply: strReq(r, 'total_supply'),\n treasury_account_id: strReq(r, 'treasury_account_id'),\n wipe_key: mapKey(r.wipe_key),\n };\n}\n\nexport function mapTokenNft(raw: unknown): TokenNft {\n const r = asRecord(raw);\n return {\n account_id: strReq(r, 'account_id'),\n created_timestamp: strReq(r, 'created_timestamp'),\n delegating_spender: str(r, 'delegating_spender'),\n deleted: bool(r, 'deleted'),\n metadata: strReq(r, 'metadata'),\n modified_timestamp: strReq(r, 'modified_timestamp'),\n serial_number: strReq(r, 'serial_number'),\n spender: str(r, 'spender'),\n token_id: strReq(r, 'token_id'),\n };\n}\n\nexport function mapTokenBalanceEntry(raw: unknown): TokenBalanceEntry {\n const r = asRecord(raw);\n return {\n account: strReq(r, 'account'),\n balance: strReq(r, 'balance'),\n decimals: ensureString(r.decimals),\n };\n}\n","/**\n * Paginator class for iterating over paginated Mirror Node API responses.\n *\n * Supports three usage patterns:\n *\n * 1. **Await** — returns the first page:\n * ```ts\n * const page = await client.accounts.list();\n * ```\n *\n * 2. **for-await-of** — yields individual items across all pages:\n * ```ts\n * for await (const account of client.accounts.list()) {\n * console.log(account);\n * }\n * ```\n *\n * 3. **`.pages()`** — yields page objects:\n * ```ts\n * for await (const page of client.accounts.list().pages()) {\n * console.log(`Got ${page.data.length} items`);\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { HttpClient, HttpResponse } from '../http/client.js';\nimport type { Page, PaginationLinks } from '../types/common.js';\n\n/**\n * A function that extracts `/api/v1/...` items from a raw API response\n * and returns a {@link Page} of mapped items.\n */\nexport type PageExtractor<T> = (raw: unknown) => Page<T>;\n\n/**\n * Configuration for creating a Paginator.\n */\nexport interface PaginatorOptions<T> {\n /** The HTTP client instance. */\n client: HttpClient;\n /** The initial API path (e.g., `/api/v1/accounts`). */\n path: string;\n /** Query parameters for the first request. */\n params?: Record<string, unknown>;\n /** Mapper function: raw JSON → Page<T>. */\n extract: PageExtractor<T>;\n}\n\n/**\n * Lazy paginator that fetches pages on demand.\n *\n * Implements `PromiseLike<Page<T>>` so `await` returns the first page.\n * Implements `AsyncIterable<T>` so `for await...of` yields items.\n *\n * EC19: Uses `links.next` as an opaque cursor (never constructs cursors).\n * EC47: Terminates when `links.next` is null.\n * EC8: Resolves relative `links.next` URLs against the base URL.\n */\nexport class Paginator<T> implements PromiseLike<Page<T>>, AsyncIterable<T> {\n private readonly client: HttpClient;\n private readonly initialPath: string;\n private readonly params?: Record<string, unknown>;\n private readonly extract: PageExtractor<T>;\n\n constructor(options: PaginatorOptions<T>) {\n this.client = options.client;\n this.initialPath = options.path;\n this.params = options.params;\n this.extract = options.extract;\n }\n\n // --------------------------------------------------------------------------\n // PromiseLike — `await paginator` returns the first page.\n // --------------------------------------------------------------------------\n\n then<TResult1 = Page<T>, TResult2 = never>(\n onfulfilled?: ((value: Page<T>) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.fetchFirstPage().then(onfulfilled, onrejected);\n }\n\n // --------------------------------------------------------------------------\n // AsyncIterable — `for await (const item of paginator)` yields items.\n // --------------------------------------------------------------------------\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n for await (const page of this.pages()) {\n yield* page.data;\n }\n }\n\n // --------------------------------------------------------------------------\n // Page iterator — yields Page<T> objects.\n // --------------------------------------------------------------------------\n\n /**\n * Returns an async iterable of page objects.\n *\n * Follows `links.next` until null (EC47).\n */\n async *pages(): AsyncIterable<Page<T>> {\n let nextPath: string | null = this.initialPath;\n let isFirst = true;\n\n while (nextPath != null) {\n const response: HttpResponse<unknown> = isFirst\n ? await this.client.get(nextPath, this.params as Record<string, string>)\n : await this.client.get(nextPath);\n\n isFirst = false;\n\n const page = this.extract(response.data);\n\n // EC48: Also check for Link header as fallback.\n if (page.links.next == null) {\n const linkHeader = response.headers.get('link') ?? response.headers.get('Link');\n if (linkHeader) {\n const match = linkHeader.match(/<([^>]+)>;\\s*rel=\"next\"/);\n if (match?.[1]) {\n page.links.next = match[1];\n }\n }\n }\n\n yield page;\n\n // EC47: Terminate when links.next is null.\n nextPath = page.links.next;\n\n // EC8/19: links.next is a relative path like `/api/v1/accounts?...`.\n // The HttpClient.get() already resolves against baseUrl.\n }\n }\n\n // --------------------------------------------------------------------------\n // Internal\n // --------------------------------------------------------------------------\n\n private async fetchFirstPage(): Promise<Page<T>> {\n const response = await this.client.get<unknown>(\n this.initialPath,\n this.params as Record<string, string>,\n );\n return this.extract(response.data);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helper: extract page from common envelope shapes\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a standard page extractor for the common envelope:\n * `{ <key>: T[], links: { next: string | null } }`\n */\nexport function createPageExtractor<T>(\n dataKey: string,\n mapItem: (raw: unknown) => T,\n): PageExtractor<T> {\n return (raw: unknown): Page<T> => {\n const record =\n raw != null && typeof raw === 'object' && !Array.isArray(raw)\n ? (raw as Record<string, unknown>)\n : {};\n\n const items = Array.isArray(record[dataKey]) ? (record[dataKey] as unknown[]).map(mapItem) : [];\n\n const linksRaw =\n record.links != null && typeof record.links === 'object'\n ? (record.links as Record<string, unknown>)\n : {};\n\n const links: PaginationLinks = {\n next: typeof linksRaw.next === 'string' ? linksRaw.next : null,\n };\n\n return { data: items, links };\n };\n}\n","/**\n * Accounts resource — 10 methods.\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport {\n mapAccountDetail,\n mapAccountSummary,\n mapAirdrop,\n mapCryptoAllowance,\n mapNftAllowance,\n mapStakingReward,\n mapTokenAllowance,\n mapTokenRelationship,\n} from '../mappers/account.js';\nimport { mapTokenNft } from '../mappers/token.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport type {\n AccountDetail,\n AccountListParams,\n AccountNftsParams,\n AccountRewardsParams,\n AccountSummary,\n AccountTokensParams,\n Airdrop,\n AirdropParams,\n AllowanceCryptoParams,\n AllowanceNftParams,\n AllowanceTokenParams,\n CryptoAllowance,\n NftAllowance,\n StakingReward,\n TokenAllowance,\n TokenRelationship,\n} from '../types/accounts.js';\nimport type { TokenNft } from '../types/tokens.js';\n\nexport class AccountsResource {\n constructor(private readonly client: HttpClient) {}\n\n list(params?: AccountListParams): Paginator<AccountSummary> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/accounts',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('accounts', mapAccountSummary),\n });\n }\n\n async get(idOrAliasOrEvmAddress: string): Promise<AccountDetail> {\n const response = await this.client.get<unknown>(\n `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}`,\n );\n return mapAccountDetail(response.data);\n }\n\n getNFTs(idOrAliasOrEvmAddress: string, params?: AccountNftsParams): Paginator<TokenNft> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}/nfts`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('nfts', mapTokenNft),\n });\n }\n\n getTokens(\n idOrAliasOrEvmAddress: string,\n params?: AccountTokensParams,\n ): Paginator<TokenRelationship> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}/tokens`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('tokens', mapTokenRelationship),\n });\n }\n\n getRewards(\n idOrAliasOrEvmAddress: string,\n params?: AccountRewardsParams,\n ): Paginator<StakingReward> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}/rewards`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('rewards', mapStakingReward),\n });\n }\n\n getCryptoAllowances(\n idOrAliasOrEvmAddress: string,\n params?: AllowanceCryptoParams,\n ): Paginator<CryptoAllowance> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}/allowances/crypto`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('allowances', mapCryptoAllowance),\n });\n }\n\n getTokenAllowances(\n idOrAliasOrEvmAddress: string,\n params?: AllowanceTokenParams,\n ): Paginator<TokenAllowance> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}/allowances/tokens`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('allowances', mapTokenAllowance),\n });\n }\n\n getNftAllowances(\n idOrAliasOrEvmAddress: string,\n params?: AllowanceNftParams,\n ): Paginator<NftAllowance> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}/allowances/nfts`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('allowances', mapNftAllowance),\n });\n }\n\n getOutstandingAirdrops(\n idOrAliasOrEvmAddress: string,\n params?: AirdropParams,\n ): Paginator<Airdrop> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}/airdrops/outstanding`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('airdrops', mapAirdrop),\n });\n }\n\n getPendingAirdrops(idOrAliasOrEvmAddress: string, params?: AirdropParams): Paginator<Airdrop> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/accounts/${encodeURIComponent(idOrAliasOrEvmAddress)}/airdrops/pending`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('airdrops', mapAirdrop),\n });\n }\n}\n","/**\n * Balances resource — 1 method.\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport { arr, asRecord, strReq } from '../mappers/common.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport type { BalanceEntry, BalanceListParams } from '../types/balances.js';\nimport type { TokenBalance } from '../types/common.js';\n\nfunction mapBalanceEntry(raw: unknown): BalanceEntry {\n const r = asRecord(raw);\n return {\n account: strReq(r, 'account'),\n balance: strReq(r, 'balance'),\n tokens: arr(r, 'tokens').map((t) => {\n const tr = asRecord(t);\n return { token_id: strReq(tr, 'token_id'), balance: strReq(tr, 'balance') } as TokenBalance;\n }),\n };\n}\n\nexport class BalancesResource {\n constructor(private readonly client: HttpClient) {}\n\n list(params?: BalanceListParams): Paginator<BalanceEntry> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/balances',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('balances', mapBalanceEntry),\n });\n }\n}\n","/**\n * Block response mapper.\n * @internal\n */\n\nimport type { Block } from '../types/blocks.js';\nimport { asRecord, num, str, strReq } from './common.js';\n\nexport function mapBlock(raw: unknown): Block {\n const r = asRecord(raw);\n const tsRaw = asRecord(r.timestamp);\n return {\n count: num(r, 'count'),\n gas_used: strReq(r, 'gas_used'),\n hapi_version: strReq(r, 'hapi_version'),\n hash: strReq(r, 'hash'),\n logs_bloom: strReq(r, 'logs_bloom'),\n name: strReq(r, 'name'),\n number: num(r, 'number'),\n previous_hash: strReq(r, 'previous_hash'),\n size: num(r, 'size'),\n /** EC15/28: TimestampRange object. */\n timestamp: { from: strReq(tsRaw, 'from'), to: str(tsRaw, 'to') },\n };\n}\n","/**\n * Blocks resource — 2 methods.\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport { mapBlock } from '../mappers/block.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport type { Block, BlockListParams } from '../types/blocks.js';\n\nexport class BlocksResource {\n constructor(private readonly client: HttpClient) {}\n\n list(params?: BlockListParams): Paginator<Block> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/blocks',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('blocks', mapBlock),\n });\n }\n\n async get(hashOrNumber: string | number): Promise<Block> {\n const response = await this.client.get<unknown>(\n `/api/v1/blocks/${encodeURIComponent(String(hashOrNumber))}`,\n );\n return mapBlock(response.data);\n }\n}\n","/**\n * Contract response mappers.\n * @internal\n */\n\nimport type { HieroKey, TimestampRange } from '../types/common.js';\nimport type {\n ContractAction,\n ContractDetail,\n ContractLog,\n ContractResult,\n ContractSummary,\n StateChange,\n} from '../types/contracts.js';\nimport { arr, asRecord, bool, decodeHexString, num, str, strReq } from './common.js';\n\nfunction mapKey(raw: unknown): HieroKey | null {\n if (raw == null) return null;\n const r = asRecord(raw);\n return { _type: strReq(r, '_type'), key: strReq(r, 'key') } as HieroKey;\n}\n\nfunction mapTimestampRange(raw: unknown): TimestampRange {\n const r = asRecord(raw);\n return { from: strReq(r, 'from'), to: str(r, 'to') };\n}\n\nexport function mapContractSummary(raw: unknown): ContractSummary {\n const r = asRecord(raw);\n return {\n admin_key: mapKey(r.admin_key),\n auto_renew_account: str(r, 'auto_renew_account'),\n auto_renew_period: str(r, 'auto_renew_period'),\n contract_id: strReq(r, 'contract_id'),\n created_timestamp: strReq(r, 'created_timestamp'),\n deleted: bool(r, 'deleted'),\n evm_address: strReq(r, 'evm_address'),\n expiration_timestamp: str(r, 'expiration_timestamp'),\n file_id: str(r, 'file_id'),\n max_automatic_token_associations: num(r, 'max_automatic_token_associations'),\n memo: strReq(r, 'memo'),\n nonce: strReq(r, 'nonce'),\n obtainer_id: str(r, 'obtainer_id'),\n permanent_removal: r.permanent_removal == null ? null : bool(r, 'permanent_removal'),\n proxy_account_id: str(r, 'proxy_account_id'),\n timestamp: mapTimestampRange(r.timestamp),\n };\n}\n\nexport function mapContractDetail(raw: unknown): ContractDetail {\n const r = asRecord(raw);\n const summary = mapContractSummary(raw);\n return {\n ...summary,\n bytecode: strReq(r, 'bytecode'),\n runtime_bytecode: strReq(r, 'runtime_bytecode'),\n };\n}\n\nexport function mapContractLog(raw: unknown): ContractLog {\n const r = asRecord(raw);\n return {\n address: strReq(r, 'address'),\n bloom: strReq(r, 'bloom'),\n contract_id: strReq(r, 'contract_id'),\n data: strReq(r, 'data'),\n index: num(r, 'index'),\n topics: arr<string>(r, 'topics'),\n root_contract_id: str(r, 'root_contract_id'),\n timestamp: strReq(r, 'timestamp'),\n block_hash: strReq(r, 'block_hash'),\n block_number: num(r, 'block_number'),\n transaction_hash: strReq(r, 'transaction_hash'),\n transaction_index: num(r, 'transaction_index'),\n };\n}\n\nfunction mapStateChange(raw: unknown): StateChange {\n const r = asRecord(raw);\n return {\n address: strReq(r, 'address'),\n contract_id: strReq(r, 'contract_id'),\n slot: strReq(r, 'slot'),\n value_read: strReq(r, 'value_read'),\n value_written: str(r, 'value_written'),\n };\n}\n\nexport function mapContractResult(raw: unknown): ContractResult {\n const r = asRecord(raw);\n const errorMessage = str(r, 'error_message');\n return {\n access_list: str(r, 'access_list'),\n address: strReq(r, 'address'),\n amount: strReq(r, 'amount'),\n block_gas_used: strReq(r, 'block_gas_used'),\n block_hash: strReq(r, 'block_hash'),\n block_number: num(r, 'block_number'),\n bloom: strReq(r, 'bloom'),\n call_result: str(r, 'call_result'),\n chain_id: strReq(r, 'chain_id'),\n contract_id: str(r, 'contract_id'),\n created_contract_ids: arr<string>(r, 'created_contract_ids'),\n error_message: errorMessage,\n /** EC24: Hex-decoded human-readable error. */\n error_message_decoded: decodeHexString(errorMessage),\n failed_initcode: str(r, 'failed_initcode'),\n from: strReq(r, 'from'),\n function_parameters: strReq(r, 'function_parameters'),\n gas_consumed: str(r, 'gas_consumed'),\n gas_limit: strReq(r, 'gas_limit'),\n gas_price: strReq(r, 'gas_price'),\n gas_used: strReq(r, 'gas_used'),\n hash: strReq(r, 'hash'),\n logs: arr(r, 'logs').map(mapContractLog),\n max_fee_per_gas: strReq(r, 'max_fee_per_gas'),\n max_priority_fee_per_gas: strReq(r, 'max_priority_fee_per_gas'),\n nonce: num(r, 'nonce'),\n r: strReq(r, 'r'),\n result: strReq(r, 'result'),\n s: strReq(r, 's'),\n state_changes: arr(r, 'state_changes').map(mapStateChange),\n status: strReq(r, 'status'),\n timestamp: strReq(r, 'timestamp'),\n to: str(r, 'to'),\n transaction_index: num(r, 'transaction_index'),\n type: num(r, 'type'),\n v: num(r, 'v'),\n };\n}\n\nexport function mapContractAction(raw: unknown): ContractAction {\n const r = asRecord(raw);\n return {\n call_depth: num(r, 'call_depth'),\n call_operation_type: strReq(r, 'call_operation_type'),\n call_type: strReq(r, 'call_type'),\n caller: strReq(r, 'caller'),\n caller_type: strReq(r, 'caller_type'),\n from: strReq(r, 'from'),\n gas: strReq(r, 'gas'),\n gas_used: strReq(r, 'gas_used'),\n index: num(r, 'index'),\n input: str(r, 'input'),\n recipient: str(r, 'recipient'),\n recipient_type: str(r, 'recipient_type'),\n result_data: str(r, 'result_data'),\n result_data_type: strReq(r, 'result_data_type'),\n timestamp: strReq(r, 'timestamp'),\n to: str(r, 'to'),\n value: strReq(r, 'value'),\n };\n}\n","/**\n * Contracts resource — 12 methods.\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport { asRecord, strReq } from '../mappers/common.js';\nimport {\n mapContractAction,\n mapContractDetail,\n mapContractLog,\n mapContractResult,\n mapContractSummary,\n} from '../mappers/contract.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport type {\n ContractAction,\n ContractCallRequest,\n ContractCallResponse,\n ContractDetail,\n ContractListParams,\n ContractLog,\n ContractLogsParams,\n ContractResult,\n ContractResultsParams,\n ContractStateParams,\n ContractSummary,\n StateChange,\n} from '../types/contracts.js';\n\nfunction mapStateChange(raw: unknown): StateChange {\n const r = asRecord(raw);\n return {\n address: strReq(r, 'address'),\n contract_id: strReq(r, 'contract_id'),\n slot: strReq(r, 'slot'),\n value_read: strReq(r, 'value_read'),\n value_written: r.value_written == null ? null : strReq(r, 'value_written'),\n };\n}\n\nexport class ContractsResource {\n constructor(private readonly client: HttpClient) {}\n\n list(params?: ContractListParams): Paginator<ContractSummary> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/contracts',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('contracts', mapContractSummary),\n });\n }\n\n async get(contractIdOrAddress: string): Promise<ContractDetail> {\n const response = await this.client.get<unknown>(\n `/api/v1/contracts/${encodeURIComponent(contractIdOrAddress)}`,\n );\n return mapContractDetail(response.data);\n }\n\n /**\n * POST /api/v1/contracts/call — smart contract read-only simulation.\n *\n * EC29/51/130-133.\n */\n async call(request: ContractCallRequest): Promise<ContractCallResponse> {\n const response = await this.client.post<unknown>('/api/v1/contracts/call', request);\n const r = asRecord(response.data);\n return { result: strReq(r, 'result') };\n }\n\n getResults(params?: ContractResultsParams): Paginator<ContractResult> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/contracts/results',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('results', mapContractResult),\n });\n }\n\n getResultsByContract(\n contractIdOrAddress: string,\n params?: ContractResultsParams,\n ): Paginator<ContractResult> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/contracts/${encodeURIComponent(contractIdOrAddress)}/results`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('results', mapContractResult),\n });\n }\n\n async getResultByTimestamp(\n contractIdOrAddress: string,\n timestamp: string,\n ): Promise<ContractResult> {\n const response = await this.client.get<unknown>(\n `/api/v1/contracts/${encodeURIComponent(contractIdOrAddress)}/results/${encodeURIComponent(timestamp)}`,\n );\n return mapContractResult(response.data);\n }\n\n async getResultByTransactionIdOrHash(transactionIdOrHash: string): Promise<ContractResult> {\n const response = await this.client.get<unknown>(\n `/api/v1/contracts/results/${encodeURIComponent(transactionIdOrHash)}`,\n );\n return mapContractResult(response.data);\n }\n\n getActions(transactionIdOrHash: string): Paginator<ContractAction> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/contracts/results/${encodeURIComponent(transactionIdOrHash)}/actions`,\n extract: createPageExtractor('actions', mapContractAction),\n });\n }\n\n getLogs(params?: ContractLogsParams): Paginator<ContractLog> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/contracts/results/logs',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('logs', mapContractLog),\n });\n }\n\n getLogsByContract(\n contractIdOrAddress: string,\n params?: ContractLogsParams,\n ): Paginator<ContractLog> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/contracts/${encodeURIComponent(contractIdOrAddress)}/results/logs`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('logs', mapContractLog),\n });\n }\n\n getState(contractIdOrAddress: string, params?: ContractStateParams): Paginator<StateChange> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/contracts/${encodeURIComponent(contractIdOrAddress)}/state`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('state', mapStateChange),\n });\n }\n\n async getOpcodes(transactionIdOrHash: string): Promise<unknown> {\n const response = await this.client.get<unknown>(\n `/api/v1/contracts/results/${encodeURIComponent(transactionIdOrHash)}/opcodes`,\n );\n return response.data;\n }\n}\n","/**\n * Network response mappers.\n * @internal\n */\n\nimport type { TimestampRange } from '../types/common.js';\nimport type {\n ExchangeRate,\n ExchangeRateSet,\n Fee,\n FeeSchedule,\n NetworkNode,\n NetworkStake,\n ServiceEndpoint,\n Supply,\n} from '../types/network.js';\nimport { arr, asRecord, num, str, strReq } from './common.js';\n\nfunction mapTimestampRange(raw: unknown): TimestampRange {\n const r = asRecord(raw);\n return { from: strReq(r, 'from'), to: str(r, 'to') };\n}\n\nfunction mapServiceEndpoint(raw: unknown): ServiceEndpoint {\n const r = asRecord(raw);\n return {\n ip_address_v4: strReq(r, 'ip_address_v4'),\n port: num(r, 'port'),\n domain_name: strReq(r, 'domain_name'),\n };\n}\n\nexport function mapNetworkNode(raw: unknown): NetworkNode {\n const r = asRecord(raw);\n return {\n admin_key: r.admin_key ?? null,\n description: strReq(r, 'description'),\n file_id: strReq(r, 'file_id'),\n max_stake: strReq(r, 'max_stake'),\n memo: strReq(r, 'memo'),\n min_stake: strReq(r, 'min_stake'),\n node_account_id: strReq(r, 'node_account_id'),\n node_id: num(r, 'node_id'),\n node_cert_hash: strReq(r, 'node_cert_hash'),\n public_key: strReq(r, 'public_key'),\n reward_rate_start: strReq(r, 'reward_rate_start'),\n service_endpoints: arr(r, 'service_endpoints').map(mapServiceEndpoint),\n stake: strReq(r, 'stake'),\n stake_not_rewarded: strReq(r, 'stake_not_rewarded'),\n stake_rewarded: strReq(r, 'stake_rewarded'),\n staking_period: mapTimestampRange(r.staking_period),\n timestamp: mapTimestampRange(r.timestamp),\n };\n}\n\nexport function mapNetworkStake(raw: unknown): NetworkStake {\n const r = asRecord(raw);\n return {\n max_stake_rewarded: strReq(r, 'max_stake_rewarded'),\n max_staking_reward_rate_per_hbar: strReq(r, 'max_staking_reward_rate_per_hbar'),\n max_total_reward: strReq(r, 'max_total_reward'),\n node_reward_fee_fraction: num(r, 'node_reward_fee_fraction'),\n reserved_staking_rewards: strReq(r, 'reserved_staking_rewards'),\n reward_balance_threshold: strReq(r, 'reward_balance_threshold'),\n stake_total: strReq(r, 'stake_total'),\n staking_period: mapTimestampRange(r.staking_period),\n staking_period_duration: strReq(r, 'staking_period_duration'),\n staking_periods_stored: strReq(r, 'staking_periods_stored'),\n staking_reward_fee_fraction: num(r, 'staking_reward_fee_fraction'),\n staking_reward_rate: strReq(r, 'staking_reward_rate'),\n staking_start_threshold: strReq(r, 'staking_start_threshold'),\n unreserved_staking_reward_balance: strReq(r, 'unreserved_staking_reward_balance'),\n };\n}\n\nexport function mapExchangeRate(raw: unknown): ExchangeRate {\n const r = asRecord(raw);\n return {\n cent_equivalent: num(r, 'cent_equivalent'),\n expiration_time: num(r, 'expiration_time'),\n hbar_equivalent: num(r, 'hbar_equivalent'),\n };\n}\n\nexport function mapExchangeRateSet(raw: unknown): ExchangeRateSet {\n const r = asRecord(raw);\n return {\n current_rate: mapExchangeRate(r.current_rate),\n next_rate: mapExchangeRate(r.next_rate),\n timestamp: strReq(r, 'timestamp'),\n };\n}\n\nexport function mapSupply(raw: unknown): Supply {\n const r = asRecord(raw);\n return {\n released_supply: strReq(r, 'released_supply'),\n timestamp: strReq(r, 'timestamp'),\n total_supply: strReq(r, 'total_supply'),\n };\n}\n\nfunction mapFee(raw: unknown): Fee {\n const r = asRecord(raw);\n return {\n gas: strReq(r, 'gas'),\n transaction_type: strReq(r, 'transaction_type'),\n };\n}\n\nexport function mapFeeSchedule(raw: unknown): FeeSchedule {\n const r = asRecord(raw);\n return {\n current: r.current != null ? arr(r, 'current').map(mapFee) : undefined,\n next: r.next != null ? arr(r, 'next').map(mapFee) : undefined,\n timestamp: strReq(r, 'timestamp'),\n };\n}\n","/**\n * Network resource — 6 methods.\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport {\n mapExchangeRateSet,\n mapFeeSchedule,\n mapNetworkNode,\n mapNetworkStake,\n mapSupply,\n} from '../mappers/network.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport type {\n ExchangeRateSet,\n FeeSchedule,\n NetworkFeeParams,\n NetworkNode,\n NetworkNodeParams,\n NetworkStake,\n NetworkSupplyParams,\n Supply,\n} from '../types/network.js';\n\nexport class NetworkResource {\n constructor(private readonly client: HttpClient) {}\n\n async getExchangeRate(): Promise<ExchangeRateSet> {\n const response = await this.client.get<unknown>('/api/v1/network/exchangerate');\n return mapExchangeRateSet(response.data);\n }\n\n async getFees(params?: NetworkFeeParams): Promise<FeeSchedule> {\n const response = await this.client.get<unknown>(\n '/api/v1/network/fees',\n params as Record<string, string>,\n );\n return mapFeeSchedule(response.data);\n }\n\n /**\n * POST /api/v1/network/fees — estimate fees from protobuf payload.\n *\n * EC52: Accepts raw Uint8Array (user must serialize protobuf externally).\n */\n async estimateFees(body: Uint8Array): Promise<unknown> {\n const response = await this.client.post<unknown>('/api/v1/network/fees', body, {\n headers: { 'Content-Type': 'application/protobuf' },\n });\n return response.data;\n }\n\n getNodes(params?: NetworkNodeParams): Paginator<NetworkNode> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/network/nodes',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('nodes', mapNetworkNode),\n });\n }\n\n async getStake(): Promise<NetworkStake> {\n const response = await this.client.get<unknown>('/api/v1/network/stake');\n return mapNetworkStake(response.data);\n }\n\n async getSupply(params?: NetworkSupplyParams): Promise<Supply> {\n const response = await this.client.get<unknown>(\n '/api/v1/network/supply',\n params as Record<string, string>,\n );\n return mapSupply(response.data);\n }\n}\n","/**\n * Schedule response mapper.\n * @internal\n */\n\nimport type { HieroKey } from '../types/common.js';\nimport type { Schedule, ScheduleSignature } from '../types/schedules.js';\nimport { arr, asRecord, bool, str, strReq } from './common.js';\n\nfunction mapKey(raw: unknown): HieroKey | null {\n if (raw == null) return null;\n const r = asRecord(raw);\n return { _type: strReq(r, '_type'), key: strReq(r, 'key') } as HieroKey;\n}\n\nfunction mapSignature(raw: unknown): ScheduleSignature {\n const r = asRecord(raw);\n return {\n consensus_timestamp: strReq(r, 'consensus_timestamp'),\n public_key_prefix: strReq(r, 'public_key_prefix'),\n signature: strReq(r, 'signature'),\n type: strReq(r, 'type'),\n };\n}\n\n/** EC58: Same type for list and detail. */\nexport function mapSchedule(raw: unknown): Schedule {\n const r = asRecord(raw);\n return {\n admin_key: mapKey(r.admin_key),\n consensus_timestamp: str(r, 'consensus_timestamp'),\n creator_account_id: strReq(r, 'creator_account_id'),\n deleted: bool(r, 'deleted'),\n executed_timestamp: str(r, 'executed_timestamp'),\n expiration_time: str(r, 'expiration_time'),\n memo: strReq(r, 'memo'),\n payer_account_id: strReq(r, 'payer_account_id'),\n schedule_id: strReq(r, 'schedule_id'),\n signatures: arr(r, 'signatures').map(mapSignature),\n transaction_body: strReq(r, 'transaction_body'),\n wait_for_expiry: bool(r, 'wait_for_expiry'),\n };\n}\n","/**\n * Schedules resource — 2 methods.\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport { mapSchedule } from '../mappers/schedule.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport type { Schedule, ScheduleListParams } from '../types/schedules.js';\n\nexport class SchedulesResource {\n constructor(private readonly client: HttpClient) {}\n\n list(params?: ScheduleListParams): Paginator<Schedule> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/schedules',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('schedules', mapSchedule),\n });\n }\n\n async get(scheduleId: string): Promise<Schedule> {\n const response = await this.client.get<unknown>(\n `/api/v1/schedules/${encodeURIComponent(scheduleId)}`,\n );\n return mapSchedule(response.data);\n }\n}\n","/**\n * Transaction response mappers.\n *\n * EC21/150/151: `.get()` must unwrap `{ transactions: [...] }` → single object.\n *\n * @internal\n */\n\nimport type { NftTransaction, Transaction } from '../types/transactions.js';\nimport { arr, asRecord, bool, num, str, strReq } from './common.js';\n\nexport function mapTransaction(raw: unknown): Transaction {\n const r = asRecord(raw);\n return {\n bytes: str(r, 'bytes'),\n charged_tx_fee: strReq(r, 'charged_tx_fee'),\n consensus_timestamp: strReq(r, 'consensus_timestamp'),\n entity_id: str(r, 'entity_id'),\n max_fee: strReq(r, 'max_fee'),\n memo_base64: strReq(r, 'memo_base64'),\n name: strReq(r, 'name'),\n nft_transfers: arr(r, 'nft_transfers').map((t) => {\n const tr = asRecord(t);\n return {\n is_approval: bool(tr, 'is_approval'),\n receiver_account_id: str(tr, 'receiver_account_id'),\n sender_account_id: str(tr, 'sender_account_id'),\n serial_number: strReq(tr, 'serial_number'),\n token_id: strReq(tr, 'token_id'),\n };\n }),\n node: str(r, 'node'),\n nonce: num(r, 'nonce'),\n parent_consensus_timestamp: str(r, 'parent_consensus_timestamp'),\n result: strReq(r, 'result'),\n scheduled: bool(r, 'scheduled'),\n staking_reward_transfers: arr(r, 'staking_reward_transfers').map((s) => {\n const sr = asRecord(s);\n return { account: strReq(sr, 'account'), amount: strReq(sr, 'amount') };\n }),\n token_transfers: arr(r, 'token_transfers').map((t) => {\n const tr = asRecord(t);\n return {\n account: strReq(tr, 'account'),\n amount: strReq(tr, 'amount'),\n is_approval: bool(tr, 'is_approval'),\n token_id: strReq(tr, 'token_id'),\n };\n }),\n transaction_hash: strReq(r, 'transaction_hash'),\n transaction_id: strReq(r, 'transaction_id'),\n transfers: arr(r, 'transfers').map((t) => {\n const tr = asRecord(t);\n return {\n account: strReq(tr, 'account'),\n amount: strReq(tr, 'amount'),\n is_approval: bool(tr, 'is_approval'),\n };\n }),\n valid_duration_seconds: strReq(r, 'valid_duration_seconds'),\n valid_start_timestamp: strReq(r, 'valid_start_timestamp'),\n };\n}\n\n/**\n * Unwraps the `{ transactions: [...] }` envelope returned by GET /transactions/{id}.\n *\n * EC21/150/151: Detail endpoint wraps in array. `.get()` extracts `transactions[0]`.\n */\nexport function unwrapTransaction(raw: unknown): Transaction {\n const r = asRecord(raw);\n const txns = arr(r, 'transactions');\n if (txns.length === 0) {\n throw new Error('Transaction response contained empty transactions array');\n }\n return mapTransaction(txns[0]);\n}\n\n/** EC77: NFT transaction has a separate shape. */\nexport function mapNftTransaction(raw: unknown): NftTransaction {\n const r = asRecord(raw);\n return {\n consensus_timestamp: strReq(r, 'consensus_timestamp'),\n is_approval: bool(r, 'is_approval'),\n nonce: num(r, 'nonce'),\n receiver_account_id: str(r, 'receiver_account_id'),\n sender_account_id: str(r, 'sender_account_id'),\n transaction_id: strReq(r, 'transaction_id'),\n type: strReq(r, 'type'),\n };\n}\n","/**\n * Tokens resource — 6 methods.\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport {\n mapTokenBalanceEntry,\n mapTokenDetail,\n mapTokenNft,\n mapTokenSummary,\n} from '../mappers/token.js';\nimport { mapNftTransaction } from '../mappers/transaction.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport type {\n TokenBalanceEntry,\n TokenBalanceParams,\n TokenDetail,\n TokenListParams,\n TokenNft,\n TokenNftListParams,\n TokenSummary,\n} from '../types/tokens.js';\nimport type { NftTransaction, TransactionListParams } from '../types/transactions.js';\n\nexport class TokensResource {\n constructor(private readonly client: HttpClient) {}\n\n list(params?: TokenListParams): Paginator<TokenSummary> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/tokens',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('tokens', mapTokenSummary),\n });\n }\n\n async get(tokenId: string): Promise<TokenDetail> {\n const response = await this.client.get<unknown>(\n `/api/v1/tokens/${encodeURIComponent(tokenId)}`,\n );\n return mapTokenDetail(response.data);\n }\n\n getBalances(tokenId: string, params?: TokenBalanceParams): Paginator<TokenBalanceEntry> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/tokens/${encodeURIComponent(tokenId)}/balances`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('balances', mapTokenBalanceEntry),\n });\n }\n\n getNFTs(tokenId: string, params?: TokenNftListParams): Paginator<TokenNft> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/tokens/${encodeURIComponent(tokenId)}/nfts`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('nfts', mapTokenNft),\n });\n }\n\n async getNFTBySerial(tokenId: string, serialNumber: number | string): Promise<TokenNft> {\n const response = await this.client.get<unknown>(\n `/api/v1/tokens/${encodeURIComponent(tokenId)}/nfts/${serialNumber}`,\n );\n return mapTokenNft(response.data);\n }\n\n getNFTTransactions(\n tokenId: string,\n serialNumber: number | string,\n params?: TransactionListParams,\n ): Paginator<NftTransaction> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/tokens/${encodeURIComponent(tokenId)}/nfts/${serialNumber}/transactions`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('transactions', mapNftTransaction),\n });\n }\n}\n","/**\n * Topic response mapper.\n * @internal\n */\n\nimport type { ChunkInfo, TopicMessage } from '../types/topics.js';\nimport { asRecord, bool, decodeBase64, num, strReq } from './common.js';\n\nfunction mapChunkInfo(raw: unknown): ChunkInfo | null {\n if (raw == null) return null;\n const r = asRecord(raw);\n const initTxRaw = asRecord(r.initial_transaction_id);\n return {\n initial_transaction_id: {\n account_id: strReq(initTxRaw, 'account_id'),\n nonce: num(initTxRaw, 'nonce'),\n scheduled: bool(initTxRaw, 'scheduled'),\n transaction_valid_start: strReq(initTxRaw, 'transaction_valid_start'),\n },\n number: num(r, 'number'),\n total: num(r, 'total'),\n };\n}\n\n/**\n * Maps a raw topic message to a `TopicMessage`.\n *\n * EC3/18: Auto-decodes Base64 `message` and `running_hash` to `Uint8Array`.\n */\nexport function mapTopicMessage(raw: unknown): TopicMessage {\n const r = asRecord(raw);\n const messageStr = strReq(r, 'message');\n const runningHashStr = strReq(r, 'running_hash');\n return {\n chunk_info: mapChunkInfo(r.chunk_info),\n consensus_timestamp: strReq(r, 'consensus_timestamp'),\n message: decodeBase64(messageStr),\n payer_account_id: strReq(r, 'payer_account_id'),\n running_hash: decodeBase64(runningHashStr),\n running_hash_version: num(r, 'running_hash_version'),\n sequence_number: strReq(r, 'sequence_number'),\n topic_id: strReq(r, 'topic_id'),\n };\n}\n","/**\n * TopicStream — adaptive polling for Hedera Consensus Service topic messages.\n *\n * @packageDocumentation\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport { mapTopicMessage } from '../mappers/topic.js';\nimport type { TopicMessage } from '../types/topics.js';\n\nexport interface TopicStreamOptions {\n /** Starting timestamp cursor. Default: current time. */\n startTimestamp?: string;\n /** Base polling interval in ms. Default: 500ms (active), backs off to 5s. */\n interval?: number;\n /** Maximum items per poll request. Default: 100. */\n limit?: number;\n /** AbortSignal for cancellation. */\n signal?: AbortSignal;\n}\n\n/**\n * Adaptive polling stream for topic messages.\n *\n * - Polls at high frequency (500ms) when messages are flowing.\n * - Backs off exponentially (up to 5s) when no messages arrive.\n * - Cancellable via `AbortController`.\n * - Rate-limit aware (shares the HttpClient's token bucket).\n */\nexport class TopicStream implements AsyncIterable<TopicMessage> {\n private readonly client: HttpClient;\n private readonly topicId: string;\n private readonly options: Required<Omit<TopicStreamOptions, 'signal'>> & { signal?: AbortSignal };\n\n /** Minimum polling interval (ms). */\n private static readonly MIN_INTERVAL = 500;\n /** Maximum polling interval (ms). */\n private static readonly MAX_INTERVAL = 5000;\n /** Factor by which interval increases on empty polls. */\n private static readonly BACKOFF_FACTOR = 1.5;\n\n constructor(client: HttpClient, topicId: string, options: TopicStreamOptions = {}) {\n this.client = client;\n this.topicId = topicId;\n this.options = {\n startTimestamp: options.startTimestamp ?? Math.floor(Date.now() / 1000).toString(),\n interval: options.interval ?? TopicStream.MIN_INTERVAL,\n limit: options.limit ?? 100,\n signal: options.signal,\n };\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<TopicMessage> {\n let cursor = this.options.startTimestamp;\n let currentInterval = this.options.interval;\n\n while (!this.options.signal?.aborted) {\n try {\n const response = await this.client.get<unknown>(\n `/api/v1/topics/${this.topicId}/messages`,\n {\n timestamp: `gt:${cursor}`,\n limit: String(this.options.limit),\n order: 'asc',\n },\n { signal: this.options.signal },\n );\n\n const raw = response.data as Record<string, unknown>;\n const messages = Array.isArray(raw.messages) ? raw.messages : [];\n\n if (messages.length > 0) {\n // Active flow — reset interval to minimum.\n currentInterval = TopicStream.MIN_INTERVAL;\n\n for (const msg of messages) {\n const mapped = mapTopicMessage(msg);\n yield mapped;\n cursor = mapped.consensus_timestamp;\n }\n } else {\n // No messages — back off.\n currentInterval = Math.min(\n currentInterval * TopicStream.BACKOFF_FACTOR,\n TopicStream.MAX_INTERVAL,\n );\n }\n } catch (_error: unknown) {\n // On abort, exit gracefully.\n if (this.options.signal?.aborted) return;\n\n // On network errors, back off and retry.\n currentInterval = Math.min(\n currentInterval * TopicStream.BACKOFF_FACTOR * 2,\n TopicStream.MAX_INTERVAL,\n );\n }\n\n // Wait before next poll.\n await this.sleep(currentInterval);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, ms);\n // If the signal aborts, resolve immediately.\n this.options.signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n resolve();\n },\n { once: true },\n );\n });\n }\n}\n","/**\n * Topics resource — 4 methods + stream.\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport { asRecord, bool, str, strReq } from '../mappers/common.js';\nimport { mapTopicMessage } from '../mappers/topic.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport { TopicStream } from '../pagination/stream.js';\nimport type {\n TopicInfo,\n TopicMessage,\n TopicMessageParams,\n TopicStreamOptions,\n} from '../types/topics.js';\n\nfunction mapTopicInfo(raw: unknown): TopicInfo {\n const r = asRecord(raw);\n const tsRaw = asRecord(r.timestamp);\n return {\n admin_key: r.admin_key ?? null,\n auto_renew_account: str(r, 'auto_renew_account'),\n auto_renew_period: str(r, 'auto_renew_period'),\n created_timestamp: strReq(r, 'created_timestamp'),\n deleted: bool(r, 'deleted'),\n memo: strReq(r, 'memo'),\n submit_key: r.submit_key ?? null,\n timestamp: { from: strReq(tsRaw, 'from'), to: str(tsRaw, 'to') },\n topic_id: strReq(r, 'topic_id'),\n };\n}\n\nexport class TopicsResource {\n constructor(private readonly client: HttpClient) {}\n\n async get(topicId: string): Promise<TopicInfo> {\n const response = await this.client.get<unknown>(\n `/api/v1/topics/${encodeURIComponent(topicId)}`,\n );\n return mapTopicInfo(response.data);\n }\n\n getMessages(topicId: string, params?: TopicMessageParams): Paginator<TopicMessage> {\n return new Paginator({\n client: this.client,\n path: `/api/v1/topics/${encodeURIComponent(topicId)}/messages`,\n params: params as Record<string, unknown>,\n extract: createPageExtractor('messages', mapTopicMessage),\n });\n }\n\n async getMessageBySequence(\n topicId: string,\n sequenceNumber: number | string,\n ): Promise<TopicMessage> {\n const response = await this.client.get<unknown>(\n `/api/v1/topics/${encodeURIComponent(topicId)}/messages/${sequenceNumber}`,\n );\n return mapTopicMessage(response.data);\n }\n\n async getMessageByTimestamp(timestamp: string): Promise<TopicMessage> {\n const response = await this.client.get<unknown>(\n `/api/v1/topics/messages/${encodeURIComponent(timestamp)}`,\n );\n return mapTopicMessage(response.data);\n }\n\n stream(topicId: string, options?: TopicStreamOptions): TopicStream {\n return new TopicStream(this.client, topicId, options);\n }\n}\n","/**\n * Transactions resource — 2 methods.\n *\n * EC21/150/151: `.get()` unwraps `{ transactions: [...] }` envelope.\n *\n * @internal\n */\n\nimport type { HttpClient } from '../http/client.js';\nimport { mapTransaction, unwrapTransaction } from '../mappers/transaction.js';\nimport { createPageExtractor, Paginator } from '../pagination/paginator.js';\nimport type {\n Transaction,\n TransactionGetParams,\n TransactionListParams,\n} from '../types/transactions.js';\n\nexport class TransactionsResource {\n constructor(private readonly client: HttpClient) {}\n\n list(params?: TransactionListParams): Paginator<Transaction> {\n return new Paginator({\n client: this.client,\n path: '/api/v1/transactions',\n params: params as Record<string, unknown>,\n extract: createPageExtractor('transactions', mapTransaction),\n });\n }\n\n /**\n * Get a transaction by ID.\n *\n * EC21/150/151: The API returns `{ transactions: [{ ... }] }`.\n * This method unwraps to return the single transaction.\n */\n async get(transactionId: string, params?: TransactionGetParams): Promise<Transaction> {\n const response = await this.client.get<unknown>(\n `/api/v1/transactions/${encodeURIComponent(transactionId)}`,\n params as Record<string, string>,\n );\n return unwrapTransaction(response.data);\n }\n}\n","/**\n * MirrorNodeClient — the main entrypoint for the Hiero Mirror Client SDK.\n *\n * ```ts\n * import { MirrorNodeClient } from '@satianurag/hiero-mirror-client';\n *\n * const client = new MirrorNodeClient({ network: 'testnet' });\n * const account = await client.accounts.get('0.0.1234');\n * ```\n *\n * @packageDocumentation\n */\n\nimport { HttpClient, type HttpClientOptions, type Logger } from './http/client.js';\nimport { AccountsResource } from './resources/accounts.js';\nimport { BalancesResource } from './resources/balances.js';\nimport { BlocksResource } from './resources/blocks.js';\nimport { ContractsResource } from './resources/contracts.js';\nimport { NetworkResource } from './resources/network.js';\nimport { SchedulesResource } from './resources/schedules.js';\nimport { TokensResource } from './resources/tokens.js';\nimport { TopicsResource } from './resources/topics.js';\nimport { TransactionsResource } from './resources/transactions.js';\n\n// ---------------------------------------------------------------------------\n// Network presets\n// ---------------------------------------------------------------------------\n\n/**\n * Built-in network presets for the Hedera/Hiero Mirror Node.\n */\nexport type HieroNetwork = 'mainnet' | 'testnet' | 'previewnet';\n\nconst NETWORK_URLS: Record<HieroNetwork, string> = {\n mainnet: 'https://mainnet-public.mirrornode.hedera.com',\n testnet: 'https://testnet.mirrornode.hedera.com',\n previewnet: 'https://previewnet.mirrornode.hedera.com',\n};\n\n// ---------------------------------------------------------------------------\n// Client options\n// ---------------------------------------------------------------------------\n\nexport interface MirrorNodeClientOptions {\n /**\n * Network preset. Mutually exclusive with `baseUrl`.\n *\n * If neither `network` nor `baseUrl` is provided, defaults to `'mainnet'`.\n */\n network?: HieroNetwork;\n\n /**\n * Custom base URL. Mutually exclusive with `network`.\n *\n * Useful for self-hosted mirror nodes or proxies.\n */\n baseUrl?: string;\n\n /** Request timeout in ms. Default: `30_000`. */\n timeout?: number;\n\n /** Maximum retry attempts for retryable failures. Default: `2`. */\n maxRetries?: number;\n\n /** Rate limit in requests per second. Default: `50`. */\n rateLimitRps?: number;\n\n /** Optional logger. Compatible with `console`, `pino`, `winston`. */\n logger?: Logger;\n\n /** Custom `fetch` implementation (for testing or environments without global fetch). */\n fetch?: typeof globalThis.fetch;\n}\n\n// ---------------------------------------------------------------------------\n// Client class\n// ---------------------------------------------------------------------------\n\n/**\n * The main Hiero Mirror Client SDK entry point.\n *\n * Provides typed access to all Mirror Node REST API resources with:\n * - Automatic pagination via `Paginator`\n * - Safe JSON parsing for int64 precision\n * - ETag caching, retry/backoff, and rate limiting\n * - Type-safe responses via response mappers\n */\nexport class MirrorNodeClient {\n // --------------------------------------------------------------------------\n // Resource groups — exposed as readonly properties\n // --------------------------------------------------------------------------\n\n /** Account operations: list, get, NFTs, tokens, rewards, allowances, airdrops. */\n readonly accounts: AccountsResource;\n\n /** Global balance queries. */\n readonly balances: BalancesResource;\n\n /** Block queries. */\n readonly blocks: BlocksResource;\n\n /** Contract queries and smart contract call simulation. */\n readonly contracts: ContractsResource;\n\n /** Network info: exchange rate, fees, nodes, stake, supply. */\n readonly network: NetworkResource;\n\n /** Schedule queries. */\n readonly schedules: SchedulesResource;\n\n /** Token queries: list, get, balances, NFTs, NFT transactions. */\n readonly tokens: TokensResource;\n\n /** Topic queries and HCS message streaming. */\n readonly topics: TopicsResource;\n\n /** Transaction queries. */\n readonly transactions: TransactionsResource;\n\n /** The underlying HTTP client (exposed for advanced usage). */\n readonly httpClient: HttpClient;\n\n constructor(options: MirrorNodeClientOptions = {}) {\n // Resolve base URL.\n let baseUrl: string;\n if (options.baseUrl) {\n baseUrl = options.baseUrl;\n } else {\n const network = options.network ?? 'mainnet';\n baseUrl = NETWORK_URLS[network];\n }\n\n // Build HTTP client options.\n const httpOptions: HttpClientOptions = {\n baseUrl,\n timeout: options.timeout ?? 30_000,\n retry: { maxRetries: options.maxRetries ?? 2 },\n rateLimitRps: options.rateLimitRps ?? 50,\n logger: options.logger,\n fetch: options.fetch,\n };\n\n this.httpClient = new HttpClient(httpOptions);\n\n // Initialize resource groups.\n this.accounts = new AccountsResource(this.httpClient);\n this.balances = new BalancesResource(this.httpClient);\n this.blocks = new BlocksResource(this.httpClient);\n this.contracts = new ContractsResource(this.httpClient);\n this.network = new NetworkResource(this.httpClient);\n this.schedules = new SchedulesResource(this.httpClient);\n this.tokens = new TokensResource(this.httpClient);\n this.topics = new TopicsResource(this.httpClient);\n this.transactions = new TransactionsResource(this.httpClient);\n }\n}\n","import { HieroError } from './HieroError.js';\n\n/**\n * Thrown when a known feature is disabled on the mirror node\n * (e.g., `/stateproof` returns 404 on valid transaction IDs — EC62).\n *\n * Distinct from {@link HieroNotFoundError} because the entity exists\n * but the feature is unavailable on this mirror node instance.\n *\n * @public\n */\nexport class HieroCapabilityError extends HieroError {\n /** The feature/endpoint that is disabled. */\n readonly feature: string;\n\n constructor(message: string, options: { feature: string; rawBody?: string }) {\n super(message, { statusCode: 404, rawBody: options.rawBody });\n this.name = 'HieroCapabilityError';\n this.feature = options.feature;\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n feature: this.feature,\n };\n }\n}\n","/**\n * @satianurag/hiero-mirror-client\n *\n * Standalone TypeScript client for the Hedera/Hiero Mirror Node REST API.\n *\n * @packageDocumentation\n */\n\nexport const VERSION = '0.0.0';\n\nexport type { HieroNetwork, MirrorNodeClientOptions } from './client.js';\n// Client\nexport { MirrorNodeClient } from './client.js';\n// Errors (re-export the full hierarchy)\nexport {\n HieroCapabilityError,\n HieroError,\n HieroNetworkError,\n HieroNotFoundError,\n HieroParseError,\n HieroRateLimitError,\n HieroServerError,\n HieroTimeoutError,\n HieroValidationError,\n} from './errors/index.js';\nexport type { PageExtractor, PaginatorOptions } from './pagination/paginator.js';\n// Pagination\nexport { Paginator } from './pagination/paginator.js';\nexport type { TopicStreamOptions } from './pagination/stream.js';\nexport { TopicStream } from './pagination/stream.js';\n\n// Types (re-export everything from barrel)\nexport type * from './types/index.js';\n"],"mappings":"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"}
package/dist/utils.cjs ADDED
@@ -0,0 +1,188 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/utils/encoding.ts
3
+ /**
4
+ * Cross-platform encoding utilities.
5
+ *
6
+ * No dependency on Node.js `Buffer` — uses Web-standard APIs only.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ /**
11
+ * Base64-to-hex conversion.
12
+ *
13
+ * ```ts
14
+ * base64ToHex('SGVsbG8=') // → '48656c6c6f'
15
+ * ```
16
+ */
17
+ function base64ToHex(base64) {
18
+ const bytes = base64ToBytes(base64);
19
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
20
+ }
21
+ /**
22
+ * Hex-to-base64 conversion.
23
+ *
24
+ * Accepts optional 0x prefix.
25
+ *
26
+ * ```ts
27
+ * hexToBase64('48656c6c6f') // → 'SGVsbG8='
28
+ * hexToBase64('0x48656c6c6f') // → 'SGVsbG8='
29
+ * ```
30
+ */
31
+ function hexToBase64(hex) {
32
+ const cleaned = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
33
+ if (cleaned.length % 2 !== 0) throw new Error(`Invalid hex string: odd length (${cleaned.length})`);
34
+ const bytes = new Uint8Array(cleaned.length / 2);
35
+ for (let i = 0; i < cleaned.length; i += 2) bytes[i / 2] = Number.parseInt(cleaned.slice(i, i + 2), 16);
36
+ return bytesToBase64(bytes);
37
+ }
38
+ /**
39
+ * Convert a Uint8Array to a hex string (lowercase, no prefix).
40
+ */
41
+ function bytesToHex(bytes) {
42
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
43
+ }
44
+ /**
45
+ * Convert a hex string (with optional 0x prefix) to Uint8Array.
46
+ */
47
+ function hexToBytes(hex) {
48
+ const cleaned = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
49
+ if (cleaned.length % 2 !== 0) throw new Error(`Invalid hex string: odd length (${cleaned.length})`);
50
+ const bytes = new Uint8Array(cleaned.length / 2);
51
+ for (let i = 0; i < cleaned.length; i += 2) bytes[i / 2] = Number.parseInt(cleaned.slice(i, i + 2), 16);
52
+ return bytes;
53
+ }
54
+ const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
55
+ function base64ToBytes(base64) {
56
+ if (typeof atob === "function") {
57
+ const binary = atob(base64);
58
+ const bytes = new Uint8Array(binary.length);
59
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
60
+ return bytes;
61
+ }
62
+ const cleaned = base64.replace(/=+$/, "");
63
+ const byteLength = cleaned.length * 3 >> 2;
64
+ const bytes = new Uint8Array(byteLength);
65
+ let byteIndex = 0;
66
+ for (let i = 0; i < cleaned.length; i += 4) {
67
+ const a = BASE64_CHARS.indexOf(cleaned.charAt(i));
68
+ const b = BASE64_CHARS.indexOf(cleaned.charAt(i + 1));
69
+ const c = BASE64_CHARS.indexOf(i + 2 < cleaned.length ? cleaned.charAt(i + 2) : "A");
70
+ const d = BASE64_CHARS.indexOf(i + 3 < cleaned.length ? cleaned.charAt(i + 3) : "A");
71
+ bytes[byteIndex++] = a << 2 | b >> 4;
72
+ if (i + 2 < cleaned.length) bytes[byteIndex++] = (b & 15) << 4 | c >> 2;
73
+ if (i + 3 < cleaned.length) bytes[byteIndex++] = (c & 3) << 6 | d;
74
+ }
75
+ return bytes;
76
+ }
77
+ function bytesToBase64(bytes) {
78
+ if (typeof btoa === "function") {
79
+ let binary = "";
80
+ for (const b of bytes) binary += String.fromCharCode(b);
81
+ return btoa(binary);
82
+ }
83
+ let result = "";
84
+ for (let i = 0; i < bytes.length; i += 3) {
85
+ const a = bytes[i];
86
+ const b = bytes[i + 1] ?? 0;
87
+ const c = bytes[i + 2] ?? 0;
88
+ result += BASE64_CHARS[a >> 2 & 63];
89
+ result += BASE64_CHARS[(a & 3) << 4 | b >> 4 & 15];
90
+ result += i + 1 < bytes.length ? BASE64_CHARS[(b & 15) << 2 | c >> 6 & 3] : "=";
91
+ result += i + 2 < bytes.length ? BASE64_CHARS[c & 63] : "=";
92
+ }
93
+ return result;
94
+ }
95
+ //#endregion
96
+ //#region src/utils/timestamp.ts
97
+ /**
98
+ * Creates a HieroTimestamp from a `seconds.nanos` string.
99
+ *
100
+ * ```ts
101
+ * const ts = fromString('1710000000.123456789');
102
+ * ts.seconds // 1710000000n
103
+ * ts.nanos // 123456789
104
+ * ts.toString() // '1710000000.123456789'
105
+ * ```
106
+ */
107
+ function fromString(timestamp) {
108
+ const dotIndex = timestamp.indexOf(".");
109
+ if (dotIndex === -1) return makeTimestamp(BigInt(timestamp), 0);
110
+ const seconds = BigInt(timestamp.slice(0, dotIndex));
111
+ const nanosStr = timestamp.slice(dotIndex + 1).padEnd(9, "0").slice(0, 9);
112
+ return makeTimestamp(seconds, Number.parseInt(nanosStr, 10));
113
+ }
114
+ /**
115
+ * Creates a HieroTimestamp from a JavaScript `Date`.
116
+ *
117
+ * Note: JS Date only has millisecond precision. Nanoseconds below ms will be 0.
118
+ *
119
+ * ```ts
120
+ * const ts = fromDate(new Date('2024-03-10T00:00:00Z'));
121
+ * ```
122
+ */
123
+ function fromDate(date) {
124
+ const epochMs = date.getTime();
125
+ return makeTimestamp(BigInt(Math.floor(epochMs / 1e3)), epochMs % 1e3 * 1e6);
126
+ }
127
+ /**
128
+ * Creates a HieroTimestamp for the current moment.
129
+ *
130
+ * ```ts
131
+ * const ts = now();
132
+ * ```
133
+ */
134
+ function now() {
135
+ return fromDate(/* @__PURE__ */ new Date());
136
+ }
137
+ /**
138
+ * Creates a HieroTimestamp from separate seconds and nanoseconds.
139
+ *
140
+ * ```ts
141
+ * const ts = fromParts(1710000000n, 123456789);
142
+ * ```
143
+ */
144
+ function fromParts(seconds, nanos) {
145
+ if (nanos < 0 || nanos > 999999999) throw new RangeError(`nanoseconds must be 0..999_999_999, got ${nanos}`);
146
+ return makeTimestamp(seconds, nanos);
147
+ }
148
+ /**
149
+ * Converts a HieroTimestamp to a JavaScript Date.
150
+ *
151
+ * Note: sub-millisecond precision is lost.
152
+ */
153
+ function toDate(timestamp) {
154
+ const ms = Number(timestamp.seconds) * 1e3 + Math.floor(timestamp.nanos / 1e6);
155
+ return new Date(ms);
156
+ }
157
+ /**
158
+ * Compares two timestamps. Returns -1, 0, or 1.
159
+ */
160
+ function compare(a, b) {
161
+ if (a.seconds < b.seconds) return -1;
162
+ if (a.seconds > b.seconds) return 1;
163
+ if (a.nanos < b.nanos) return -1;
164
+ if (a.nanos > b.nanos) return 1;
165
+ return 0;
166
+ }
167
+ function makeTimestamp(seconds, nanos) {
168
+ return {
169
+ seconds,
170
+ nanos,
171
+ toString() {
172
+ return `${seconds}.${String(nanos).padStart(9, "0")}`;
173
+ }
174
+ };
175
+ }
176
+ //#endregion
177
+ exports.base64ToHex = base64ToHex;
178
+ exports.bytesToHex = bytesToHex;
179
+ exports.compare = compare;
180
+ exports.fromDate = fromDate;
181
+ exports.fromParts = fromParts;
182
+ exports.fromString = fromString;
183
+ exports.hexToBase64 = hexToBase64;
184
+ exports.hexToBytes = hexToBytes;
185
+ exports.now = now;
186
+ exports.toDate = toDate;
187
+
188
+ //# sourceMappingURL=utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.cjs","names":[],"sources":["../src/utils/encoding.ts","../src/utils/timestamp.ts"],"sourcesContent":["/**\n * Cross-platform encoding utilities.\n *\n * No dependency on Node.js `Buffer` — uses Web-standard APIs only.\n *\n * @packageDocumentation\n */\n\n/**\n * Base64-to-hex conversion.\n *\n * ```ts\n * base64ToHex('SGVsbG8=') // → '48656c6c6f'\n * ```\n */\nexport function base64ToHex(base64: string): string {\n const bytes = base64ToBytes(base64);\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Hex-to-base64 conversion.\n *\n * Accepts optional 0x prefix.\n *\n * ```ts\n * hexToBase64('48656c6c6f') // → 'SGVsbG8='\n * hexToBase64('0x48656c6c6f') // → 'SGVsbG8='\n * ```\n */\nexport function hexToBase64(hex: string): string {\n const cleaned = hex.startsWith('0x') || hex.startsWith('0X') ? hex.slice(2) : hex;\n if (cleaned.length % 2 !== 0) {\n throw new Error(`Invalid hex string: odd length (${cleaned.length})`);\n }\n const bytes = new Uint8Array(cleaned.length / 2);\n for (let i = 0; i < cleaned.length; i += 2) {\n bytes[i / 2] = Number.parseInt(cleaned.slice(i, i + 2), 16);\n }\n return bytesToBase64(bytes);\n}\n\n/**\n * Convert a Uint8Array to a hex string (lowercase, no prefix).\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Convert a hex string (with optional 0x prefix) to Uint8Array.\n */\nexport function hexToBytes(hex: string): Uint8Array {\n const cleaned = hex.startsWith('0x') || hex.startsWith('0X') ? hex.slice(2) : hex;\n if (cleaned.length % 2 !== 0) {\n throw new Error(`Invalid hex string: odd length (${cleaned.length})`);\n }\n const bytes = new Uint8Array(cleaned.length / 2);\n for (let i = 0; i < cleaned.length; i += 2) {\n bytes[i / 2] = Number.parseInt(cleaned.slice(i, i + 2), 16);\n }\n return bytes;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers (no Buffer, cross-platform)\n// ---------------------------------------------------------------------------\n\nconst BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nfunction base64ToBytes(base64: string): Uint8Array {\n // Use atob if available (browser + Node 16+)\n if (typeof atob === 'function') {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n\n // Manual fallback (should rarely be needed)\n const cleaned = base64.replace(/=+$/, '');\n const byteLength = (cleaned.length * 3) >> 2;\n const bytes = new Uint8Array(byteLength);\n let byteIndex = 0;\n\n for (let i = 0; i < cleaned.length; i += 4) {\n const a = BASE64_CHARS.indexOf(cleaned.charAt(i));\n const b = BASE64_CHARS.indexOf(cleaned.charAt(i + 1));\n const c = BASE64_CHARS.indexOf(i + 2 < cleaned.length ? cleaned.charAt(i + 2) : 'A');\n const d = BASE64_CHARS.indexOf(i + 3 < cleaned.length ? cleaned.charAt(i + 3) : 'A');\n\n bytes[byteIndex++] = (a << 2) | (b >> 4);\n if (i + 2 < cleaned.length) bytes[byteIndex++] = ((b & 15) << 4) | (c >> 2);\n if (i + 3 < cleaned.length) bytes[byteIndex++] = ((c & 3) << 6) | d;\n }\n\n return bytes;\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n // Use btoa if available (browser + Node 16+)\n if (typeof btoa === 'function') {\n let binary = '';\n for (const b of bytes) {\n binary += String.fromCharCode(b);\n }\n return btoa(binary);\n }\n\n // Manual fallback\n let result = '';\n for (let i = 0; i < bytes.length; i += 3) {\n const a = bytes[i]!;\n const b = bytes[i + 1] ?? 0;\n const c = bytes[i + 2] ?? 0;\n\n result += BASE64_CHARS[(a >> 2) & 63];\n result += BASE64_CHARS[((a & 3) << 4) | ((b >> 4) & 15)];\n result += i + 1 < bytes.length ? BASE64_CHARS[((b & 15) << 2) | ((c >> 6) & 3)] : '=';\n result += i + 2 < bytes.length ? BASE64_CHARS[c & 63] : '=';\n }\n\n return result;\n}\n","/**\n * HieroTimestamp — factory methods for Hedera/Hiero timestamps.\n *\n * Hedera timestamps use the format `seconds.nanoseconds`, e.g., `1710000000.123456789`.\n *\n * @packageDocumentation\n */\n\n/**\n * Represents a Hedera consensus timestamp as `seconds.nanoseconds`.\n */\nexport interface HieroTimestamp {\n /** Whole seconds since epoch. */\n readonly seconds: bigint;\n /** Nanosecond component (0–999,999,999). */\n readonly nanos: number;\n /** Full timestamp string: `<seconds>.<nanos padded to 9 digits>`. */\n toString(): string;\n}\n\n/**\n * Creates a HieroTimestamp from a `seconds.nanos` string.\n *\n * ```ts\n * const ts = fromString('1710000000.123456789');\n * ts.seconds // 1710000000n\n * ts.nanos // 123456789\n * ts.toString() // '1710000000.123456789'\n * ```\n */\nexport function fromString(timestamp: string): HieroTimestamp {\n const dotIndex = timestamp.indexOf('.');\n if (dotIndex === -1) {\n const seconds = BigInt(timestamp);\n return makeTimestamp(seconds, 0);\n }\n\n const seconds = BigInt(timestamp.slice(0, dotIndex));\n const nanosStr = timestamp\n .slice(dotIndex + 1)\n .padEnd(9, '0')\n .slice(0, 9);\n const nanos = Number.parseInt(nanosStr, 10);\n\n return makeTimestamp(seconds, nanos);\n}\n\n/**\n * Creates a HieroTimestamp from a JavaScript `Date`.\n *\n * Note: JS Date only has millisecond precision. Nanoseconds below ms will be 0.\n *\n * ```ts\n * const ts = fromDate(new Date('2024-03-10T00:00:00Z'));\n * ```\n */\nexport function fromDate(date: Date): HieroTimestamp {\n const epochMs = date.getTime();\n const seconds = BigInt(Math.floor(epochMs / 1000));\n const nanos = (epochMs % 1000) * 1_000_000;\n return makeTimestamp(seconds, nanos);\n}\n\n/**\n * Creates a HieroTimestamp for the current moment.\n *\n * ```ts\n * const ts = now();\n * ```\n */\nexport function now(): HieroTimestamp {\n return fromDate(new Date());\n}\n\n/**\n * Creates a HieroTimestamp from separate seconds and nanoseconds.\n *\n * ```ts\n * const ts = fromParts(1710000000n, 123456789);\n * ```\n */\nexport function fromParts(seconds: bigint, nanos: number): HieroTimestamp {\n if (nanos < 0 || nanos > 999_999_999) {\n throw new RangeError(`nanoseconds must be 0..999_999_999, got ${nanos}`);\n }\n return makeTimestamp(seconds, nanos);\n}\n\n/**\n * Converts a HieroTimestamp to a JavaScript Date.\n *\n * Note: sub-millisecond precision is lost.\n */\nexport function toDate(timestamp: HieroTimestamp): Date {\n const ms = Number(timestamp.seconds) * 1000 + Math.floor(timestamp.nanos / 1_000_000);\n return new Date(ms);\n}\n\n/**\n * Compares two timestamps. Returns -1, 0, or 1.\n */\nexport function compare(a: HieroTimestamp, b: HieroTimestamp): -1 | 0 | 1 {\n if (a.seconds < b.seconds) return -1;\n if (a.seconds > b.seconds) return 1;\n if (a.nanos < b.nanos) return -1;\n if (a.nanos > b.nanos) return 1;\n return 0;\n}\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\nfunction makeTimestamp(seconds: bigint, nanos: number): HieroTimestamp {\n return {\n seconds,\n nanos,\n toString() {\n return `${seconds}.${String(nanos).padStart(9, '0')}`;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,SAAgB,YAAY,QAAwB;CAClD,MAAM,QAAQ,cAAc,OAAO;AACnC,QAAO,MAAM,KAAK,MAAM,CACrB,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC3C,KAAK,GAAG;;;;;;;;;;;;AAab,SAAgB,YAAY,KAAqB;CAC/C,MAAM,UAAU,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,GAAG,IAAI,MAAM,EAAE,GAAG;AAC9E,KAAI,QAAQ,SAAS,MAAM,EACzB,OAAM,IAAI,MAAM,mCAAmC,QAAQ,OAAO,GAAG;CAEvE,MAAM,QAAQ,IAAI,WAAW,QAAQ,SAAS,EAAE;AAChD,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,EACvC,OAAM,IAAI,KAAK,OAAO,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,EAAE,GAAG;AAE7D,QAAO,cAAc,MAAM;;;;;AAM7B,SAAgB,WAAW,OAA2B;AACpD,QAAO,MAAM,KAAK,MAAM,CACrB,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC3C,KAAK,GAAG;;;;;AAMb,SAAgB,WAAW,KAAyB;CAClD,MAAM,UAAU,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,GAAG,IAAI,MAAM,EAAE,GAAG;AAC9E,KAAI,QAAQ,SAAS,MAAM,EACzB,OAAM,IAAI,MAAM,mCAAmC,QAAQ,OAAO,GAAG;CAEvE,MAAM,QAAQ,IAAI,WAAW,QAAQ,SAAS,EAAE;AAChD,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,EACvC,OAAM,IAAI,KAAK,OAAO,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,EAAE,GAAG;AAE7D,QAAO;;AAOT,MAAM,eAAe;AAErB,SAAS,cAAc,QAA4B;AAEjD,KAAI,OAAO,SAAS,YAAY;EAC9B,MAAM,SAAS,KAAK,OAAO;EAC3B,MAAM,QAAQ,IAAI,WAAW,OAAO,OAAO;AAC3C,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,IACjC,OAAM,KAAK,OAAO,WAAW,EAAE;AAEjC,SAAO;;CAIT,MAAM,UAAU,OAAO,QAAQ,OAAO,GAAG;CACzC,MAAM,aAAc,QAAQ,SAAS,KAAM;CAC3C,MAAM,QAAQ,IAAI,WAAW,WAAW;CACxC,IAAI,YAAY;AAEhB,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,GAAG;EAC1C,MAAM,IAAI,aAAa,QAAQ,QAAQ,OAAO,EAAE,CAAC;EACjD,MAAM,IAAI,aAAa,QAAQ,QAAQ,OAAO,IAAI,EAAE,CAAC;EACrD,MAAM,IAAI,aAAa,QAAQ,IAAI,IAAI,QAAQ,SAAS,QAAQ,OAAO,IAAI,EAAE,GAAG,IAAI;EACpF,MAAM,IAAI,aAAa,QAAQ,IAAI,IAAI,QAAQ,SAAS,QAAQ,OAAO,IAAI,EAAE,GAAG,IAAI;AAEpF,QAAM,eAAgB,KAAK,IAAM,KAAK;AACtC,MAAI,IAAI,IAAI,QAAQ,OAAQ,OAAM,gBAAiB,IAAI,OAAO,IAAM,KAAK;AACzE,MAAI,IAAI,IAAI,QAAQ,OAAQ,OAAM,gBAAiB,IAAI,MAAM,IAAK;;AAGpE,QAAO;;AAGT,SAAS,cAAc,OAA2B;AAEhD,KAAI,OAAO,SAAS,YAAY;EAC9B,IAAI,SAAS;AACb,OAAK,MAAM,KAAK,MACd,WAAU,OAAO,aAAa,EAAE;AAElC,SAAO,KAAK,OAAO;;CAIrB,IAAI,SAAS;AACb,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxC,MAAM,IAAI,MAAM;EAChB,MAAM,IAAI,MAAM,IAAI,MAAM;EAC1B,MAAM,IAAI,MAAM,IAAI,MAAM;AAE1B,YAAU,aAAc,KAAK,IAAK;AAClC,YAAU,cAAe,IAAI,MAAM,IAAO,KAAK,IAAK;AACpD,YAAU,IAAI,IAAI,MAAM,SAAS,cAAe,IAAI,OAAO,IAAO,KAAK,IAAK,KAAM;AAClF,YAAU,IAAI,IAAI,MAAM,SAAS,aAAa,IAAI,MAAM;;AAG1D,QAAO;;;;;;;;;;;;;;AClGT,SAAgB,WAAW,WAAmC;CAC5D,MAAM,WAAW,UAAU,QAAQ,IAAI;AACvC,KAAI,aAAa,GAEf,QAAO,cADS,OAAO,UAAU,EACH,EAAE;CAGlC,MAAM,UAAU,OAAO,UAAU,MAAM,GAAG,SAAS,CAAC;CACpD,MAAM,WAAW,UACd,MAAM,WAAW,EAAE,CACnB,OAAO,GAAG,IAAI,CACd,MAAM,GAAG,EAAE;AAGd,QAAO,cAAc,SAFP,OAAO,SAAS,UAAU,GAAG,CAEP;;;;;;;;;;;AAYtC,SAAgB,SAAS,MAA4B;CACnD,MAAM,UAAU,KAAK,SAAS;AAG9B,QAAO,cAFS,OAAO,KAAK,MAAM,UAAU,IAAK,CAAC,EACnC,UAAU,MAAQ,IACG;;;;;;;;;AAUtC,SAAgB,MAAsB;AACpC,QAAO,yBAAS,IAAI,MAAM,CAAC;;;;;;;;;AAU7B,SAAgB,UAAU,SAAiB,OAA+B;AACxE,KAAI,QAAQ,KAAK,QAAQ,UACvB,OAAM,IAAI,WAAW,2CAA2C,QAAQ;AAE1E,QAAO,cAAc,SAAS,MAAM;;;;;;;AAQtC,SAAgB,OAAO,WAAiC;CACtD,MAAM,KAAK,OAAO,UAAU,QAAQ,GAAG,MAAO,KAAK,MAAM,UAAU,QAAQ,IAAU;AACrF,QAAO,IAAI,KAAK,GAAG;;;;;AAMrB,SAAgB,QAAQ,GAAmB,GAA+B;AACxE,KAAI,EAAE,UAAU,EAAE,QAAS,QAAO;AAClC,KAAI,EAAE,UAAU,EAAE,QAAS,QAAO;AAClC,KAAI,EAAE,QAAQ,EAAE,MAAO,QAAO;AAC9B,KAAI,EAAE,QAAQ,EAAE,MAAO,QAAO;AAC9B,QAAO;;AAOT,SAAS,cAAc,SAAiB,OAA+B;AACrE,QAAO;EACL;EACA;EACA,WAAW;AACT,UAAO,GAAG,QAAQ,GAAG,OAAO,MAAM,CAAC,SAAS,GAAG,IAAI;;EAEtD"}