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:
- Core Layer: Defines interfaces, DTOs, and types that are storage-agnostic
- Storage Layer: Implements storage-specific logic (Redis and PostgreSQL)
- Service Layer: Provides high-level services that coordinate between storage implementations
- 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
-
Token Information
- Key:
token:info - Type: Hash
- Fields: name, symbol, emoji, decimals, initSupply
- Key:
-
User Balances
- Key Pattern:
balance:{userId} - Type: String (numeric value)
- Key Pattern:
-
Transaction Log
- Key:
transactions - Type: Stream
- Fields: from, to, amount, timestamp, type
- Key:
-
Leaderboard
- Key:
balances:zset - Type: Sorted Set
- Members: userIds with balances as scores
- Key:
PostgreSQL Data Model
-
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;
} -
Balance Entity
@Entity('balances')
export class BalanceEntity {
@PrimaryColumn()
userId: string;
@Column('numeric', { precision: 36, scale: 0 })
balance: string;
@Column()
lastUpdated: Date;
} -
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:
-
Phase 1: Redis Implementation
- Extract existing Redis implementation from Arcana
- Define core interfaces and types
- Implement Redis-specific services
- Create module registration
-
Phase 2: PostgreSQL Implementation
- Define PostgreSQL entities
- Implement repository pattern
- Create PostgreSQL-specific services
- Add transaction history
-
Phase 3: Hybrid Mode
- Implement facade services
- Add synchronization logic
- Ensure consistency between storages
- Add reconciliation tools
-
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:
- Replace direct imports with package imports
- Keep 'redis-only' mode initially
- Add PostgreSQL configuration
- Enable hybrid mode
- Monitor for consistency issues
- 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