Skip to main content

Wallet Service Documentation

Overview

The Wallet Service is a core component of the Rahat platform that provides comprehensive wallet management capabilities for blockchain-based humanitarian aid operations. It supports both EVM-based chains (Ethereum, Base, Polygon, etc.) and Stellar chain, enabling secure wallet creation, management, and transaction handling.

Features

Multi-Chain Support

  • EVM Chains: Support for Ethereum-compatible blockchains (Ethereum, Base, Polygon, etc.)
  • Stellar Chain: Support for Stellar blockchain with Soroban smart contracts
  • Dynamic Chain Detection: Automatic detection of chain type from wallet addresses
  • Chain-Specific Configuration: Separate RPC endpoints and network settings for each chain type

Wallet Management

  • Wallet Creation: Generate new wallets for any supported chain
  • Bulk Wallet Creation: Create multiple wallets in a single operation
  • Wallet Import: Import existing wallets using private keys
  • Wallet Connection: Connect to existing wallets for transaction signing
  • Address Validation: Validate wallet addresses for supported chains

Security & Storage

  • Secure Storage: File-based storage with encryption support
  • Private Key Management: Secure handling of private keys and wallet secrets
  • Phone Number Association: Link wallet addresses to beneficiary phone numbers
  • Bulk Operations: Secure bulk wallet operations for beneficiary management

Architecture

Core Components

1. Wallet Service (WalletService)

The main service class that orchestrates wallet operations:

@Injectable()
export class WalletService implements OnModuleInit {
// Core wallet operations
async createWallet(chainType?: ChainType): Promise<WalletKeys>
async create(chains: ChainType[]): Promise<WalletCreateResult[]>
async createBulk(count: number): Promise<WalletCreateResult[]>
async importWallet(privateKey: string, chain?: ChainType): Promise<WalletKeys>
async connectWallet(address: string, chain?: ChainType): Promise<IConnectedWallet>
}

2. Blockchain Provider Registry (BlockchainProviderRegistry)

Manages wallet implementations for different blockchain types:

export class BlockchainProviderRegistry {
// Register and manage wallet managers
async initializeChain(chainType: ChainType, config?: any): Promise<void>
async createWallet(chainType: ChainType): Promise<WalletKeys>
async connectWallet(address: string, chainType: ChainType): Promise<IConnectedWallet>
validateAddress(address: string, chainType: ChainType): boolean
}

3. Wallet Implementations

  • EVMWallet: Handles Ethereum-compatible chains
  • StellarWallet: Handles Stellar blockchain operations

4. Storage Layer

  • FileWalletStorage: File-based wallet storage with encryption support
  • MemoryWalletStorage: In-memory storage for testing

Module Structure

apps/rahat/src/wallet/
├── wallet.service.ts # Main service logic
├── wallet.controller.ts # API endpoints
├── wallet.module.ts # Module configuration
├── providers/
│ └── blockchain-provider.registry.ts # Chain management
├── storages/
│ └── fs.storage.ts # File storage implementation
├── types/
│ └── chain-config.interface.ts # Configuration types
└── dto/
└── getBy.dto.ts # Data transfer objects

Configuration

Chain Settings

The wallet service uses a centralized configuration system through the Settings service:

interface ChainConfig {
chainId: string;
name: string;
type: 'evm' | 'stellar';
rpcUrl: string;
explorerUrl: string;
currency: {
name: string;
symbol: string;
};
}

Environment Variables

  • WALLET_PATH: Custom storage directory for wallet files
  • Default storage: ./wallet_storage/

Default RPC Endpoints

  • EVM: https://base-sepolia-rpc.publicnode.com
  • Stellar: https://stellar-soroban-public.nodies.app

API Endpoints

Microservice Patterns

The wallet service uses NestJS microservice patterns for internal communication:

1. Create Wallets

// Create single wallet
@MessagePattern({ cmd: WalletJobs.CREATE })
create(chains: ChainType[])

// Create bulk wallets
@MessagePattern({ cmd: WalletJobs.CREATE_BULK })
createBulk(chains: BulkCreateWallet)

// Update beneficiaries with new wallets
@MessagePattern({ cmd: WalletJobs.UPDATE_BULK })
updateBulk(chains: BulkUpdateWallet)

2. Wallet Retrieval

// Get wallet by phone number
@MessagePattern({ cmd: WalletJobs.GET_WALLET_BY_PHONE })
getWalletByPhone(phoneDto: PhoneNumberDto)

// Get wallet secret by phone
@MessagePattern({ cmd: WalletJobs.GET_SECRET_BY_PHONE })
getSecretByPhone(account: PhoneAddressDto)

// Get wallet secret by address
@MessagePattern({ cmd: WalletJobs.GET_SECRET_BY_WALLET })
getSecretByWallet(account: WalletAddressDto)

// Get bulk wallet secrets
@MessagePattern({ cmd: WalletJobs.GET_BULK_SECRET_BY_WALLET })
getBulkSecretByWallet(accounts: BulkWalletAddressDto)

Usage Examples

1. Creating a Single Wallet

// Create EVM wallet
const evmWallet = await walletService.createWallet('evm');
console.log('EVM Wallet:', evmWallet.address);

// Create Stellar wallet
const stellarWallet = await walletService.createWallet('stellar');
console.log('Stellar Wallet:', stellarWallet.address);

2. Creating Multiple Wallets

// Create wallets for multiple chains
const wallets = await walletService.create(['evm', 'stellar']);
wallets.forEach(wallet => {
console.log(`${wallet.chain} Wallet:`, wallet.address);
});

3. Bulk Wallet Creation

// Create 10 wallets for the current chain
const bulkWallets = await walletService.createBulk(10);
console.log(`Created ${bulkWallets.length} wallets`);

4. Importing Existing Wallet

// Import wallet from private key
const importedWallet = await walletService.importWallet(privateKey, 'evm');
console.log('Imported Wallet:', importedWallet.address);

5. Connecting to Existing Wallet

// Connect to existing wallet
const connectedWallet = await walletService.connectWallet(walletAddress, 'evm');

// Sign a message
const signature = await connectedWallet.signMessage('Hello World');

// Send transaction
const tx = await connectedWallet.sendTransaction(transactionData);

6. Phone Number Association

// Get wallet by phone number
const walletAddress = await walletService.getWalletByPhone('+1234567890');

// Get wallet secret by phone
const walletKeys = await walletService.getSecretByPhone('+1234567890', 'evm');

7. Address Validation

// Validate EVM address
const isValidEVM = await walletService.validateAddress('0x1234...', 'evm');

// Validate Stellar address
const isValidStellar = await walletService.validateAddress('GABC...', 'stellar');

Data Types

Wallet Keys

interface WalletKeys {
address: string;
privateKey: string;
publicKey?: string;
blockchain: string;
mnemonic?: string;
}

Connected Wallet

interface IConnectedWallet {
signMessage(message: string): Promise<string>;
sendTransaction(rawTransaction: any): Promise<any>;
getWalletKeys(): WalletKeys;
}

Bulk Operations

type BulkCreateWallet = {
chain?: ChainType;
count: number;
};

type BulkUpdateWallet = {
chain: ChainType;
benUuids: string[];
};

Security Considerations

Private Key Storage

  • Private keys are stored in encrypted files
  • File-based storage with configurable directory
  • Support for custom storage implementations

Chain Isolation

  • Each chain type has separate storage
  • Chain-specific validation and configuration
  • Isolated wallet management per chain

Access Control

  • Microservice-based access patterns
  • Internal service communication only
  • No direct external API exposure

Error Handling

The wallet service includes comprehensive error handling:

// Chain not supported
if (!this.providerRegistry.getSupportedChains().includes(chainType)) {
throw new Error(`Chain ${chainType} not supported in this instance`);
}

// Configuration missing
if (!settings || !settings.value) {
throw new Error('CHAIN_SETTINGS configuration not found');
}

// Invalid chain type
if (!validChainTypes.includes(rawValue.type as ChainType)) {
throw new Error(`Invalid chain type "${rawValue.type}"`);
}

Future Enhancements

Multi-Chain Support

The service is designed for future multi-chain support:

// TODO: Multi-chain support - Future enhancement to support multiple chains per instance
// Currently: One instance = One chain type
// Future: One instance = Multiple chain types with dynamic selection

Planned Features

  • Dynamic Chain Selection: Support multiple chains simultaneously
  • Enhanced Storage: Database-backed storage options
  • Advanced Encryption: Hardware security module integration
  • Transaction Batching: Optimized bulk transaction processing

Integration

With Beneficiary Service

The wallet service integrates with the beneficiary management system:

// Update beneficiaries with new wallets
async updateBulk(bulkUpdateWalletDto: BulkUpdateWallet) {
return Promise.all(bulkUpdateWalletDto.benUuids.map(async (uuid) => {
const walletAddress = await this.create([bulkUpdateWalletDto.chain]);
const beneficiary = await this.prisma.beneficiary.update({
where: { uuid },
data: { walletAddress: walletAddress[0].address },
});
return { uuid, walletAddress: beneficiary.walletAddress, secret: walletAddress[0].privateKey };
}));
}

With Settings Service

Chain configuration is managed through the settings service:

private async getCurrentChainSettings(): Promise<{
detectedChain: ChainType;
stellar: any;
evm: any;
}> {
const settings = await this.settings.getByName('CHAIN_SETTINGS');
// ... configuration processing
}

Testing

The wallet service includes comprehensive test coverage:

  • Unit Tests: wallet.service.spec.ts
  • Controller Tests: wallet.controller.spec.ts
  • Integration Tests: End-to-end wallet operations

Monitoring

The service includes logging for monitoring and debugging:

private readonly logger = new Logger(WalletService.name);

this.logger.log(`Creating ${chain} wallet`);
this.logger.warn(`Chain ${chainType} not supported in this instance`);
this.logger.error('Error reading wallet file:', error);

Conclusion

The Wallet Service provides a robust, secure, and scalable foundation for blockchain wallet management in the Rahat platform. Its support for both EVM and Stellar chains, combined with comprehensive security features and flexible configuration options, makes it suitable for humanitarian aid operations requiring reliable wallet infrastructure.