Skip to main content

id: token-system-package

Token System Package

Overview

The Token System Package provides a comprehensive solution for implementing a centralized token system within NestJS applications. It offers flexible storage options with Redis for high-performance real-time operations and PostgreSQL for durability and complex queries. The package is designed to support small to medium businesses with up to 1 million users, providing a reliable and non-restrictive way to implement tokenomics and incorporate it as a default payment solution.

Status

  • Planning
  • Implementation
  • Testing
  • Documentation
  • Release

Components

Core Module

  • Token interfaces and types
  • Configuration interfaces
  • Error types and handling
  • Validation schemas
  • Module registration

Redis Implementation

  • Token information management
  • Balance operations
  • Transfer functionality
  • Burn operations
  • Supply tracking
  • Event publishing
  • Leaderboard functionality

PostgreSQL Implementation

  • Entity definitions
  • Repository implementations
  • Transaction history
  • Balance tracking
  • Audit logging
  • Reporting capabilities

Facade Services

  • Token service
  • Balance service
  • Transaction service
  • Formatter service
  • Analytics service

Synchronization

  • Redis to PostgreSQL sync
  • Consistency verification
  • Reconciliation tools
  • Error recovery

Integration

  • NestJS module integration
  • Configuration options
  • Health checks
  • Monitoring hooks

Technical Implementation

Architecture

The package follows a modular architecture with clear separation of concerns:

  1. Core Layer: Defines interfaces, DTOs, and types that are storage-agnostic
  2. Storage Layer: Implements storage-specific logic (Redis and PostgreSQL)
  3. Service Layer: Provides high-level services that coordinate between storage implementations
  4. Integration Layer: Handles module registration and configuration
┌─────────────────────────────────────────────────────────┐
│ Application │
└───────────────────────────┬─────────────────────────────┘

┌───────────────────────────▼─────────────────────────────┐
│ Token Module │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Facade Services │ │
│ │ │ │
│ │ TokenService, BalanceService, etc. │ │
│ └───────────┬─────────────────────────┬───────────┘ │
│ │ │ │
│ ┌───────────▼───────────┐ ┌─────────▼───────────┐ │
│ │ Redis Services │ │ PostgreSQL Services │ │
│ │ │ │ │ │
│ │ TokenRedisService │ │ TokenPostgresService │ │
│ │ BalanceRedisService │ │ BalancePostgresService │
│ └───────────┬───────────┘ └─────────┬───────────┘ │
│ │ │ │
│ ┌───────────▼───────────┐ ┌─────────▼───────────┐ │
│ │ Redis Client │ │ TypeORM / Entities │ │
│ └───────────────────────┘ └───────────────────────┘ │
└─────────────────────────────────────────────────────────┘

Storage Models

Redis Data Model

  1. Token Information

    • Key: token:info
    • Type: Hash
    • Fields: name, symbol, emoji, decimals, initSupply
  2. User Balances

    • Key Pattern: balance:{userId}
    • Type: String (numeric value)
  3. Transaction Log

    • Key: transactions
    • Type: Stream
    • Fields: from, to, amount, timestamp, type
  4. Leaderboard

    • Key: balances:zset
    • Type: Sorted Set
    • Members: userIds with balances as scores

PostgreSQL Data Model

  1. Token Entity

    @Entity('token')
    export class TokenEntity {
    @PrimaryColumn()
    symbol: string;

    @Column()
    name: string;

    @Column()
    emoji: string;

    @Column()
    decimals: number;

    @Column('numeric', { precision: 36, scale: 0 })
    initSupply: string;

    @Column('numeric', { precision: 36, scale: 0 })
    circulatingSupply: string;
    }
  2. Balance Entity

    @Entity('balances')
    export class BalanceEntity {
    @PrimaryColumn()
    userId: string;

    @Column('numeric', { precision: 36, scale: 0 })
    balance: string;

    @Column()
    lastUpdated: Date;
    }
  3. Transaction Entity

    @Entity('transactions')
    export class TransactionEntity {
    @PrimaryGeneratedColumn('uuid')
    id: string;

    @Column()
    fromUserId: string;

    @Column()
    toUserId: string;

    @Column('numeric', { precision: 36, scale: 0 })
    amount: string;

    @Column()
    type: 'transfer' | 'burn' | 'mint';

    @Column()
    timestamp: Date;

    @Column({ nullable: true })
    metadata: string;
    }

Core Interfaces

export interface TokenInfo {
name: string;
symbol: string;
emoji: string;
decimals: number;
initSupply: string;
}

export interface ITokenService {
initializeToken(): Promise<void>;
getTokenInfo(): Promise<TokenInfo>;
getBalance(userId: string): Promise<number>;
transfer(fromUserId: string, toUserId: string, amount: number): Promise<void>;
burn(userId: string, amount: number): Promise<void>;
getTotalSupply(): Promise<number>;
getCirculatingSupply(): Promise<number>;
getTopHolders(
limit: number,
): Promise<Array<{ userId: string; balance: number }>>;
}

export interface IBalanceService {
getBalance(userId: string): Promise<number>;
getFormattedBalance(userId: string, options?: FormatOptions): Promise<string>;
getBalanceInUsd(userId: string): Promise<number>;
subscribeToBalanceUpdates(userId: string, callback: BalanceCallback): void;
unsubscribeFromBalanceUpdates(userId: string): void;
}

export interface ITransactionService {
recordTransaction(transaction: TransactionDto): Promise<string>;
getTransactionHistory(
userId: string,
options?: PaginationOptions,
): Promise<Transaction[]>;
getTransactionById(id: string): Promise<Transaction | null>;
}

Module Configuration

export interface TokenModuleOptions {
// Storage mode configuration
mode?: 'redis-only' | 'postgres-only' | 'hybrid';

// Redis configuration
redis?: {
url?: string;
host?: string;
port?: number;
password?: string;
db?: number;
keyPrefix?: string;
};

// PostgreSQL configuration
postgres?: {
entities?: any[];
synchronize?: boolean;
autoLoadEntities?: boolean;
};

// Token configuration
token?: {
name: string;
symbol: string;
emoji: string;
decimals: number;
initialSupply: number;
};

// Feature flags
features?: {
enableLeaderboard?: boolean;
enableNotifications?: boolean;
enableAuditLog?: boolean;
enableSynchronization?: boolean;
};
}

Implementation Strategy

The package will be implemented in phases:

  1. Phase 1: Redis Implementation

    • Extract existing Redis implementation from Arcana
    • Define core interfaces and types
    • Implement Redis-specific services
    • Create module registration
  2. Phase 2: PostgreSQL Implementation

    • Define PostgreSQL entities
    • Implement repository pattern
    • Create PostgreSQL-specific services
    • Add transaction history
  3. Phase 3: Hybrid Mode

    • Implement facade services
    • Add synchronization logic
    • Ensure consistency between storages
    • Add reconciliation tools
  4. Phase 4: Advanced Features

    • Analytics capabilities
    • Reporting tools
    • Monitoring integration
    • Performance optimizations

Configuration

Module Registration

// In app.module.ts
import { Module } from '@nestjs/common';
import { TokenModule } from '@your-org/token';

@Module({
imports: [
TokenModule.register({
mode: 'redis-only', // or 'postgres-only', 'hybrid'
redis: {
url: 'redis://localhost:6379',
},
token: {
name: 'Tarot Token',
symbol: 'TARO',
emoji: '🔮',
decimals: 6,
initialSupply: 100_000_000,
},
features: {
enableLeaderboard: true,
enableNotifications: true,
},
}),
],
})
export class AppModule {}

Environment Variables

The module will support configuration through environment variables:

TOKEN_STORAGE_MODE=hybrid
REDIS_URL=redis://localhost:6379
TOKEN_NAME=Tarot Token
TOKEN_SYMBOL=TARO
TOKEN_EMOJI=🔮
TOKEN_DECIMALS=6
TOKEN_INITIAL_SUPPLY=100000000

Development Guidelines

Error Handling

  • All storage operations should have proper error handling
  • Errors should be categorized (e.g., InsufficientBalanceError, StorageError)
  • Facade services should handle errors from both storage implementations

Validation

  • All input parameters should be validated
  • Use Zod for runtime validation
  • Provide clear error messages for validation failures

Testing

  • Unit tests for each service
  • Integration tests for storage implementations
  • End-to-end tests for complete flows
  • Performance tests for critical operations

Documentation

  • API documentation with examples
  • Configuration options documentation
  • Migration guides
  • Performance considerations

Security Measures

Access Control

  • Services should not handle authentication/authorization
  • Applications should implement access control
  • Provide hooks for integrating with guards

Data Protection

  • Sensitive operations should be logged
  • Transaction history should be immutable
  • Balance changes should be auditable

Monitoring & Analytics

Health Checks

  • Redis connection health
  • PostgreSQL connection health
  • Synchronization status

Metrics

  • Transaction volume
  • Balance distribution
  • Operation latency
  • Error rates

Logging

  • Operation logging
  • Error logging
  • Audit logging for sensitive operations

Migration Path

For existing applications using the Redis-only implementation:

  1. Replace direct imports with package imports
  2. Keep 'redis-only' mode initially
  3. Add PostgreSQL configuration
  4. Enable hybrid mode
  5. Monitor for consistency issues
  6. Optionally switch to 'postgres-only' mode

Future Enhancements

  • Blockchain integration for public verification
  • Multi-token support
  • Exchange rate integration
  • Advanced tokenomics features (staking, vesting)
  • Performance optimizations for larger user bases