Skip to content

Core Layer

Home · Top · Table of Contents

Table of Contents

The core layer (src/core/) is TrustLedger's framework-agnostic foundation: a small set of reusable modules that the app, API routes, and feature code build on. It is documented in src/core/README.md; this page covers usage and integration guidance.

Importing

Home · Top · Table of Contents

import {
    logger,
    analytics,
    isEnabled,
    can,
    validateAmount,
    normalizeError,
} from "@/core";

@/core resolves to src/core/index.ts, which re-exports the canonical surface in src/core/core.ts. Prefer the barrel import over reaching into individual module folders.

Modules and examples

Home · Top · Table of Contents

Logging

Home · Top · Table of Contents

import { logger } from "@/core";

const log = logger.child({ feature: "staking" });
log.info("stake submitted", { asset: "USDC", amount: "100" });

Level is controlled by NEXT_PUBLIC_LOG_LEVEL (debug | info | warn | error), defaulting to debug in development and warn in production. Install a custom sink in tests with setLogSink / resetLogSink.

Errors

Home · Top · Table of Contents

import { normalizeError, ValidationError, isAppError } from "@/core";

try {
    doWork();
} catch (err) {
    const appError = normalizeError(err); // always an AppError
    logger.error(appError.message, { code: appError.code });
}

Feature flags

Home · Top · Table of Contents

import { isEnabled, setFlagOverride } from "@/core";

if (isEnabled("stakingSolEnabled")) {
    /* render SOL staking option */
}

Defaults live in core/flags. Override per environment with NEXT_PUBLIC_FLAG_<NAME>=true|false, or at runtime via setFlagOverride.

Permissions

Home · Top · Table of Contents

import { can, assertCan } from "@/core";

if (can(role, "analytics:view")) {
    /* show dashboards */
}
assertCan(role, "admin:access"); // throws PermissionError otherwise

Validation

Home · Top · Table of Contents

import { validateAmount, isEvmAddress } from "@/core";

const result = validateAmount(input, 6); // USDC has 6 decimals
if (!result.ok) setError(result.message);

Caching

Home · Top · Table of Contents

import { memoizeAsync } from "@/core";

const getSummary = memoizeAsync(fetchSummary, (id) => id, 30_000);

Analytics and events

Home · Top · Table of Contents

import { analytics, eventBus } from "@/core";

analytics.track("stake_created", { asset: "SOL" });
eventBus.on("stake:created", ({ asset }) => log.debug("staked", { asset }));

analytics.track is a no-op when NEXT_PUBLIC_ANALYTICS_DISABLED=true.

Adding a module

Home · Top · Table of Contents

  1. Create src/core/<name>/index.ts with the implementation and doc comments.
  2. Re-export it from src/core/core.ts.
  3. Add unit tests to src/tests/unit/core.test.ts.
  4. Update the module map in src/core/README.md.

Keep modules dependency-free and SSR-safe (no top-level browser globals).

Configuration reference

Home · Top · Table of Contents

Env var Effect
NEXT_PUBLIC_LOG_LEVEL Minimum log level emitted by logger
NEXT_PUBLIC_ANALYTICS_ENDPOINT Analytics POST endpoint (default /api/analytics/events)
NEXT_PUBLIC_ANALYTICS_DISABLED true disables analytics.track
NEXT_PUBLIC_FLAG_<NAME> Per-flag override (true/false)

Authors and Contributors

Home · Top · Table of Contents

  • Kevin K. Le — Founder, Founding Engineer, and Current Lead Engineer (LinkedIn)
  • Kellen Snider — Founding Engineer (LinkedIn)

See CREDITS.md for the complete acknowledgement list.

Home · Top · Table of Contents

This document is part of TrustLedger, an open-source decentralized escrow and arbitration protocol. Use of this software and documentation is subject to the Terms and Conditions, Privacy Policy, and Risk Disclosure. See LEGAL.md for the full compliance and licensing overview.