34 KiB
@opchan/core API Reference
Complete API documentation for all classes, interfaces, and utilities in the OpChan Core SDK.
Table of Contents
- OpChanClient
- DelegationManager
- LocalDatabase
- ForumActions
- UserIdentityService
- RelevanceCalculator
- MessageManager
- BookmarkService
- MessageValidator
- Type Definitions
- Utility Functions
OpChanClient
Main client class that orchestrates all services and provides a unified interface.
Constructor
constructor(config: OpChanClientConfig)
Parameters:
config.wakuConfig- Waku network configurationcontentTopic- Content topic for Waku messages (e.g.,/opchan/1/messages/proto)reliableChannelId- Channel ID for reliable messaging (e.g.,opchan-messages)
config.reownProjectId- Optional Reown/WalletConnect project ID
Example:
const client = new OpChanClient({
wakuConfig: {
contentTopic: '/opchan/1/messages/proto',
reliableChannelId: 'opchan-messages'
},
reownProjectId: 'your-project-id'
});
Properties
config: OpChanClientConfig
Client configuration object passed to constructor.
messageManager: DefaultMessageManager
Manages Waku network connectivity and message transmission.
database: LocalDatabase
IndexedDB-backed local storage with in-memory caching.
forumActions: ForumActions
High-level actions for content creation and moderation.
relevance: RelevanceCalculator
Content relevance scoring algorithm.
messageService: MessageService
Low-level message signing and broadcasting.
userIdentityService: UserIdentityService
User identity resolution and profile management.
delegation: DelegationManager
Cryptographic key delegation system.
DelegationManager
Manages browser key delegation with wallet signatures or anonymous sessions.
Methods
delegate(address, duration, signFunction)
Create a wallet-signed delegation authorizing browser keys.
Signature:
async delegate(
address: `0x${string}`,
duration: '7days' | '30days' = '7days',
signFunction: (message: string) => Promise<string>
): Promise<boolean>
Parameters:
address- Wallet address to delegate fromduration- Delegation validity period ('7days' or '30days')signFunction- Function that signs the authorization message with wallet
Returns: true if delegation created successfully, false otherwise
Example:
import { signMessage } from 'viem/accounts';
const success = await client.delegation.delegate(
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
'7days',
async (message) => await signMessage({ message, account: walletAddress })
);
Flow:
- Generates Ed25519 browser keypair
- Creates authorization message with expiry timestamp and nonce
- Signs authorization message with wallet (via
signFunction) - Stores delegation in IndexedDB
- Returns success status
delegateAnonymous(duration)
Create an anonymous delegation without wallet signature.
Signature:
async delegateAnonymous(
duration: '7days' | '30days' = '7days'
): Promise<string>
Parameters:
duration- Delegation validity period
Returns: Session ID (UUID) for the anonymous user
Example:
const sessionId = await client.delegation.delegateAnonymous('7days');
// sessionId: "a3f5c2d1-8e9b-4c7a-b6d5-3e2f1a0b9c8d"
Flow:
- Generates Ed25519 browser keypair
- Generates UUID session ID
- Creates expiry timestamp and nonce
- Stores anonymous delegation in IndexedDB
- Returns session ID as user address
signMessage(message)
Sign a message with the delegated browser key.
Signature:
async signMessage(
message: UnsignedMessage
): Promise<OpchanMessage | null>
Parameters:
message- Unsigned message object (cell, post, comment, vote, etc.)
Returns: Signed message with signature and delegation proof, or null if delegation invalid
Example:
const unsignedPost = {
type: MessageType.POST,
id: 'post-id',
cellId: 'cell-id',
title: 'Hello',
content: 'World',
timestamp: Date.now(),
author: userAddress
};
const signed = await client.delegation.signMessage(unsignedPost);
if (signed) {
// Message is now signed and ready to send
await client.messageManager.sendMessage(signed);
}
Signature Process:
- Retrieves cached delegation (or loads from storage)
- Checks if delegation is valid (not expired)
- Creates message payload (excluding signature fields)
- Signs payload with browser private key (Ed25519)
- Attaches signature, browser public key, and delegation proof
- Returns signed message
verify(message)
Verify a signed message's authenticity.
Signature:
async verify(message: OpchanMessage): Promise<boolean>
Parameters:
message- Signed message to verify
Returns: true if message is valid, false otherwise
Example:
const isValid = await client.delegation.verify(message);
if (isValid) {
await client.database.applyMessage(message);
}
Verification Process:
- Checks required fields (signature, browserPubKey, author)
- Verifies message signature with browser public key
- If wallet delegation: verifies delegation proof
- If anonymous: validates session ID format (UUID)
- Returns validation result
verifyWithReason(message)
Verify message and return detailed validation reasons.
Signature:
async verifyWithReason(
message: OpchanMessage
): Promise<{ isValid: boolean; reasons: string[] }>
Example:
const result = await client.delegation.verifyWithReason(message);
if (!result.isValid) {
console.error('Validation failed:', result.reasons);
}
getStatus(currentAddress?)
Get current delegation status.
Signature:
async getStatus(
currentAddress?: string
): Promise<DelegationFullStatus>
Parameters:
currentAddress- Optional address to check against stored delegation
Returns:
interface DelegationFullStatus {
hasDelegation: boolean;
isValid: boolean;
timeRemaining?: number; // milliseconds
publicKey?: string;
address?: `0x${string}`;
proof?: DelegationProof;
}
Example:
const status = await client.delegation.getStatus(userAddress);
if (!status.isValid) {
console.log('Delegation expired or invalid');
// Re-authorize user
} else {
console.log(`Valid for ${Math.round(status.timeRemaining! / 3600000)} more hours`);
}
clear()
Clear stored delegation from IndexedDB.
Signature:
async clear(): Promise<void>
Example:
await client.delegation.clear();
// User needs to re-authorize
LocalDatabase
IndexedDB-backed local storage with in-memory caching for fast reads.
Properties
cache: LocalDatabaseCache
In-memory cache of all content. Fast synchronous access.
interface LocalDatabaseCache {
cells: { [id: string]: CellMessage };
posts: { [id: string]: PostMessage };
comments: { [id: string]: CommentMessage };
votes: { [key: string]: VoteMessage };
moderations: { [key: string]: ModerateMessage };
userIdentities: { [address: string]: UserIdentityCache };
bookmarks: { [id: string]: Bookmark };
}
Example:
// Synchronous access to cached data
const cells = Object.values(client.database.cache.cells);
const posts = Object.values(client.database.cache.posts);
// Filter by relationship
const cellPosts = posts.filter(p => p.cellId === 'cell-id');
Methods
open()
Open IndexedDB and hydrate in-memory cache.
Signature:
async open(): Promise<void>
Example:
const client = new OpChanClient(config);
await client.database.open(); // MUST call before use
Hydration Process:
- Opens IndexedDB connection
- Loads all cells, posts, comments, votes, moderations from stores
- Populates in-memory cache
- Loads pending message IDs
- Ready for use
applyMessage(message)
Validate and store an incoming message.
Signature:
async applyMessage(message: unknown): Promise<boolean>
Parameters:
message- Message to validate and store
Returns: true if message was newly processed and stored, false if invalid or duplicate
Example:
client.messageManager.onMessageReceived(async (message) => {
const wasNew = await client.database.applyMessage(message);
if (wasNew) {
console.log('New message stored:', message.type);
updateUI();
}
});
Process:
- Validates message signature and structure
- Checks for duplicates (message key =
type:id:timestamp) - Stores in appropriate cache collection
- Persists to IndexedDB
- Updates last sync timestamp
- Returns whether message was new
updateCache(message)
Alias for applyMessage(). For backward compatibility.
clear()
Clear all in-memory cache (does not affect IndexedDB).
Signature:
clear(): void
clearAll()
Clear both in-memory cache and all IndexedDB stores.
Signature:
async clearAll(): Promise<void>
Example:
// Complete reset
await client.database.clearAll();
await client.database.open();
User Storage
storeUser(user) / loadUser() / clearUser()
Persist user authentication state.
Signatures:
async storeUser(user: User): Promise<void>
async loadUser(): Promise<User | null>
async clearUser(): Promise<void>
Example:
// Store current user
await client.database.storeUser(currentUser);
// Load on app start
const restoredUser = await client.database.loadUser();
if (restoredUser) {
console.log('Restored session:', restoredUser.displayName);
}
// Clear on logout
await client.database.clearUser();
User Expiry: Stored user expires after 24 hours. loadUser() returns null if expired.
Delegation Storage
storeDelegation(delegation) / loadDelegation() / clearDelegation()
Persist delegation information.
Signatures:
async storeDelegation(delegation: DelegationInfo): Promise<void>
async loadDelegation(): Promise<DelegationInfo | null>
async clearDelegation(): Promise<void>
Pending State
markPending(id) / clearPending(id) / isPending(id) / onPendingChange(listener)
Track pending message synchronization for optimistic UI.
Signatures:
markPending(id: string): void
clearPending(id: string): void
isPending(id: string): boolean
onPendingChange(listener: () => void): () => void
Example:
// Mark as pending when creating
const post = await createPost(...);
client.database.markPending(post.id);
// Show pending indicator
if (client.database.isPending(post.id)) {
showSyncingBadge(post.id);
}
// Listen for changes
const unsubscribe = client.database.onPendingChange(() => {
updateAllPendingIndicators();
});
// Clear when confirmed via network
client.database.clearPending(post.id);
Sync State
getSyncState() / setSyncing(isSyncing) / updateLastSync(timestamp)
Manage synchronization state.
Signatures:
getSyncState(): { lastSync: number | null; isSyncing: boolean }
setSyncing(isSyncing: boolean): void
updateLastSync(timestamp: number): void
Example:
const { lastSync, isSyncing } = client.database.getSyncState();
if (isSyncing) {
showSyncSpinner();
}
if (lastSync) {
console.log('Last synced:', new Date(lastSync));
}
Bookmarks
addBookmark(bookmark) / removeBookmark(id) / getUserBookmarks(userId)
Manage user bookmarks.
Signatures:
async addBookmark(bookmark: Bookmark): Promise<void>
async removeBookmark(bookmarkId: string): Promise<void>
async getUserBookmarks(userId: string): Promise<Bookmark[]>
async getUserBookmarksByType(userId: string, type: 'post' | 'comment'): Promise<Bookmark[]>
isBookmarked(userId: string, type: 'post' | 'comment', targetId: string): boolean
getBookmark(bookmarkId: string): Bookmark | undefined
getAllBookmarks(): Bookmark[]
Example:
// Add bookmark
await client.database.addBookmark({
id: `post:${postId}`,
type: 'post',
targetId: postId,
userId: currentUser.address,
createdAt: Date.now(),
title: post.title,
author: post.author,
cellId: post.cellId
});
// Check if bookmarked
const isBookmarked = client.database.isBookmarked(
userId,
'post',
postId
);
// Get all user bookmarks
const bookmarks = await client.database.getUserBookmarks(userId);
// Remove bookmark
await client.database.removeBookmark(`post:${postId}`);
User Identity Cache
upsertUserIdentity(address, record)
Update user identity in centralized cache.
Signature:
async upsertUserIdentity(
address: string,
record: Partial<UserIdentityCache[string]> & { lastUpdated?: number }
): Promise<void>
Example:
await client.database.upsertUserIdentity(address, {
ensName: 'alice.eth',
ensAvatar: 'https://...',
verificationStatus: 'ens-verified',
lastUpdated: Date.now()
});
UI State
storeUIState(key, value) / loadUIState(key) / clearUIState(key)
Persist arbitrary UI state to IndexedDB.
Signatures:
async storeUIState(key: string, value: unknown): Promise<void>
async loadUIState(key: string): Promise<unknown>
async clearUIState(key: string): Promise<void>
Example:
// Store theme preference
await client.database.storeUIState('theme', 'dark');
// Load on app start
const theme = await client.database.loadUIState('theme');
// Clear
await client.database.clearUIState('theme');
ForumActions
High-level actions for content creation, voting, and moderation.
Content Creation
createCell(params, updateCallback)
Create a new cell. Requires ENS-verified wallet.
Signature:
async createCell(
params: {
name: string;
description: string;
icon?: string;
currentUser: User | null;
isAuthenticated: boolean;
},
updateCallback: () => void
): Promise<{ success: boolean; data?: Cell; error?: string }>
Parameters:
params.name- Cell name (required)params.description- Cell description (required)params.icon- Optional emoji/icon for cellparams.currentUser- Current user objectparams.isAuthenticated- Whether user is authenticatedupdateCallback- Function called when cache is updated (for UI refresh)
Returns: Result object with success status, created cell, or error message
Permissions: Only ENS-verified users can create cells
Example:
const result = await client.forumActions.createCell(
{
name: 'Tech Discussion',
description: 'A place for tech enthusiasts',
icon: '💻',
currentUser,
isAuthenticated: true
},
() => {
// Refresh UI
renderCells();
}
);
if (result.success) {
console.log('Cell created:', result.data);
} else {
console.error('Error:', result.error);
}
createPost(params, updateCallback)
Create a new post in a cell.
Signature:
async createPost(
params: {
cellId: string;
title: string;
content: string;
currentUser: User | null;
isAuthenticated: boolean;
},
updateCallback: () => void
): Promise<{ success: boolean; data?: Post; error?: string }>
Permissions: Wallet-connected or anonymous users
Example:
const result = await client.forumActions.createPost(
{
cellId: 'cell-id',
title: 'My First Post',
content: 'Hello, OpChan!',
currentUser,
isAuthenticated: true
},
() => renderPosts()
);
createComment(params, updateCallback)
Add a comment to a post.
Signature:
async createComment(
params: {
postId: string;
content: string;
currentUser: User | null;
isAuthenticated: boolean;
},
updateCallback: () => void
): Promise<{ success: boolean; data?: Comment; error?: string }>
Permissions: Wallet-connected or anonymous users
Example:
const result = await client.forumActions.createComment(
{
postId: 'post-id',
content: 'Great post!',
currentUser,
isAuthenticated: true
},
() => renderComments()
);
Voting
vote(params, updateCallback)
Vote on a post or comment.
Signature:
async vote(
params: {
targetId: string;
isUpvote: boolean;
currentUser: User | null;
isAuthenticated: boolean;
},
updateCallback: () => void
): Promise<{ success: boolean; data?: boolean; error?: string }>
Permissions: Wallet-connected or anonymous users
Example:
// Upvote
await client.forumActions.vote(
{
targetId: postId,
isUpvote: true,
currentUser,
isAuthenticated: true
},
() => updateVoteCount()
);
// Downvote
await client.forumActions.vote(
{
targetId: commentId,
isUpvote: false,
currentUser,
isAuthenticated: true
},
() => updateVoteCount()
);
Moderation
moderatePost(params, updateCallback)
Moderate a post (hide it).
Signature:
async moderatePost(
params: {
cellId: string;
postId: string;
reason?: string;
currentUser: User | null;
isAuthenticated: boolean;
cellOwner: string;
},
updateCallback: () => void
): Promise<{ success: boolean; data?: boolean; error?: string }>
Permissions: Cell owner only
Similar Methods:
unmoderatePost()- Remove moderation from postmoderateComment()- Moderate a commentunmoderateComment()- Remove moderation from commentmoderateUser()- Moderate user in a cellunmoderateUser()- Remove user moderation
Example:
const cell = client.database.cache.cells[cellId];
if (currentUser.address === cell.author) {
await client.forumActions.moderatePost(
{
cellId,
postId,
reason: 'Spam',
currentUser,
isAuthenticated: true,
cellOwner: cell.author
},
() => renderPosts()
);
}
UserIdentityService
Manages user identity resolution, ENS lookup, and profile management.
Methods
getIdentity(address, opts?)
Get user identity with ENS resolution and caching.
Signature:
async getIdentity(
address: string,
opts?: { fresh?: boolean }
): Promise<UserIdentity | null>
Parameters:
address- Wallet address or session IDopts.fresh- Iftrue, bypass cache and resolve fresh
Returns:
interface UserIdentity {
address: `0x${string}`;
ensName?: string;
ensAvatar?: string;
callSign?: string;
displayPreference: EDisplayPreference;
displayName: string;
lastUpdated: number;
verificationStatus: EVerificationStatus;
}
Example:
// Cached lookup (fast)
const identity = await client.userIdentityService.getIdentity(address);
// Fresh lookup (bypasses cache)
const freshIdentity = await client.userIdentityService.getIdentity(
address,
{ fresh: true }
);
if (identity) {
console.log('Display name:', identity.displayName);
console.log('ENS name:', identity.ensName);
console.log('Call sign:', identity.callSign);
console.log('Verification:', identity.verificationStatus);
}
Caching Strategy:
- Checks LocalDatabase cache first
- If not found or stale, resolves from ENS
- Stores result in cache
- Returns identity
setPublicClient(publicClient)
Set viem PublicClient for ENS resolution.
Signature:
setPublicClient(publicClient: PublicClient): void
Example:
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';
const publicClient = createPublicClient({
chain: mainnet,
transport: http()
});
client.userIdentityService.setPublicClient(publicClient);
updateProfile(address, updates)
Update user profile (call sign and display preference).
Signature:
async updateProfile(
address: string,
updates: {
callSign?: string;
displayPreference?: EDisplayPreference;
}
): Promise<{ ok: true; identity: UserIdentity } | { ok: false; error: Error }>
Example:
const result = await client.userIdentityService.updateProfile(
userAddress,
{
callSign: 'alice',
displayPreference: EDisplayPreference.CALL_SIGN
}
);
if (result.ok) {
console.log('Profile updated:', result.identity);
} else {
console.error('Failed:', result.error);
}
Process:
- Creates USER_PROFILE_UPDATE message
- Signs with delegated key
- Broadcasts to network
- Updates LocalDatabase
- Returns updated identity
getDisplayName(params)
Get display name for a user based on their preferences.
Signature:
getDisplayName({
address: string,
ensName?: string | null,
displayPreference?: EDisplayPreference
}): string
Example:
const displayName = client.userIdentityService.getDisplayName({
address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
ensName: 'alice.eth',
displayPreference: EDisplayPreference.CALL_SIGN
});
// If user has call sign and preference is CALL_SIGN: "alice"
// If user has ENS: "alice.eth"
// Otherwise: "0x742d...0bEb"
subscribe(listener)
Subscribe to identity changes.
Signature:
subscribe(
listener: (address: string, identity: UserIdentity | null) => void
): () => void
Returns: Unsubscribe function
Example:
const unsubscribe = client.userIdentityService.subscribe(
(address, identity) => {
console.log('Identity updated:', address);
if (identity) {
updateUserDisplay(address, identity.displayName);
}
}
);
// Clean up
unsubscribe();
getAll()
Get all cached user identities.
Signature:
getAll(): UserIdentity[]
refreshIdentity(address)
Force refresh of a user's identity.
Signature:
async refreshIdentity(address: string): Promise<void>
RelevanceCalculator
Calculates content relevance scores based on multiple factors.
Method
calculatePostScore(post, votes, comments, userVerificationStatus, moderatedPosts)
Calculate relevance score for a post.
Signature:
calculatePostScore(
post: PostMessage,
votes: VoteMessage[],
comments: CommentMessage[],
userVerificationStatus: UserVerificationStatus,
moderatedPosts: { [postId: string]: ModerateMessage }
): RelevanceScoreDetails
Parameters:
post- Post message to scorevotes- All votes for this postcomments- All comments on this postuserVerificationStatus- Verification status of all users (for bonuses)moderatedPosts- Moderation records
Returns:
interface RelevanceScoreDetails {
baseScore: number; // 100
engagementScore: number; // upvotes*10 + comments*3
authorVerificationBonus: number; // +20 if ENS verified
verifiedUpvoteBonus: number; // +5 per verified upvoter
verifiedCommenterBonus: number; // +10 per verified commenter
timeDecayMultiplier: number; // Exponential decay (half-life 7 days)
moderationPenalty: number; // -50% if moderated
finalScore: number; // Combined total
isVerified: boolean;
upvotes: number;
comments: number;
verifiedUpvotes: number;
verifiedCommenters: number;
daysOld: number;
isModerated: boolean;
}
Scoring Formula:
base = 100
engagement = (upvotes * 10) + (comments * 3)
verification = (author ENS ? 20 : 0) +
(verified upvoters * 5) +
(verified commenters * 10)
timeDecay = exp(-0.693 * daysOld / 7)
moderation = isModerated ? 0.5 : 1.0
finalScore = (base + engagement + verification) * timeDecay * moderation
Example:
const post = client.database.cache.posts['post-id'];
const votes = Object.values(client.database.cache.votes)
.filter(v => v.targetId === post.id);
const comments = Object.values(client.database.cache.comments)
.filter(c => c.postId === post.id);
const userVerificationStatus = {};
for (const [addr, identity] of Object.entries(client.database.cache.userIdentities)) {
userVerificationStatus[addr] = {
isVerified: identity.verificationStatus === 'ens-verified',
hasENS: !!identity.ensName,
ensName: identity.ensName
};
}
const score = client.relevance.calculatePostScore(
post,
votes,
comments,
userVerificationStatus,
client.database.cache.moderations
);
console.log('Final score:', score.finalScore);
console.log('Breakdown:', {
base: score.baseScore,
engagement: score.engagementScore,
verification: score.authorVerificationBonus +
score.verifiedUpvoteBonus +
score.verifiedCommenterBonus,
timeDecay: score.timeDecayMultiplier,
moderation: score.moderationPenalty
});
MessageManager
Manages Waku network connectivity and message transmission.
Properties
isReady: boolean
Whether Waku node is ready to send/receive messages.
currentHealth: HealthStatus
Current network health status.
Methods
sendMessage(message, statusCallback?)
Send a message via Waku network.
Signature:
async sendMessage(
message: OpchanMessage,
statusCallback?: (status: MessageStatus) => void
): Promise<void>
Example:
const signed = await client.delegation.signMessage(unsignedMessage);
if (signed) {
await client.messageManager.sendMessage(signed, (status) => {
console.log('Message status:', status);
});
}
onMessageReceived(callback)
Subscribe to incoming messages.
Signature:
onMessageReceived(
callback: (message: OpchanMessage) => void
): () => void
Returns: Unsubscribe function
Example:
const unsubscribe = client.messageManager.onMessageReceived(
async (message) => {
await client.database.applyMessage(message);
console.log('Received:', message.type);
}
);
onHealthChange(callback)
Monitor network health changes.
Signature:
onHealthChange(
callback: (isHealthy: boolean) => void
): () => void
Example:
client.messageManager.onHealthChange((isHealthy) => {
if (isHealthy) {
showConnectedIndicator();
} else {
showDisconnectedIndicator();
}
});
onSyncStatus(callback)
Monitor synchronization status.
Signature:
onSyncStatus(
callback: (status: SyncStatus) => void
): () => void
BookmarkService
Service for managing user bookmarks (posts and comments).
Methods
addPostBookmark(post, userId, cellId?)
Add a post to bookmarks.
Signature:
async addPostBookmark(
post: Post,
userId: string,
cellId?: string
): Promise<Bookmark>
addCommentBookmark(comment, userId, postId?)
Add a comment to bookmarks.
Signature:
async addCommentBookmark(
comment: Comment,
userId: string,
postId?: string
): Promise<Bookmark>
removeBookmark(bookmarkId)
Remove a bookmark by ID.
Signature:
async removeBookmark(bookmarkId: string): Promise<void>
Example:
import { BookmarkService } from '@opchan/core';
const bookmarkService = new BookmarkService();
// Add post bookmark
await bookmarkService.addPostBookmark(post, userId, cellId);
// Check if bookmarked
const isBookmarked = client.database.isBookmarked(userId, 'post', postId);
// Remove bookmark
await bookmarkService.removeBookmark(`post:${postId}`);
MessageValidator
Validates message signatures and structure.
Methods
isValidMessage(message)
Check if message is valid.
Signature:
async isValidMessage(message: unknown): Promise<boolean>
getValidationReport(message)
Get detailed validation report.
Signature:
async getValidationReport(message: unknown): Promise<{
isValid: boolean;
missingFields: string[];
invalidFields: string[];
hasValidSignature: boolean;
errors: string[];
warnings: string[];
}>
Example:
import { MessageValidator } from '@opchan/core';
const validator = new MessageValidator();
const report = await validator.getValidationReport(message);
if (!report.isValid) {
console.error('Validation failed:');
console.error('Missing fields:', report.missingFields);
console.error('Invalid fields:', report.invalidFields);
console.error('Errors:', report.errors);
}
Type Definitions
Enums
EVerificationStatus
User verification levels.
enum EVerificationStatus {
ANONYMOUS = 'anonymous',
WALLET_UNCONNECTED = 'wallet-unconnected',
WALLET_CONNECTED = 'wallet-connected',
ENS_VERIFIED = 'ens-verified',
}
EDisplayPreference
User display name preference.
enum EDisplayPreference {
CALL_SIGN = 'call-sign',
WALLET_ADDRESS = 'wallet-address',
}
MessageType
Message types in the protocol.
enum MessageType {
CELL = 'cell',
POST = 'post',
COMMENT = 'comment',
VOTE = 'vote',
MODERATE = 'moderate',
USER_PROFILE_UPDATE = 'user_profile_update',
}
EModerationAction
Moderation actions.
enum EModerationAction {
MODERATE = 'moderate',
UNMODERATE = 'unmoderate',
}
Core Interfaces
User
User object representing authenticated or anonymous user.
interface User {
address: string; // 0x${string} for wallet, UUID for anonymous
ensName?: string;
ensAvatar?: string;
callSign?: string;
displayPreference: EDisplayPreference;
displayName: string;
verificationStatus: EVerificationStatus;
lastChecked?: number;
browserPubKey?: string;
delegationSignature?: string;
delegationExpiry?: number;
}
Cell
Extended cell with computed fields.
interface Cell extends CellMessage {
relevanceScore?: number;
activeMemberCount?: number;
recentActivity?: number;
postCount?: number;
relevanceDetails?: RelevanceScoreDetails;
}
Post
Extended post with votes and moderation.
interface Post extends PostMessage {
authorAddress: string;
upvotes: VoteMessage[];
downvotes: VoteMessage[];
moderated?: boolean;
moderatedBy?: string;
moderationReason?: string;
moderationTimestamp?: number;
relevanceScore?: number;
verifiedUpvotes?: number;
verifiedCommenters?: string[];
relevanceDetails?: RelevanceScoreDetails;
voteScore?: number;
}
Comment
Extended comment with votes and moderation.
interface Comment extends CommentMessage {
authorAddress: string;
upvotes: VoteMessage[];
downvotes: VoteMessage[];
moderated?: boolean;
moderatedBy?: string;
moderationReason?: string;
moderationTimestamp?: number;
relevanceScore?: number;
relevanceDetails?: RelevanceScoreDetails;
voteScore?: number;
}
Bookmark
Bookmark data structure.
interface Bookmark {
id: string; // `${type}:${targetId}`
type: BookmarkType;
targetId: string;
userId: string;
createdAt: number;
title?: string;
author?: string;
cellId?: string;
postId?: string;
}
Message Types
OpchanMessage
Union type of all signed message types.
type OpchanMessage = (
| CellMessage
| PostMessage
| CommentMessage
| VoteMessage
| ModerateMessage
| UserProfileUpdateMessage
) & SignedMessage;
SignedMessage
Signature fields present on all messages.
interface SignedMessage {
signature: string; // Ed25519 signature
browserPubKey: string; // Browser public key
delegationProof?: DelegationProof; // Optional for anonymous
}
DelegationProof
Proof that browser key was authorized by wallet.
interface DelegationProof {
authMessage: string; // Message signed by wallet
walletSignature: string; // Wallet's signature
expiryTimestamp: number; // When delegation expires
walletAddress: string; // Wallet that signed
}
Utility Functions
transformPost(postMessage)
Transform raw post message to enhanced Post type.
Signature:
async transformPost(postMessage: PostMessage): Promise<Post | null>
transformComment(commentMessage)
Transform raw comment message to enhanced Comment type.
Signature:
async transformComment(commentMessage: CommentMessage): Promise<Comment | null>
transformCell(cellMessage)
Transform raw cell message to enhanced Cell type.
Signature:
async transformCell(cellMessage: CellMessage): Promise<Cell | null>
Example:
import { transformPost, transformComment, transformCell } from '@opchan/core';
// Transform messages
const post = await transformPost(postMessage);
const comment = await transformComment(commentMessage);
const cell = await transformCell(cellMessage);
// Use enhanced types
if (post) {
console.log('Upvotes:', post.upvotes.length);
console.log('Downvotes:', post.downvotes.length);
console.log('Vote score:', post.voteScore);
console.log('Relevance:', post.relevanceScore);
}
Complete Type Reference
For complete TypeScript type definitions, see:
packages/core/src/types/forum.ts- Forum-specific typespackages/core/src/types/identity.ts- Identity and user typespackages/core/src/types/waku.ts- Message and network typespackages/core/src/lib/delegation/types.ts- Delegation types
End of API Reference