npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@the_library/public

v1.0.0

Published

Consolidated public libraries and Web3 SDK for DataPond and World Library

Readme

@the_library/public — Complete API Documentation

This document provides exhaustive API reference for all exports from @the_library/public and its subpaths. It is organized by subpath/module and includes every function, type, interface, and composable with full parameter and return type documentation.


Table of Contents

  1. Downloader API

  2. Models API

  3. Web3 API

  4. Branding API


1. Downloader API (@the_library/public/downloader)

The Downloader manages parallelized, cross-worker PDF and image fetching, decryption, decompression, and rendering using Web Workers and IndexedDB/Cache API storage backends.

Initialization

InitDownloaderV2(options?: InitOptions): Promise<void>

Single-call initialization of the download orchestrator. Must be called once at app boot before calling any file-fetch functions. Idempotent — subsequent calls are no-ops.

import { InitDownloaderV2 } from '@the_library/public/downloader';

await InitDownloaderV2({
  gateways: ['https://arweave.net', 'https://arweave.dev'],
  requestPersistence: true,
  concurrency: { pdf: 3, preview: 6 },
  mupdfUrl: '/js/mupdf.js',
});

Parameters:

  • options.gateways?: string[] — Array of Arweave gateway URLs to try in sequence. Defaults to ['https://arweave.net'].
  • options.requestPersistence?: boolean — If true, asks the browser for persistent storage via navigator.storage.persist(), which may prevent auto-eviction of cached files. Defaults to false.
  • options.concurrency?: { pdf: number; preview: number } — Limits simultaneous downloads: pdf caps concurrent PDF fetches, preview caps concurrent page-image renders. Defaults to { pdf: 3, preview: 6 }.
  • options.mupdfUrl?: string — URL to mupdf.js (WASM runtime). Must be adjacent to mupdf-wasm.js and mupdf-wasm.wasm in the app's public/ directory. Defaults to '/js/mupdf.js'.

Returns: Promise<void> — resolves once worker threads are initialized.

Throws:

  • If InitDownloaderV2 is called simultaneously from multiple call sites, the first promise is returned (idempotency guard).
  • Worker thread setup errors (e.g., broken WASM URL) surface on the returned promise.

preloadWorkersV2(): void

Eagerly constructs worker threads so the worker JS bundles download in the background. Call as early as possible (e.g., during app shell initialization before the app mounts components).

import { preloadWorkersV2 } from '@the_library/public/downloader';

// Call immediately when app boots, before any heavy imports:
preloadWorkersV2();

Parameters: None

Returns: void (synchronous; starts background downloads, doesn't wait for them)


File Operations

GetPdf(txId: string, options?: { priority?: 'low' | 'high' }): Promise<Response>

Fetches, decrypts, and decompresses a PDF by Arweave TX ID. Returns a Response object wrapping the decrypted bytes.

import { GetPdf, GetObjectUrl } from '@the_library/public/downloader';

const response = await GetPdf(txId);
const blob = await response.blob();
const objectUrl = await GetObjectUrl(response); // for <iframe> or <embed>

Parameters:

  • txId: string — Arweave TX ID identifying the encrypted PDF.
  • options.priority?: 'low' | 'high' — Queue priority. Defaults to 'low'. Use 'high' for user-initiated "open book" actions to bump ahead of background prefetches.

Returns: Promise<Response> — HTTP Response object (status 200) wrapping the decrypted PDF bytes. Use .blob(), .arrayBuffer(), or .text() to read the body.

Throws:

  • If all gateways are unreachable or return 404/500, rejects with a NetworkError or NotFoundError.
  • If decryption fails, rejects with a DecryptionError.

Caching: The result is cached by txId in the browser's Cache API (under CACHES.pdf). Subsequent calls return the cached response synchronously.


GetImage(txId: string, pageOverride?: number): Promise<Response>

Renders a page preview image (JPEG/PNG) via the mupdf worker. By default, renders the first page of a PDF. Returns a Response wrapping the image bytes.

import { GetImage } from '@the_library/public/downloader';

// Get the cover image (first page)
const coverResponse = await GetImage(txId);
const imageBlob = await coverResponse.blob();
const imgSrc = URL.createObjectURL(imageBlob);

// Get a specific page
const page5Image = await GetImage(txId, 5);

Parameters:

  • txId: string — Arweave TX ID of the PDF.
  • pageOverride?: number — 1-indexed page number. Defaults to 1 (first page).

Returns: Promise<Response> — HTTP Response object (status 200) wrapping JPEG/PNG bytes.

Throws:

  • Same as GetPdf (gateway errors, decryption failures).
  • If pageOverride is out of range (e.g., page 1000 of a 10-page PDF), rejects with RangeError.

Caching: Rendered images are cached in CACHES.preview under the key {txId}_page{n}. Cached preview images persist across sessions.


EnsurePdf(txId: string): Promise<void>

Pre-downloads and caches a PDF without needing the Response object back. Useful for background prefetching or "warm up" operations.

import { EnsurePdf } from '@the_library/public/downloader';

// Background prefetch (fire and forget)
EnsurePdf(txId).catch(e => console.warn('Prefetch failed:', e));

// Wait for it
await EnsurePdf(txId);

Parameters:

  • txId: string — Arweave TX ID of the PDF.

Returns: Promise<void> — resolves once the PDF is cached.

Throws: Same as GetPdf.


EnsurePageImage(txId: string, page: number): Promise<void>

Pre-renders and caches a specific page image without returning the bytes. Used to warm up page-image cache before the user scrolls to that page.

import { EnsurePageImage } from '@the_library/public/downloader';

// Render pages 2-5 in the background while user reads page 1
for (let i = 2; i <= 5; i++) {
  EnsurePageImage(txId, i).catch(e => console.warn(`Page ${i} prefetch failed`));
}

Parameters:

  • txId: string — Arweave TX ID.
  • page: number — 1-indexed page number.

Returns: Promise<void> — resolves once the image is cached.

Throws: Same as GetImage.


DownloadPdfToDisk(txId: string, filename?: string): Promise<void>

Triggers a browser "Save As" dialog and writes the decrypted PDF to the user's local Downloads folder.

import { DownloadPdfToDisk } from '@the_library/public/downloader';

await DownloadPdfToDisk(txId, 'My Book Title.pdf');

Parameters:

  • txId: string — Arweave TX ID.
  • filename?: string — Suggested filename for the browser's save dialog. If omitted, the browser uses a default name.

Returns: Promise<void> — resolves once the download is initiated (does not wait for the user to confirm the save dialog).

Throws:

  • Same as GetPdf (fetch/decrypt errors).
  • If the browser blocks the download (e.g., security policy), the promise rejects with a SecurityError.

GetObjectUrl(response: Response): Promise<string>

Converts a GetPdf or GetImage response to a blob URL suitable for <iframe src="">, <embed src="">, or <img src="">.

import { GetPdf, GetObjectUrl } from '@the_library/public/downloader';

const pdfResponse = await GetPdf(txId);
const blobUrl = await GetObjectUrl(pdfResponse);
// Now use: <iframe :src="blobUrl" />

Parameters:

  • response: Response — A Response object returned by GetPdf or GetImage.

Returns: Promise<string> — A blob: URL (e.g., blob:https://example.com/...).


revokeObjectUrl(blobUrl: string): void

Explicitly revokes a blob URL created by GetObjectUrl to release memory.

const blobUrl = await GetObjectUrl(response);
// ... later ...
revokeObjectUrl(blobUrl);

Parameters:

  • blobUrl: string — The blob URL to revoke.

Returns: void

Note: Blob URLs are automatically revoked when the page navigates away or the tab closes. Manual revocation is only necessary to free memory during a long-running session (e.g., a single-page app that opens/closes many books).


storageEstimate(): Promise<{ usage: number; quota: number }>

Queries the browser's storage quota and current usage.

import { storageEstimate } from '@the_library/public/downloader';

const { usage, quota } = await storageEstimate();
const percentUsed = (usage / quota) * 100;
console.log(`${percentUsed.toFixed(1)}% of storage in use`);

Parameters: None

Returns: Promise<{ usage: number; quota: number }>usage is bytes currently used by Cache API + IndexedDB, quota is the browser's total storage quota in bytes.


Metadata & Storage

getBookData(txId: string): Promise<BookData | undefined>

Reads cached book metadata (title, page count, etc.) from IndexedDB.

import { getBookData } from '@the_library/public/downloader';

const bookData = await getBookData(txId);
if (bookData) {
  console.log(`${bookData.title} has ${bookData.pages} pages`);
}

Parameters:

  • txId: string — Arweave TX ID.

Returns: Promise<BookData | undefined> — Book metadata if cached, undefined if no metadata has been hydrated yet.

Type: BookData

interface BookData {
  txId: string;
  title: string;
  pages: number;
  // ... other fields set by the mupdf worker
}

getAllBookData(): Promise<BookData[]>

Retrieves all cached book metadata records from IndexedDB.

import { getAllBookData } from '@the_library/public/downloader';

const allBooks = await getAllBookData();
console.log(`${allBooks.length} books cached`);

Parameters: None

Returns: Promise<BookData[]> — Array of all cached BookData records. Empty array if no books have been hydrated yet.


getDownloadRecord(txId: string): Promise<DownloadRecord | undefined>

Reads the download progress record for a TX ID.

import { getDownloadRecord } from '@the_library/public/downloader';

const record = await getDownloadRecord(txId);
if (record) {
  console.log(`${record.loaded}/${record.total} bytes downloaded`);
}

Parameters:

  • txId: string — Arweave TX ID.

Returns: Promise<DownloadRecord | undefined>

Type: DownloadRecord

interface DownloadRecord {
  txId: string;
  loaded: number;   // bytes downloaded so far
  total: number;    // total file size in bytes
  timestamp: number; // last update time (ms since epoch)
}

getAllDownloadRecords(): Promise<DownloadRecord[]>

Retrieves all download progress records.

import { getAllDownloadRecords } from '@the_library/public/downloader';

const records = await getAllDownloadRecords();
console.log(`${records.length} active/recent downloads`);

Parameters: None

Returns: Promise<DownloadRecord[]> — Array of all cached progress records.


Cache Management

downloadState

The canonical, synchronous, framework-agnostic store for all file state. Every framework adapter (vue, react, solid) is a thin reactive wrapper around this store.

import { downloadState } from '@the_library/public/downloader';

// Subscribe to changes
const unsubscribe = downloadState.subscribe((changedTxId) => {
  console.log(`File state changed for ${changedTxId}`);
});

// Read current state
const fileState = downloadState.get(txId);
if (fileState?.phase === 'done') {
  console.log('Download complete');
}

// Read render state (page images, book metadata)
const renderState = downloadState.getRender(txId);
console.log(`${renderState.pages.size} page images cached`);

// Global summary
const summary = downloadState.summary();
console.log(`${summary.downloading} active downloads`);

Methods:

  • downloadState.get(txId: string): FileState | undefined — Returns current state of one file.

  • downloadState.getRender(txId: string): RenderState | undefined — Returns render/page state for one file.

  • downloadState.summary(): DownloadSummary — Returns global aggregate (total files, total bytes, etc.).

  • downloadState.subscribe(callback: (txId: string) => void): () => void — Registers a listener. Returns unsubscribe function.

Type: FileState

interface FileState {
  phase: 'unknown' | 'queued' | 'downloading' | 'done' | 'error';
  loaded: number;
  total: number;
  error?: string;
  progress?: number; // 0-1
}

Type: RenderState

interface RenderState {
  bookData?: BookData;
  pages: Map<number, FilePhase>; // page number -> 'done' | 'error' | ...
}

deletePdf(txId: string): Promise<boolean>

Removes a cached PDF from Cache API storage.

import { deletePdf } from '@the_library/public/downloader';

const deleted = await deletePdf(txId);
console.log(deleted ? 'Deleted' : 'Not found in cache');

Parameters:

  • txId: string — Arweave TX ID.

Returns: Promise<boolean>true if deletion succeeded, false if the PDF was not cached.


deletePreview(txId: string): Promise<boolean>

Removes all cached page preview images for a TX ID.

import { deletePreview } from '@the_library/public/downloader';

await deletePreview(txId);

Parameters:

  • txId: string — Arweave TX ID.

Returns: Promise<boolean>true if deletion succeeded.


deleteDownloadRecord(txId: string): Promise<void>

Removes the download progress record from IndexedDB.

import { deleteDownloadRecord } from '@the_library/public/downloader';

await deleteDownloadRecord(txId);

Parameters:

  • txId: string — Arweave TX ID.

Returns: Promise<void>


Cache Store API

Raw cache and IndexedDB access (rarely called directly; use the higher-level APIs above when possible).

openPdfCache(): Promise<Cache>

Gets the Cache API store for PDFs.

const cache = await openPdfCache();
const keys = await cache.keys();

openPreviewCache(): Promise<Cache>

Gets the Cache API store for preview images.

openPagesCache(): Promise<Cache>

Gets the Cache API store for individual page images.

matchPdf(txId: string): Promise<Response | undefined>

Low-level cache lookup for a single PDF.

matchPreview(txId: string): Promise<Response | undefined>

Low-level cache lookup for a cover/first-page image.

matchPage(txId: string, pageNumber: number): Promise<Response | undefined>

Low-level cache lookup for a specific page image.

putPdf(txId: string, response: Response): Promise<void>

Low-level cache write for a PDF.

putPreview(txId: string, response: Response): Promise<void>

Low-level cache write for a cover image.

putPage(txId: string, pageNumber: number, response: Response): Promise<void>

Low-level cache write for a page image.

pdfKeys(): Promise<string[]>

Lists all cached PDF keys.

previewKeys(): Promise<string[]>

Lists all cached preview-image keys.

pageKeys(): Promise<string[]>

Lists all cached page-image keys.


Keys & Naming

pdfKey(txId: string): string

Generates the cache key for a PDF.

const key = pdfKey(txId); // e.g., "arweave_pdf_{txId}"

previewKey(txId: string): string

Generates the cache key for a cover image.

pageKey(txId: string, pageNumber: number): string

Generates the cache key for a specific page.

const key = pageKey(txId, 5); // e.g., "arweave_page_5_{txId}"

CACHES (constant)

import { CACHES } from '@the_library/public/downloader';

// CACHES = {
//   pdf: 'dl2-pdf-cache-v1',
//   preview: 'dl2-preview-cache-v1',
//   pages: 'dl2-pages-cache-v1'
// }

CACHE_VERSION (constant)

import { CACHE_VERSION } from '@the_library/public/downloader';
// CACHE_VERSION = 1

DL2_SW_VERSION (constant)

Service worker build version. Used internally to detect when the SW script has been updated.


Framework Adapters (/downloader/{vue,react,solid})

Vue Composables

import {
  useFileStatus,
  useRenderStatus,
  useGlobalProgress,
  usePruning
} from '@the_library/public/downloader/vue';

// Reactive ref for one file's download state
const status = useFileStatus(txId); // ComputedRef<FileState | undefined>

// Reactive ref for render/page state
const render = useRenderStatus(txId); // ComputedRef<RenderState | undefined>

// Global download progress
const progress = useGlobalProgress(); // ComputedRef<DownloadSummary>

// LRU pruning activity
const pruning = usePruning(); // ComputedRef<PruningState>

React Hooks

import {
  useFileStatus,
  useRenderStatus,
  useGlobalProgress,
  usePruning
} from '@the_library/public/downloader/react';

// Synchronized external store hooks
const status = useFileStatus(txId);       // FileState | undefined
const render = useRenderStatus(txId);     // RenderState | undefined
const progress = useGlobalProgress();     // DownloadSummary
const pruning = usePruning();             // PruningState

Solid.js Primitives

import {
  useFileStatus,
  useRenderStatus,
  useGlobalProgress,
  usePruning
} from '@the_library/public/downloader/solid';

// Solid createMemo/createSignal-based reactivity
const [status] = useFileStatus(txId);
const [render] = useRenderStatus(txId);
const [progress] = useGlobalProgress();
const [pruning] = usePruning();

Service Worker API (@the_library/public/downloader/sw)

Installs a service worker that intercepts PDF/image requests, serving cached responses offline and persisting downloads across tab reloads.

registerDownloaderSW(): Promise<ServiceWorkerState>

Registers (or reuses) the downloader service worker.

import { registerDownloaderSW } from '@the_library/public/downloader/sw';

const state = await registerDownloaderSW();
if (state.active) {
  console.log('Service worker active and controlling pages');
}

Parameters: None

Returns: Promise<ServiceWorkerState>

Type: ServiceWorkerState

interface ServiceWorkerState {
  registered: boolean;     // SW is registered
  active: boolean;         // SW is controlling this page
  waiting: boolean;        // Update pending
  installing: boolean;     // New registration in progress
  controller: ServiceWorkerContainer | null;
}

swStatus(): Promise<ServiceWorkerState>

Checks current service worker status without re-registering.

import { swStatus } from '@the_library/public/downloader/sw';

const state = await swStatus();

Parameters: None

Returns: Promise<ServiceWorkerState>


clearDownloaderCaches(): Promise<void>

Drops all Cache API entries (PDFs, page images, previews), but keeps IndexedDB metadata records intact.

import { clearDownloaderCaches } from '@the_library/public/downloader/sw';

await clearDownloaderCaches();
console.log('Cache storage cleared, IndexedDB preserved');

Parameters: None

Returns: Promise<void>


nukeDownloaderStorage(): Promise<void>

Full reset: deletes everything — Cache API entries, IndexedDB records, service worker registration. Use when the user logs out or to recover storage quota.

import { nukeDownloaderStorage } from '@the_library/public/downloader/sw';

await nukeDownloaderStorage();
console.log('All download data erased');

Parameters: None

Returns: Promise<void>


unregisterDownloaderSW(): Promise<void>

Unregisters the service worker.

import { unregisterDownloaderSW } from '@the_library/public/downloader/sw';

await unregisterDownloaderSW();

Parameters: None

Returns: Promise<void>


2. Models API (@the_library/public/models)

The Models API provides the in-memory ORM, record cache, patch/replay engine, and schema registry for Sanctuary's data model. The root subpath exports only the framework-agnostic core; session bootstrap and reactive views are framework-specific and live under /models/{vue,react,solid,astro}.

Core Types & Registry

Registry (singleton, exported from registry.ts)

Holds enriched ModelDefinition for every registered object type — property IDs, field schemas, and relations.

import { Registry, type ModelDefinition } from '@the_library/public/models';

// Get schema by numeric type ID
const bookSchema: ModelDefinition = Registry.get(Book.type);
// bookSchema.name, bookSchema.typePrefix, bookSchema.props, bookSchema.instanceFields, ...

// Get schema by class name
const byName = Registry.getByName('Book');

Methods:

  • Registry.get(typeId: number): ModelDefinition — Returns the enriched schema for a type. Throws if typeId is not registered.

  • Registry.getByName(name: string): ModelDefinition — Returns the schema for a named type (e.g., 'Book'). Throws if no type with that name is registered.

  • Registry.all(): ModelDefinition[] — Returns all registered type schemas.

Type: ModelDefinition

interface ModelDefinition {
  name: string;                        // e.g., 'Book'
  type: number;                        // numeric type ID
  typePrefix: string;                  // e.g., 'B' for Book
  props: PropertyDefinition[];          // field schemas
  instanceFields: InstanceFieldInfo[]; // relation/reference fields
  relations: RelationDefinition[];
}

Record Cache & Reactivity

configureDb(options?: { cacheLimit?: number }): void

Sets the in-memory LRU cache size. Call before loading any records.

import { configureDb } from '@the_library/public/models';

// Lower cache limit for mobile devices
configureDb({ cacheLimit: 500 });

Parameters:

  • options.cacheLimit?: number — Maximum number of records to hold in memory. Default is 2000. Older records are evicted when the limit is exceeded.

Returns: void


getRecord(typeId: number, id: string): any

Synchronously retrieves a record from the cache.

import { getRecord } from '@the_library/public/models';
import { Book } from '@the_library/public/models';

if (hasRecord(Book.type, bookId)) {
  const book = getRecord(Book.type, bookId);
  console.log(book.title);
}

Parameters:

  • typeId: number — The model type ID (e.g., Book.type).
  • id: string — The record UID.

Returns: The record object (e.g., a Book instance) if cached.

Throws: If the record is not in cache (LRU eviction or never loaded). Use hasRecord() to check first, or call the model's LoadAsync() method to load from disk.


addRecord(typeId: number, id: string, record: any): void

Adds or updates a record in the cache.

import { addRecord } from '@the_library/public/models';

addRecord(Book.type, bookId, bookInstance);

Parameters:

  • typeId: number — Model type ID.
  • id: string — Record UID.
  • record: any — The record object.

Returns: void


removeRecord(typeId: number, id: string): void

Removes a record from the cache.

import { removeRecord } from '@the_library/public/models';

removeRecord(Book.type, bookId);

Parameters:

  • typeId: number — Model type ID.
  • id: string — Record UID.

Returns: void


hasRecord(typeId: number, id: string): boolean

Checks if a record is currently cached.

import { hasRecord } from '@the_library/public/models';

if (hasRecord(Book.type, bookId)) {
  // safe to call getRecord()
}

Parameters:

  • typeId: number — Model type ID.
  • id: string — Record UID.

Returns: boolean


pinRecord(typeId: number, id: string): void

Pins a record so it won't be evicted from the LRU cache. Use for the currently-open record, search results, etc.

import { pinRecord } from '@the_library/public/models';

// User opened a book — don't evict it while they're reading
pinRecord(Book.type, openBookId);

Parameters:

  • typeId: number — Model type ID.
  • id: string — Record UID.

Returns: void


unpinRecord(typeId: number, id: string): void

Unpins a record so it can be evicted again.

import { unpinRecord } from '@the_library/public/models';

// User closed the book
unpinRecord(Book.type, openBookId);

Parameters:

  • typeId: number — Model type ID.
  • id: string — Record UID.

Returns: void


addReactivitySystem(system: ReactivitySystem): void

Installs a framework-agnostic reactivity hook that fires when records change. Framework adapters call this once at boot.

import { addReactivitySystem } from '@the_library/public/models';

addReactivitySystem({
  track: (typeId, id) => { /* called when record added/changed */ },
  trigger: (typeId, id) => { /* called when record needs re-render */ },
});

setReactivitySystem(system: ReactivitySystem): void

Replaces the current reactivity system. Typically called by framework adapters during initialization.


Generated Models

Generated model classes (e.g., Book, Person, Tag) are built from your schema via pnpm generate and exported from both the root (@the_library/public/models) and the dedicated /models/models subpath.

import { Book, Person, NewBookWithId, ModelTypes } from '@the_library/public/models';
// equivalently: from '@the_library/public/models/models'

// Create a new record in memory (not yet persisted)
const book = NewBookWithId('book:abc123', 'username');
book.title = 'A Study in Scarlet';
book.author = 'Sir Arthur Conan Doyle';

// Load an existing record from disk
const loaded = await Book.LoadAsync('book:abc123');

// Check type at runtime
if (loaded instanceof Book) {
  console.log('It is a book');
}

// Generic record hydration (type unknown at compile time)
const typeId = 10; // some numeric type
const RecordClass = ModelTypes[typeId];
const generic = new RecordClass();

Key Functions:

  • NewBookWithId(id: string, creatorUsername: string): Book — Factory to create a new Book record in memory.

  • Book.LoadAsync(id: string): Promise<Book> — Loads a Book by UID from IndexedDB.

  • ModelTypes: { [typeId: number]: typeof ModelClass } — Maps numeric type IDs to model classes.


Schema Registry

The Registry singleton (above) holds ModelDefinition for each type. Accessed via Registry.get(typeId) or Registry.getByName(name).


Trash Index

A global, boot-owned index of which record ids (any object type) are currently deleted or flagged !safe — bucketed by the creatorUsername namespace the record belongs to. Fully automatic: there is nothing to register or feed it.

import { trashStore, scanTrash, type TrashStore } from '@the_library/public/models';

How it populates:

  • At bootscanTrash() runs a full pass over every currently-hydrated record right after hydrateAll() (both the initial bootModelsV2() call and every loadLanguage() call), deriving membership directly from each record's live deleted/safe state. No per-type registration needed — deleted/safe are universal base properties present on every model.
  • Live — registered internally as a ReactivitySystem (see addReactivitySystem, above). Orm.patch() fires this unconditionally for every mutation source — a local edit, restoreAccountSave()'s cross-device replay, and subscription-graph sync alike — so the index stays current automatically as patches land from anywhere, for any username. (An item lands in the trash by having its deleted/safe property patched — the same op every property edit uses — so this module never creates patches, it only mirrors them.)
  • Instant paint — a localStorage snapshot seeds the in-memory state synchronously at import time, so useTrash() reads a cached value immediately instead of empty until bootModelsV2() resolves; scanTrash() then reconciles it against the live corpus once boot completes.

trashStore (singleton)

import { Tag } from '@the_library/public/models/models';
import { trashStore } from '@the_library/public/models';

// All ids currently trashed for Tag, merged across every bucketed username
const allTrashedTagIds = trashStore.list(Tag.type);

// Merge only specific usernames' buckets
const mineOnly = trashStore.list(Tag.type, ['mine']);

const count = trashStore.count(Tag.type);
const buckets = trashStore.usernames(Tag.type); // e.g. ['canonical']

const unsubscribe = trashStore.subscribe(Tag.type, () => {
  console.log('Tag trash changed:', trashStore.count(Tag.type));
});

Methods:

  • trashStore.list(objectType: number, usernames?: string[]): number[] — Merges trashed ids across usernames. Empty array (default) merges every bucketed username for that type.

  • trashStore.count(objectType: number, usernames?: string[]): number — Same merge semantics as list(); returns the count.

  • trashStore.usernames(objectType: number): string[] — Usernames currently bucketed for a type (e.g. to populate a filter picker).

  • trashStore.subscribe(objectType: number, listener: () => void): () => void — Registers a listener, fired whenever that type's trash membership changes for any username. Returns an unsubscribe function.

Important — 'canonical' vs 'mine': Orm.creatorUsername resolves to the fixed string 'canonical' for any record id without the top bit set (isUserCreated() false) — which is essentially the entire shared catalog (Book, Tag, ...), regardless of who edited it or which sync path delivered the patch. Only records with a genuinely user-created id (top bit set) carry a specific creator's username. Filtering list()/count() to ['mine'] for catalog types will silently return nothing — call with no argument (or []) unless you specifically know the type is user-created content.

Type: TrashStore

interface TrashStore {
  list(objectType: number, usernames?: string[]): number[];
  count(objectType: number, usernames?: string[]): number;
  usernames(objectType: number): string[];
  subscribe(objectType: number, listener: () => void): () => void;
}

scanTrash(): void

Full (re)scan — walks every currently-hydrated record and reconciles trash membership against its live deleted/safe state. Called automatically by session.ts's hydrateAll() (boot + every loadLanguage() call); not normally called directly.

Parameters: None

Returns: void


Framework Adapters (/models/{vue,react,solid,astro})

Vue Composables

import {
  bootstrapModelsV2,
  useLevel,
  useDraft,
  useTrash,
  resetModelsV2Session
} from '@the_library/public/models/vue';

bootstrapModelsV2(options: BootstrapOptions): Promise<void>

Initializes the models subsystem once at app boot. Idempotent across Astro <ClientRouter /> navigations.

await bootstrapModelsV2({
  userLang: 'en',
  models: [{ type: Book.type, create: NewBookWithId }],
  localMode: '/corpus_v2',  // OR registry: { dataBlock, gateway }
  onBoot: (data) => console.log(`booted ${data.sidecars.length} sidecars`),
});

Parameters:

  • userLang: string — User's preferred language (ISO 639-1 or custom code).
  • models: ModelFactory[] — Array of { type: number; create: (id, username) => ModelInstance }.
  • localMode?: string — Folder path to serve corpus from (dev mode, mutually exclusive with registry).
  • registry?: { dataBlock: string; gateway: string } — Arweave data block & gateway (production mode).
  • onBoot?: (data: BootData) => void — Callback fired when bootstrap completes.

Returns: Promise<void> — resolves once all sidecars are hydrated.


useLevel(username?: string): Ref<LevelData>

Reactive per-username level state and corpus metadata.

import { useLevel } from '@the_library/public/models/vue';

const { level, progress } = useLevel('alice').value;
console.log(`Alice's level: ${level}`);

Parameters:

  • username?: string — Username. Defaults to the currently-logged-in user.

Returns: Ref<LevelData>

Type: LevelData

interface LevelData {
  username: string;
  level: number;
  progress: number; // 0-1
  lastUpdated: number; // timestamp
}

useDraft(getter: () => ModelInstance): { draft, isDirty, commit, rollback }

Tracks edits to a model instance before committing them back to the original.

import { useDraft } from '@the_library/public/models/vue';

const { draft, isDirty, commit, rollback } = useDraft(() => book);

// Edit the draft
draft.value.title = 'New Title';

// Check if unsaved changes exist
if (isDirty.value) {
  await commit(); // apply to original book
  // or rollback() to discard
}

Parameters:

  • getter: () => ModelInstance — A function returning the record to edit (usually a computed ref).

Returns:

{
  draft: Ref<ModelInstance>;  // editable proxy of the original
  isDirty: Ref<boolean>;      // true if any properties differ
  commit: () => Promise<void>; // apply changes to original
  rollback: () => void;        // discard changes
}

useTrash(objectType: number, usernames?: string[]): { count: Ref<number>; getIds: () => number[] }

Reactive view over the global Trash Index for one object type, merged across usernames. Population and live updates are entirely automatic — nothing to register, nothing to feed it.

import { useTrash } from '@the_library/public/models/vue';
import { Tag } from '@the_library/public/models/models';

const { count, getIds } = useTrash(Tag.type); // merges every username (canonical catalog trash)

Parameters:

  • objectType: number — Model type ID (e.g. Tag.type).
  • usernames?: string[] — Usernames to merge. Defaults to [] (every known username — see the 'canonical' vs 'mine' note in Trash Index).

Returns:

{
  count: Ref<number>;
  getIds: () => number[];
}

resetModelsV2Session(): void

Clears the session and cached level state. Used for logout and testing/HMR.

import { resetModelsV2Session } from '@the_library/public/models/vue';

resetModelsV2Session();

React Hooks

Same API as Vue, but exported from @the_library/public/models/react:

import {
  bootstrapModelsV2,
  useLevel,
  useModelUpdate,
  useTrash,
  resetModelsV2Session
} from '@the_library/public/models/react';

useLevel(username?: string): LevelData

Hook returning the current level data. Re-renders when level changes.

useModelUpdate(record: ModelInstance): boolean

Subscribes to updates for a single record, triggering re-render on change. Returns true if subscription is active.

useTrash(objectType: number, usernames?: string[]): { count: number; getIds: () => number[] }

Re-renders the calling component whenever the global Trash Index changes for objectType, merged across usernames (defaults to [] — every known username). Population and live updates are entirely automatic.

import { useTrash } from '@the_library/public/models/react';
import { Tag } from '@the_library/public/models/models';

const { count, getIds } = useTrash(Tag.type);

Note: React does not export useDraft (no fine-grained reactivity primitive like Vue's Ref). Use manual imperative edits or a state manager instead.


Solid.js Primitives

import {
  bootstrapModelsV2,
  useLevel,
  subscribeRecord,
  useTrash,
  resetModelsV2Session
} from '@the_library/public/models/solid';

useLevel(username?: string): () => LevelData

Signal factory returning the current level data.

subscribeRecord(record: ModelInstance, callback: (record) => void): () => void

Manual subscription to record updates. Returns unsubscribe function.

useTrash(objectType: number, usernames?: string[]): { count: () => number; getIds: () => number[] }

Signal accessor over the global Trash Index for one object type, merged across usernames (defaults to [] — every known username). Population and live updates are entirely automatic.

import { useTrash } from '@the_library/public/models/solid';
import { Tag } from '@the_library/public/models/models';

const { count, getIds } = useTrash(Tag.type);
return <span>{count()}</span>;

Astro / Static Generation

import {
  bootstrapModelsV2,
  resetModelsV2Session,
  subscribeRecord
} from '@the_library/public/models/astro';

bootstrapModelsV2(options): Promise<void>

Same as Vue/React.

subscribeRecord(record, callback): () => void

Manual subscription (islands use this for client-side updates).

Note: Astro does not export useLevel, useDraft, or useTrash — use vanilla JS on the client (trashStore directly from @the_library/public/models works fine, it's framework-agnostic).


Patch & Session Management

Low-level APIs (not normally called directly; used by bootstrapModelsV2):

serializePatches(patches: Patch[]): Uint8Array

Encodes patches to binary for transmission or storage.

deserializePatches(data: Uint8Array): Patch[]

Decodes binary patches.

applyRestoredPatches(patches: Patch[], models: ModelFactory[]): void

Applies a set of deserialized patches to the in-memory records.

getPatchInstanceByAccount(username: string): Patches

Retrieves the patch store for a specific account.


3. Web3 API (@the_library/public/web3)

The Web3 API consolidates blockchain login, wallet connections, transaction mutations, session state, on-chain subscriptions, and contract/address resolution.

3.1 Session API

Manages wallet accounts, session persistence, and the centralized write-transaction pipeline.

sessionStore (singleton)

The canonical, framework-agnostic store for known and active wallet accounts.

import { sessionStore } from '@the_library/public/web3';

const { active, known } = sessionStore.getState();
console.log(`Active account: ${active?.account}`);
console.log(`${known.length} known accounts`);

// React to changes
const unsubscribe = sessionStore.subscribe(() => {
  const newState = sessionStore.getState();
  console.log('Session changed', newState);
});

Methods:

  • sessionStore.getState(): SessionState — Returns current state: { active: Web3SessionAccount | null; known: Web3SessionAccount[] }.

  • sessionStore.subscribe(callback: () => void): () => void — Registers a listener, returns unsubscribe function.

Type: Web3SessionAccount

interface Web3SessionAccount {
  account: string;              // hex address
  chainId: number;
  wallet: WalletType;           // 'metamask' | 'private_key'
  username?: string;
  userId?: number;
  hasAccount: boolean;          // registered on-chain
  level?: number;
  projectBalance?: {
    contributions: number;
    allocated: number;
    remaining: number;
  };
  donationsPerProject?: number[];
  metadata?: {
    country?: string;
    language?: string;
    lastSyncTime?: number;
  };
}

syncAccount(address: string, chainId: number, walletType: WalletType): Promise<Web3SessionAccount>

Hydrates a wallet account after connection by pulling hasAccount, username, level, and other on-chain data. Also kicks off background subscription sync for the account's userId.

import { syncAccount } from '@the_library/public/web3';

const account = await syncAccount('0xabc...', 1116, 'metamask');
console.log(`${account.username} is level ${account.level}`);

Parameters:

  • address: string — Wallet address (hex).
  • chainId: number — Chain ID (1116, 1114, etc.).
  • walletType: WalletType'metamask' or 'private_key'.

Returns: Promise<Web3SessionAccount> — The hydrated account record.

Side effects:

  • Adds/updates the account in sessionStore.
  • Persists the account to localStorage.
  • Kicks off a background subscriptionSync for the account's userId.

useWeb3Session() (Vue composable)

Reactive wrapper over sessionStore.

import { useWeb3Session } from '@the_library/public/web3/vue';

const {
  accounts,           // Ref<Web3SessionAccount[]> — all known accounts
  registeredAccounts, // Ref<Web3SessionAccount[]> — only hasAccount=true
  activeAccount,      // Ref<Web3SessionAccount | null>
  isConnecting,       // Ref<boolean>
  setActive,          // (account: Web3SessionAccount) => void
} = useWeb3Session();

3.2 Client API

Typed read and write adapters over deployed contracts.

getReadClient(chainId: number, environment?: 'production' | 'staging'): ReadOnlyDomainAPI

Gets the read-only client for a chain. Blocks until contract addresses/ABIs are loaded from the registry.

import { getReadClient } from '@the_library/public/web3';

const client = getReadClient(1116);
await client.ready; // wait for registry load

const balance = await client.projectManagerStorage.balanceOfAddress('0xabc...');
const level = await client.archivistStorage.userLevel(userId);
const nbAccounts = await client.bouncerStorage.nbAccounts();

Parameters:

  • chainId: number — EVM chain ID (1116, 1114, 84532, etc.).
  • environment?: 'production' | 'staging' — Defaults to 'production'. Use 'staging' to read staging-deployed contract addresses.

Returns: ReadOnlyDomainAPI — Typed interface to all contract reads.

Type: ReadOnlyDomainAPI

interface ReadOnlyDomainAPI {
  readonly chainId: number;
  readonly ready: Promise<void>;
  readonly bouncerStorage: BouncerStorageReadAPI;
  readonly archivistStorage: ArchivistStorageReadAPI;
  readonly scientistStorage: ScientistStorageReadAPI;
  readonly projectManagerStorage: ProjectManagerStorageReadAPI;
  readonly factory: FactoryReadAPI;
  readonly addressRegistry: AddressRegistryReadAPI;
  readonly subscriptionManager: SubscriptionManagerReadAPI;
  readonly libraryRegistryStorage: LibraryRegistryStorageReadAPI;
  readonly publicLibraryStorage: PublicLibraryStorageReadAPI;
  getUsdPrice(): Promise<number>;
  getRegistryStatus(): Promise<any>;
}

Contract APIs

BouncerStorageReadAPI

Account identity and registration queries:

  • hasAccount(address: string): Promise<boolean> — Is the address registered?
  • userInfos(address: string): Promise<[username, country, language, userId]> — Fetch user metadata by address.
  • userData(userId: number): Promise<[id, addr, username, language, country]> — Fetch user metadata by ID.
  • getUsernameByAddress(address: string): Promise<string> — Get username for an address.
  • userIdOf(address: string): Promise<number> — Get user ID for an address.
  • userIdToUsername(userId: number): Promise<string> — Get username for a user ID.
  • usernameToUserId(username: string): Promise<number> — Get user ID for a username.
  • userAddr(userId: number): Promise<string> — Get address for a user ID.
  • nbAccounts(): Promise<number> — Total registered accounts on this chain.
  • getAllLocationCounts(): Promise<any[]> — Aggregate account counts by location.
  • getActiveLocationCount(): Promise<number> — Number of locations with at least one account.
  • identityStats(): Promise<[nbVerbs, nbAdjectives]> — Stats on generated usernames.

ArchivistStorageReadAPI

User level and backup history:

  • userLevel(userId: number): Promise<number> — Reading level for a user.
  • nbWrites(userId: number): Promise<number> — Total patches authored.
  • loadActions(userId: number): Promise<[bigint[], bigint[], string[]]> — All patches for a user (raw format).
  • loadActionsSince(userId: number, index: number): Promise<[bigint[], bigint[], string[]]> — Patches since a given index.

ScientistStorageReadAPI

Anonymized reading statistics:

  • getLastMonthId(): Promise<number> — Latest month in the stats index.
  • getDeploymentDate(): Promise<[year, month]> — When the contract was deployed.
  • getStatsRaw(action: number, objectType: number, monthId: number): Promise<[bigint[], number[]]> — Raw stats for a category/type/month.

ProjectManagerStorageReadAPI

Project discovery and donation voting:

  • nbProjects(): Promise<number> — Total projects on-chain.
  • getProjectSupportedLanguages(projectId: number): Promise<string[]> — Languages available for a project.
  • loadProject(projectId: number): Promise<Project> — Fetch full project metadata.
  • balanceOfAddress(address: string): Promise<{ total, donations, unspent }> — Wallet's donation balance breakdown.
  • addressDonationsPerProject(address: string): Promise<number[]> — Vote allocation by project (array indexed by projectId-1).
  • projectVotingBalances(projectId: number): Promise<number> — Total votes allocated to a project.

FactoryReadAPI

Global corpus metadata:

  • load(): Promise<[bigint[], bigint[], string[]]> — All patches in the corpus (raw format).
  • loadUsername(username: string): Promise<[bigint[], bigint[], string[]]> — Patches for one user.
  • loadUsernameSince(username: string, index: number): Promise<[bigint[], bigint[], string[]]> — Incremental patch fetch.
  • nbWritesByUsername(username: string): Promise<number> — Patch count for a user.

AddressRegistryReadAPI

Dynamic contract address/ABI resolution:

  • getLatestContract(name: string): Promise<[address, abiUrl]> — Latest address for a named contract.
  • getContractHistory(name: string): Promise<AddressRegistryContractRecord[]> — All addresses ever deployed for a contract.
  • getAllContractNames(): Promise<string[]> — List of all contracts.
  • getLatestData(key: string): Promise<string> — Fetch arbitrary key-value data from the registry.

SubscriptionManagerReadAPI

Who-follows-whom graph:

  • getSubscriptions(userId: number): Promise<number[]> — List of user IDs that this user subscribes to.
  • getSubscriptionCount(userId: number): Promise<bigint> — Total subscriptions for a user.
  • isSubscribed(subscriber: number, target: number): Promise<boolean> — Is subscriber following target?
  • scoreOf(userId: number): Promise<bigint> — Social score (based on follower count, etc.).

LibraryRegistryStorageReadAPI

Library Collection and Registry metadata:

  • getUnverifiedCollectionIds(): Promise<string[]> — List of pending collection IDs.
  • getVerifiedCollectionIds(): Promise<string[]> — List of verified collection IDs.
  • getCollection(id: string): Promise<Collection> — Get full collection metadata by ID.

LibraryRegistryStorageWriteAPI

Library Collection and Registry mutations (Requires Admin Authorization):

  • addUnverifiedCollection(input: CollectionInput, options?: TransactionOptions): Promise<any> — Submits a new collection for review.
  • verifyCollection(id: string, options?: TransactionOptions): Promise<any> — Approves a pending collection.
  • rejectCollection(id: string, options?: TransactionOptions): Promise<any> — Rejects and removes a pending collection.
  • updateCollectionStats(id: string, initialBookCount: number, dSafeBookCount: number, options?: TransactionOptions): Promise<any> — Updates statistics for a collection.
  • setImportStatus(id: string, status: number, options?: TransactionOptions): Promise<any> — Updates the import status enum.
  • setPublished(id: string, isPublished: boolean, options?: TransactionOptions): Promise<any> — Toggles publication status of a collection.
  • setCollectionPublicLibrary(id: string, publicLibraryId: number, options?: TransactionOptions): Promise<any> — Links a collection to a public library.
  • setPublicLibraryStorage(storageAddr: string, options?: TransactionOptions): Promise<any> — Sets the address of the PublicLibraryStorage contract.

PublicLibraryStorageReadAPI

Public Library cataloging metadata:

  • libraryExists(id: number): Promise<boolean> — Checks if a library ID exists.
  • getPublicLibrary(id: number): Promise<PublicLibrary> — Get full public library metadata by ID.
  • nbLibraries(): Promise<number> — Returns the total number of registered public libraries.

PublicLibraryStorageWriteAPI

Public Library management (Requires Admin Authorization):

  • addPublicLibrary(input: PublicLibraryInput, options?: TransactionOptions): Promise<any> — Creates a new public library record.
  • updatePublicLibrary(id: number, input: PublicLibraryInput, options?: TransactionOptions): Promise<any> — Updates an existing public library record.

Write Operations

import { writeOperations, resetTransactionState } from '@the_library/public/web3';

await writeOperations.register(walletType, chainId, address, registrationFee);
await writeOperations.vote(walletType, chainId, address, projectId, language, voteAmount);
await writeOperations.save(walletType, chainId, address, compressedActions, textIndexes, textData, level);
await writeOperations.subscribe(walletType, chainId, address, subscriberUserId, targetUserId);
await writeOperations.unsubscribe(walletType, chainId, address, subscriberUserId, targetUserId);

All write operations:

  • Acquire a 1-minute run-lock (only one transaction per address/chain at a time).
  • Emit WalletEvents state notifications.
  • Automatically refresh the account via syncAccount() on success.

If a transaction throws and the run-lock needs to be cleared manually, call resetTransactionState().


Chain Metadata

import { getChain, EVM_CHAINS, DEFAULT_CHAIN_ID } from '@the_library/public/web3';

const chain = getChain(1116);
// chain.name, chain.symbol, chain.shortName, chain.logo, chain.explorer, 
// chain.rpc, chain.main (true for mainnet), chain.deployed, chain.stagingDeployed

const deployedChains = Object.values(EVM_CHAINS).filter(c => c.deployed);

Type: EvmChainConfig

interface EvmChainConfig {
  name: string;              // 'CORE' | 'tCORE2' | 'Base Sepolia'
  shortName: string;         // 'core' | 'tcore2' | ...
  chainId: number;
  symbol: string;            // 'CORE' | 'CORETST' | ...
  logo: string;              // URL to chain logo
  explorer: string;          // Block explorer URL
  rpc: string[];             // RPC endpoints
  main: boolean;             // Mainnet vs testnet
  deployed: boolean;         // Contracts deployed on this chain
  stagingDeployed?: boolean;
}

Vue Composable: useChain(chainId)

import { useChain } from '@the_library/public/web3/vue';

const { chain, client, usdPrice, refreshPrice, isMainnet, chainRouteQuery } = useChain(1116);
// chain: EvmChainConfig
// client: ReadOnlyDomainAPI (ready to use)
// usdPrice: Ref<number> — live USD price polling
// refreshPrice: () => Promise<void>
// isMainnet: boolean
// chainRouteQuery: { chainId: '1116' } — useful for router links

3.3 Registry API

Dynamic contract address and ABI resolution from the on-chain AddressRegistry.

addressLoader (singleton)

import { addressLoader, setRegistryBaseUrl } from '@the_library/public/web3';

// Set custom registry host (before anything else runs)
setRegistryBaseUrl('https://registry.world.bibliotech.com');

// Subscribe to per-contract load progress
const unsubscribe = addressLoader.subscribe((chainId, status) => {
  console.log(`chain ${chainId}: ${status.loaded}/${status.total} contracts loaded`);
});

// Get resolved address/ABI for a contract
const addr = addressLoader.getAddress(chainId, 'Factory');
const abi = addressLoader.getAbi(chainId, 'Factory');

Methods:

  • addressLoader.subscribe(callback: (chainId, LoadingStatus) => void): () => void — Listen for load progress.

  • addressLoader.getAddress(chainId: number, contractName: string): string | undefined — Resolved contract address, or undefined if not yet loaded.

  • addressLoader.getAbi(chainId: number, contractName: string): any[] | undefined — Resolved ABI array, or undefined if not yet loaded.

  • addressLoader.loadManifest(environment: 'production' | 'staging'): Promise<Manifest> — Manually load the registry manifest (auto-called by clients).


setRegistryBaseUrl(url: string): void

Override the default registry host URL (normally https://registry.world.bibliotech.com). Call before any clients are instantiated.


3.4 Subscription API

Walks the on-chain subscription graph (who-follows-whom) and incrementally fetches patches.

getSubscriptionClient(chainId: number): SubscriptionClient

Gets a chain-scoped subscription client.

import { getSubscriptionClient } from '@the_library/public/web3';

const subs = getSubscriptionClient(1116);

// First sync: full BFS walk + patch fetch
const { patches, cursor, truncated } = await subs.sync(rootUserId);

// Later: incremental — only fetch new patches since cursor
const next = await subs.syncSince(cursor);

// Query the graph
const followees = await subs.getSubscriptions(userId);
const score = await subs.getScore(userId);

Methods:

  • subs.sync(rootUserId: number): Promise<SyncResult> — Walk subscription graph starting from a user, fetch all patches.

  • subs.syncSince(cursor: SyncCursor): Promise<SyncResult> — Incremental sync using a persisted cursor.

  • subs.getSubscriptions(userId: number): Promise<number[]> — List of users this user subscribes to.

  • subs.getScore(userId: number): Promise<number> — Social score for a user.

Type: SyncResult

interface SyncResult {
  patches: Patch[];
  cursor: SyncCursor;     // Persist this to resume next sync
  truncated: boolean;     // true if result was truncated (more data available)
}

cursorStore (IndexedDB persistence)

import { cursorStore } from '@the_library/public/web3';

const cursor = await cursorStore.get(userId);
const result = cursor 
  ? await subs.syncSince(cursor)
  : await subs.sync(userId);
await cursorStore.set(userId, result.cursor);

Methods:

  • cursorStore.get(userId: number): Promise<SyncCursor | null> — Retrieve persisted cursor, or null if never synced.

  • cursorStore.set(userId: number, cursor: SyncCursor): Promise<void> — Save cursor for next sync.


Vue Composable: useSubscriptionSync(userId)

import { useSubscriptionSync } from '@the_library/public/web3/vue';

const { cursor, patches, isLoading, refresh } = useSubscriptionSync(userId);
// cursor: Ref<SyncCursor>
// patches: Ref<Patch[]>
// isLoading: Ref<boolean>
// refresh: () => Promise<void>

3.5 Contracts API

Static ABI exports for contracts that don't use dynamic resolution.

import { addressRegistryAbi, pythAbi } from '@the_library/public/web3';

// Use with viem directly:
import { createPublicClient, http } from 'viem';

const client = createPublicClient({ 
  chain: /*...*/, 
  transport: http() 
});

const data = await client.readContract({
  address: '0x...',
  abi: addressRegistryAbi,
  functionName: 'getLatestContract',
  args: ['Factory'],
});

3.6 Events API

Typed pub/sub bus for wallet and transaction state notifications.

WalletEvents (typed pub/sub)

import { WalletEvents, type WalletState, type WalletError } from '@the_library/public/web3';

const unsubWalletState = WalletEvents.onWalletStateEvent((e) => {
  // e: { wallet, chainId, event: WalletState, functionName?, timestamp }
  if (e.event === 'TRANSACTION_STARTED') showSpinner();
  if (e.event === 'TRANSACTION_DONE') hideSpinner();
  if (e.event === 'ACCOUNT_SYNCED') updateUI();
});

const unsubError = WalletEvents.onWalletError((e) => {
  // e: { wallet, chainId, reason: WalletError, timestamp }
  toast.error(e.reason);
});

const unsubSaveRestored = WalletEvents.onSaveRestored((e) => {
  // e: { compressedActions, indexes, stringIndexes, timestamp }
  // Patches from on-chain state that outran local edits
});

const unsubPatchesSynced = WalletEvents.onSubscriptionPatchesSynced((e) => {
  // e: { rootUserId, patches: Patch[], timestamp }
  // Subscription graph patches fetched in background
});

// Unsubscribe
unsubWalletState();
unsubError();
unsubSaveRestored();
unsubPatchesSynced();

Enums:

WalletState — transaction lifecycle events:

  • 'WALLET_CONNECTED'
  • 'WALLET_DISCONNECTED'
  • 'TRANSACTION_STARTED'
  • 'TRANSACTION_DONE'
  • 'TRANSACTION_FAILED'
  • 'ACCOUNT_SYNCED'
  • 'SUBSCRIPTION_SYNC_STARTED'
  • 'SUBSCRIPTION_SYNC_DONE'

WalletError — error reasons:

  • 'NETWORK_ERROR'
  • 'TRANSACTION_REJECTED'
  • 'INSUFFICIENT_BALANCE'
  • 'UNKNOWN_ERROR'
  • etc. (see source for full list)

Low-level EventBus (rarely used)

import { getEventBus } from '@the_library/public/web3';

const bus = getEventBus();
const unsubscribe = bus.on('topic', (data) => { /* handle */ });
bus.emit('topic', data);
bus.once('topic', (data) => { /* one-time listener */ });
bus.clear('topic'); // remove all listeners

3.7 Wallets API

Wallet connectors (MetaMask, PrivateKey) and metadata.

getConnector(type: WalletType): WalletConnector | undefined

Retrieves a registered wallet connector by type.

import { getConnector } from '@the_library/public/web3';

const metamask = getConnector('metamask');
if (metamask?.isAvailable()) {
  const { address, chainId } = await metamask.connect();
}

Parameters:

  • type: WalletType'metamask' | 'private_key'

Returns: The connector, or undefined if not registered (e.g., bootstrapWebSDK() hasn't run yet).


getRegisteredConnectors(): WalletConnector[]

Lists all registered connectors.

import { getRegisteredConnectors } from '@the_library/public/web3';

const connectors = getRegisteredConnectors();
// array of MetaMaskConnector, PrivateKeyConnector, etc.

walletMeta (metadata for each wallet)

import { walletMeta } from '@the_library/public/web3';

const meta = walletMeta.metamask;
// {
//   displayName: 'MetaMask',
//   logoUrl: 'https://...',
//   description: '...',
//   website: 'https://metamask.io',
//   isInstalled(): boolean,
//   isInstallable(): boolean,
//   getInstallUrl(): string,
// }

if (!meta.isInstalled() && meta.isInstallable()) {
  window.open(meta.getInstallUrl(), '_blank');
}

Private Key Storage

import { storePrivateKey, hasPrivateKey, hasAnyPrivateKey } from '@the_library/public/web3';

storePrivateKey(1116, '0x1234...'); // raw hex, no '0x' prefix required
if (hasPrivateKey(1116)) {
  // PrivateKeyConnector can connect to this chain
}

if (hasAnyPrivateKey()) {
  // At least one chain has a stored key
}

Warning: Private keys are stored in plaintext localStorage. Only use for dev/test wallets, never for real user funds.


3.8 Projects API

Project discovery and voting.

loadProject(chainId: number, language: string, projectId: number, refresh?: boolean): Promise<ProjectLocale>

Loads a single project by ID with language fallback. Cached automatically.

import { loadProject } from '@the_library/public/web3';

const project = await loadProject(1116, 'eng', 5);
console.log(`${project.version.name} — ${project.balance} tokens`);

// Force re-fetch from chain, bypassing cache
const fresh = await loadProject(1116, 'eng', 5, true);

Parameters:

  • chainId: number — Chain ID.
  • language: string — Preferred language code (e.g., 'eng', 'deu', 'spa').
  • projectId: number — On-chain project ID (1-indexed).
  • refresh?: boolean — If true, bypass cache and refetch from chain.

Returns: Promise<ProjectLocale>

Throws: If cache miss and chain unreachable.


loadProjects(chainId: number, language: string): Promise<Array<ProjectLocale | null>>

Loads all projects for a chain/language. Returns cached projects if chain is unreachable (with console warning).

import { loadProjects } from '@the_library/public/web3';

const projects = await loadProjects(1116, 'eng');
const validProjects = projects.filter(p => p !== null);

Parameters:

  • chainId: number — Chain ID.
  • language: string — Preferred language code.

Returns: Promise<Array<ProjectLocale | null>> — Array where null entries represent projects that failed to load.


projectLocale(project: Project, language: string, chainId: number): ProjectLocale

Helper to convert raw Project data to ProjectLocale with language selection and decimal normalization.

import { projectLocale } from '@the_library/public/web3';

const raw = await client.projectManagerStorage.loadProject(5);
const locale = projectLocale(raw, 'eng', 1116);

Parameters:

  • project: Project — Raw contract data.
  • language: string — Preferred language.
  • chainId: number — For decimal normalization.

Returns: ProjectLocale


Vue Composable: useLoadProjects(chainId, language)

import { useLoadProjects } from '@the_library/public/web3/vue';

const chainId = ref(1116);
const language = ref('eng');

const { projects, isLoading, error, reload } = useLoadProjects(chainId, language);
// projects: Ref<Array<ProjectLocale | null>>
// isLoading: Ref<boolean>
// error: Ref<Error | null>
// reload: () => Promise<void>

3.9 Chain & Network Configuration

EVM_CHAINS (constant)

import { EVM_CHAINS } from '@the_library/public/web3';

// EVM_CHAINS = {
//   1116: { name: 'CORE', ... },
//   1114: { name: 'tCORE2', ... },
//   84532: { name: 'Base Sepolia', ... },
// }

DEFAULT_CHAIN_ID (constant)

The default chain for new users (usually production mainnet, e.g., 1116).


getChain(chainId: number): EvmChainConfig

Gets full metadata for a chain. Throws if chainId is not registered.

import { getChain } from '@the_library/public/web3';

const chain = getChain(1116);
console.log(`${chain.name} (${chain.symbol})`);

3.10 Vue Composables (@the_library/public/web3/vue)

bootstrapWebSDK(options?: BootstrapOptions): Promise<BootstrapResult>

Single app-wide initialization: registers connectors, loads persisted session, hydrates accounts.

import { bootstrapWebSDK, BootstrapResultKey } from '@the_library/public/web3/vue';

const result = await bootstrapWebSDK({
  withTest: true,
  environment: 'production',
  chainFilter: [1116, 1114], // optional: limit to these chains
});

await result.ready; // wait for account discovery

// Provide at app root
app.provide(BootstrapResultKey, result);

Parameters:

  • options.withTest?: boolean — Include test chains (Base Sepolia).
  • options.environment?: 'production' | 'staging' — Contract environment.
  • options.chainFilter?: number[] — Optional: only bootstrap these chains.

Returns: Promise<BootstrapResult>

Type: BootstrapResult

interface BootstrapResult {
  ready: Promise<void>;
  chains: EvmChainConfig[];
  installedConnectors: WalletConnector[];
  installableConnectors: WalletConnector[];
  primaryAccount: Web3SessionAccount | null;
}

useBootstrap(): BootstrapResult

Retrieves the app-wide bootstrap result (must have been provided via app.provide(BootstrapResultKey, result)).

import { useBootstrap } from '@the_library/public/web3/vue';

const { chains, installedConnectors, primaryAccount } = useBootstrap();

useWeb3Session()

Reactive wrapper over sessionStore.

import { useWeb3Session } from '@the_library/public/web3/vue';

const {
  accounts,           // Ref<Web3SessionAccount[]>
  registeredAccounts, // Ref<Web3SessionAccount[]> filtered by hasAccou