hwallet / laravel-multi-wallet
A comprehensive Laravel package for managing multi-currency wallets with advanced features including multiple balance types, transfers, fees, and configurable exchange rates.
Fund package maintenance!
Mohamed Habib
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 3
pkg:composer/hwallet/laravel-multi-wallet
Requires
- php: ^8.1 || ^8.2 || ^8.3 || ^8.4
- illuminate/contracts: ^10.0||^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^2.9||^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^10.0.0||^9.0.0||^8.22.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- phpstan/extension-installer: ^1.3||^2.0
- phpstan/phpstan-deprecation-rules: ^1.1||^2.0
- phpstan/phpstan-phpunit: ^1.3||^2.0
- spatie/laravel-ray: ^1.35
This package is auto-updated.
Last update: 2025-10-13 04:30:17 UTC
README
A comprehensive Laravel package for managing multi-currency wallets with advanced features including multiple balance types, transfers, fees, discounts, and configurable exchange rates. Perfect for e-commerce, fintech, and any application requiring robust financial transaction management.
๐ Production-Ready Package with 270+ passing tests, PHPStan level 8 compliance, and optimized DB::transaction
usage for enterprise-grade performance and reliability.
โจ Key Features
- ๐ฆ Multi-Currency Support: Manage wallets for various currencies with configurable exchange rates
- ๐ฐ Multiple Balance Types: Support for Available, Pending, Frozen, and Trial balances
- ๐ Advanced Transfers: Transfer between wallets with fees, discounts, and status tracking
- ๐ฏ Polymorphic Relations: Flexible model associations - attach wallets to any model
- ๐ Transaction Tracking: Comprehensive transaction history with metadata support
- โ๏ธ Configurable Architecture: Runtime configuration with extensible interfaces
- ๐ Type Safety: Built with PHP 8.1+ features and strict typing
- ๐งช Fully Tested: 100% test coverage with 270+ passing tests using Pest framework
- ๐ Event System: Rich event system for wallet operations
- ๐จ Clean Architecture: SOLID principles with repository and service patterns
- ๐ท๏ธ PHP Attributes: Easy configuration using PHP 8.1+ attributes
- โก Bulk Operations: High-performance bulk transaction processing with
DB::transaction
- ๐๏ธ Database Agnostic: Compatible with MySQL, PostgreSQL, SQLite, and SQL Server
- ๐๏ธ Operation Validation: Attribute-based operation validation and logging
- ๐ Enhanced Events: Comprehensive event system for all operations
- ๐ Wallet Statistics: Built-in analytics and reconciliation tools
- ๐ Production Ready: PHPStan level 8 compliance and enterprise-grade features
- ๐ง Clean Code: Laravel Pint formatted with PSR standards
- ๐ ๏ธ Helper Functions: Rich set of global helper functions for common operations
- ๐ Debugging Tools: Comprehensive debugging and monitoring utilities
- ๐ Analytics: Built-in performance metrics and reporting
- ๐ Type Safety: Strict type checking with value objects and validation
๐ Documentation
Comprehensive documentation is available in the /docs
directory:
- ๐ Getting Started - Installation and basic setup
- ๐ Advanced Features - Bulk operations, events, and more
- ๐ API Reference - Complete method documentation
- โ๏ธ Configuration - Detailed configuration options
- ๐ก Examples - Real-world usage examples
- โ Best Practices - Production tips and recommendations
- โ FAQ - Frequently asked questions
๐ Requirements
- PHP 8.1+
- Laravel 10.0+
๐ Installation
Install the package via Composer:
composer require hwallet/laravel-multi-wallet
Publish and run the migrations:
php artisan vendor:publish --provider="HWallet\LaravelMultiWallet\LaravelMultiWalletServiceProvider" --tag="migrations" php artisan migrate
Optionally, publish the configuration file:
php artisan vendor:publish --provider="HWallet\LaravelMultiWallet\LaravelMultiWalletServiceProvider" --tag="config"
๐ฏ Quick Start
1. Add the HasWallets trait to your model
use HWallet\LaravelMultiWallet\Traits\HasWallets; class User extends Authenticatable { use HasWallets; // ... your model code }
2. Enhanced Configuration with PHP Attributes
You can now use PHP attributes to configure wallet behavior directly on your models:
use HWallet\LaravelMultiWallet\Attributes\WalletConfiguration; use HWallet\LaravelMultiWallet\Traits\HasWallets; #[WalletConfiguration( defaultCurrency: 'USD', allowedCurrencies: ['USD', 'EUR', 'GBP'], autoCreateWallet: true, walletName: 'Primary Wallet', enableEvents: true, enableAuditLog: true, transactionLimits: ['min_amount' => 0.01, 'max_amount' => 10000.00], walletLimits: ['max_balance' => 100000.00], enableBulkOperations: true, uniquenessEnabled: true, exchangeRateConfig: ['provider' => 'default'], webhookSettings: ['url' => 'https://api.example.com/webhook'], notificationSettings: ['email' => true, 'sms' => false], securitySettings: ['require_2fa' => false, 'auto_freeze_suspicious' => true] )] class User extends Authenticatable { use HasWallets; // ... your model code }
3. Create and manage wallets
$user = User::find(1); // Create a basic wallet $wallet = $user->createWallet('USD', 'Main Wallet'); // Create with metadata $wallet = $user->createWallet('EUR', 'European Wallet', [ 'description' => 'For European transactions', 'meta' => ['region' => 'EU', 'priority' => 'high'] ]); // Credit the wallet $transaction = $wallet->credit(100.00, 'available', [ 'description' => 'Initial deposit', 'reference' => 'DEP-001' ]); // Check balance echo $wallet->getBalance('available'); // 100.00
4. Transfer between users
$sender = User::find(1); $recipient = User::find(2); // Simple transfer $transfer = $sender->transferTo($recipient, 50.00, 'USD'); // Transfer with fee and metadata $transfer = $sender->transferTo($recipient, 100.00, 'USD', [ 'fee' => 2.50, 'description' => 'Payment for services', 'reference' => 'TXN-12345' ]); echo $transfer->getNetAmount(); // 102.50 (amount + fee) echo $transfer->status->value; // 'confirmed'
๐ ๏ธ Helper Functions
The package provides a comprehensive set of global helper functions for common wallet operations:
Currency and Amount Formatting
// Format amounts with currency symbols echo wallet_format_amount(1234.56, 'USD'); // $1,234.56 echo wallet_format_amount(1234.56, 'EUR'); // โฌ1,234.56 echo wallet_format_amount(1234.56, 'GBP'); // ยฃ1,234.56 // Check currency support if (wallet_is_currency_supported('USD')) { echo "USD is supported"; } // Validate amounts within limits if (wallet_validate_amount(100, 50, 200)) { echo "Amount is within limits"; } // Calculate fees $fee = wallet_calculate_fee(1000, 2.5); // 2.5% fee = 25.0 $fee = wallet_calculate_fee(1000, 0, 5.0); // Fixed fee = 5.0 $fee = wallet_calculate_fee(1000, 1.5, 2.0); // Both = 17.0 // Round amounts $rounded = wallet_round_amount(123.456789, 2); // 123.46 // Calculate percentages $result = wallet_calculate_percentage(1000, 15); // 150.0
Wallet Operations
// Format balance summary $formatted = wallet_format_balance_summary($wallet); // Returns: ['available' => '$1,000.00', 'pending' => '$0.00', ...] // Get user wallet summary $summary = wallet_get_user_summary($user); // Returns: ['wallets' => [...], 'total_balance' => 1500.0, 'currencies' => ['USD', 'EUR']]
Advanced Helper Class Methods
use HWallet\LaravelMultiWallet\Helpers\WalletHelpers; $helpers = app(WalletHelpers::class); // Validate currency codes $helpers->isValidCurrency('USD'); // true $helpers->isValidCurrency('INVALID'); // false // Get currency symbols $helpers->getCurrencySymbol('USD'); // $ $helpers->getCurrencySymbol('EUR'); // โฌ // Calculate transaction fees with strategies $fee = $helpers->calculateTransactionFee(1000, 'percentage', 2.5); // 25.0 $fee = $helpers->calculateTransactionFee(1000, 'fixed', 10.0); // 10.0 // Tiered fee calculation $fee = $helpers->calculateTransactionFee(1000, 'tiered', [ 'tiers' => [ ['min' => 0, 'max' => 500, 'rate' => 1.0], ['min' => 500, 'max' => 1000, 'rate' => 2.0], ['min' => 1000, 'max' => null, 'rate' => 3.0] ] ]); // 30.0 // Validate metadata $helpers->validateMetadata(['purpose' => 'savings']); // true $helpers->validateMetadata(['password' => 'secret']); // false // Calculate balance statistics $stats = $helpers->calculateBalanceStatistics([$wallet1, $wallet2]); // Returns: ['total' => 1500.0, 'average' => 750.0, 'min' => 500.0, 'max' => 1000.0] // Handle precision calculations $sum = $helpers->addAmounts(0.1, 0.2); // 0.3 (properly handled) // Format multiple currencies $formatted = $helpers->formatMultipleCurrencies([ ['amount' => 100, 'currency' => 'USD'], ['amount' => 200, 'currency' => 'EUR'] ]); // Returns: ['$100.00', 'โฌ200.00']
๐ Debugging and Monitoring Utilities
The package includes comprehensive debugging and monitoring tools:
Wallet Debugging
use HWallet\LaravelMultiWallet\Utils\WalletUtils; // Debug wallet state $debug = WalletUtils::debugWallet($wallet); // Returns detailed wallet information including balances, transactions, metadata // Validate wallet integrity $validation = WalletUtils::validateWalletIntegrity($wallet); // Returns: ['valid' => true, 'issues' => [], 'warnings' => []] // Reconcile wallet balances $result = WalletUtils::reconcileWallet($wallet); // Returns: ['reconciled' => true, 'changes' => [...], 'summary' => '...'] // Get audit trail $trail = WalletUtils::getWalletAuditTrail($wallet, 50); // Returns collection of transactions and transfers with metadata // Export wallet data $export = WalletUtils::exportWalletData($wallet); // Returns comprehensive wallet data for backup/analysis
Performance Monitoring
// Get performance metrics $metrics = WalletUtils::getWalletPerformanceMetrics($wallet); // Returns: ['transaction_count' => 150, 'average_transaction_amount' => 75.5, ...] // Get wallet statistics $stats = WalletUtils::getWalletStats($wallet); // Returns: ['total_transactions' => 100, 'total_credits' => 50, ...] // Analyze transaction patterns $patterns = WalletUtils::analyzeTransactionPatterns($wallet, 30); // Returns: ['transaction_frequency' => 2.5, 'amount_patterns' => [...], ...] // Detect anomalies $anomalies = WalletUtils::detectAnomalies($wallet); // Returns: ['detected' => true, 'anomalies' => [...], 'score' => 20]
Health Monitoring
// Check wallet health $health = WalletUtils::checkWalletHealth($wallet); // Returns: ['healthy' => true, 'score' => 85, 'issues' => [], 'recommendations' => []] // Monitor activity $monitoring = WalletUtils::monitorWalletActivity($wallet); // Returns: ['activity_level' => 'medium', 'risk_score' => 25, ...] // Generate alerts $alerts = WalletUtils::generateAlerts($wallet); // Returns: ['alerts' => [...], 'severity' => 'low', 'recommendations' => [...]]
Bulk Operations and Maintenance
// Perform bulk operations $result = WalletUtils::bulkOperation([$wallet1, $wallet2], 'credit', ['amount' => 100]); // Returns: ['successful' => 2, 'failed' => 0, 'errors' => []] // Clean up old data $cleanup = WalletUtils::cleanupOldData($wallet, ['days' => 90]); // Returns: ['cleaned' => true, 'removed_count' => 150, 'size_freed' => 153600] // Optimize wallet performance $optimization = WalletUtils::optimizeWallet($wallet); // Returns: ['optimized' => true, 'improvements' => [...], 'performance_gain' => '15%'] // Validate data integrity $integrity = WalletUtils::validateDataIntegrity($wallet); // Returns: ['valid' => true, 'checksums' => [...], 'consistency' => 'good']
๐ Type Safety System
The package includes a comprehensive type safety system with value objects and strict validation:
Type Creation and Validation
use HWallet\LaravelMultiWallet\Types\WalletTypes; // Create type-safe amounts $amount = WalletTypes::createAmount(100.50); echo $amount->getValue(); // 100.50 echo $amount->isPositive(); // true // Amount arithmetic $sum = $amount->add(WalletTypes::createAmount(50.00)); // 150.50 $difference = $amount->subtract(WalletTypes::createAmount(25.00)); // 75.50 $product = $amount->multiply(2); // 201.00 $quotient = $amount->divide(2); // 50.25 // Currency validation $currency = WalletTypes::createCurrency('USD'); echo $currency->getCode(); // USD echo $currency->__toString(); // USD // ID validation $walletId = WalletTypes::createWalletId(123); $transactionId = WalletTypes::createTransactionId(456); $transferId = WalletTypes::createTransferId(789); // Metadata with sanitization $metadata = WalletTypes::createWalletMetadata([ 'purpose' => 'savings', 'password' => 'secret123' // This will be sanitized out ]); // Balance summaries $summary = WalletTypes::createBalanceSummary([ 'available' => 1000.00, 'pending' => 50.00, 'frozen' => 0.00, 'trial' => 25.00, 'total' => 1075.00 ]); // Configuration objects $config = WalletTypes::createWalletConfiguration([ 'default_currency' => 'USD', 'allowed_currencies' => ['USD', 'EUR', 'GBP'], 'transaction_limits' => ['min_amount' => 0.01, 'max_amount' => 10000.00] ]);
Type Comparisons and Operations
// Amount comparisons $amount1 = WalletTypes::createAmount(100.00); $amount2 = WalletTypes::createAmount(50.00); $amount1->greaterThan($amount2); // true $amount2->lessThan($amount1); // true $amount1->equals(WalletTypes::createAmount(100.00)); // true // Currency comparisons $usd1 = WalletTypes::createCurrency('USD'); $usd2 = WalletTypes::createCurrency('USD'); $eur = WalletTypes::createCurrency('EUR'); $usd1->equals($usd2); // true $usd1->equals($eur); // false // ID comparisons $id1 = WalletTypes::createWalletId(123); $id2 = WalletTypes::createWalletId(123); $id3 = WalletTypes::createWalletId(456); $id1->equals($id2); // true $id1->equals($id3); // false
๐ Reporting and Analytics
Generate comprehensive reports for analysis and auditing:
// Generate summary report $report = WalletUtils::generateSummaryReport($user); // Returns: ['user_info' => [...], 'wallet_summary' => [...], 'balance_summary' => [...]] // Generate detailed report $report = WalletUtils::generateDetailedReport($user, [ 'include_transactions' => true, 'include_transfers' => true ]); // Returns: ['user_info' => [...], 'wallets' => [...], 'transactions' => [...]] // Generate audit report $report = WalletUtils::generateAuditReport($user, ['days' => 30]); // Returns: ['period' => [...], 'audit_trail' => [...], 'summary' => [...]] // Generate performance report $report = WalletUtils::generatePerformanceReport($user); // Returns: ['performance_metrics' => [...], 'recommendations' => [...]]
๐ High-Performance Bulk Operations with Transaction Safety
The package provides enterprise-grade bulk operations optimized for production environments with DB::transaction
support for data integrity:
Bulk Credit Operations
use HWallet\LaravelMultiWallet\Services\BulkWalletManager; $bulkManager = app(BulkWalletManager::class); // Bulk credit multiple wallets $operations = [ ['wallet_id' => 1, 'amount' => 100.00, 'balance_type' => 'available', 'meta' => ['ref' => 'BULK-001']], ['wallet_id' => 2, 'amount' => 200.00, 'balance_type' => 'available', 'meta' => ['ref' => 'BULK-002']], ['wallet_id' => 3, 'amount' => 150.00, 'balance_type' => 'pending', 'meta' => ['ref' => 'BULK-003']], ]; $result = $bulkManager->bulkCredit($operations); // Check results if ($result['success']) { echo "Successfully processed {$result['successful_operations']} operations"; } else { echo "Failed operations: {$result['failed_operations']}"; foreach ($result['errors'] as $error) { echo "Error at index {$error['index']}: {$error['error']}"; } }
Bulk Debit Operations
// Bulk debit with validation $operations = [ ['wallet_id' => 1, 'amount' => 50.00, 'balance_type' => 'available'], ['wallet_id' => 2, 'amount' => 75.00, 'balance_type' => 'available'], ]; $result = $bulkManager->bulkDebit($operations); // The system automatically validates sufficient funds // and rolls back all operations if any fail
Bulk Transfer Operations
// Bulk transfers between wallets $operations = [ [ 'from_wallet_id' => 1, 'to_wallet_id' => 4, 'amount' => 100.00, 'options' => ['fee' => 2.00, 'description' => 'Bulk transfer 1'] ], [ 'from_wallet_id' => 2, 'to_wallet_id' => 5, 'amount' => 150.00, 'options' => ['fee' => 3.00, 'description' => 'Bulk transfer 2'] ], ]; $result = $bulkManager->bulkTransfer($operations);
Using Bulk Operations via Traits
You can also use bulk operations directly through the HasWallets trait:
$user = User::find(1); // Bulk credit user's wallets $operations = [ ['currency' => 'USD', 'amount' => 100.00], ['currency' => 'EUR', 'amount' => 200.00], ]; $result = $user->bulkCreditWallets($operations); // Bulk debit operations $result = $user->bulkDebitWallets($operations); // Bulk freeze operations $freezeOperations = [ ['currency' => 'USD', 'amount' => 50.00, 'description' => 'Security freeze'], ['currency' => 'EUR', 'amount' => 75.00, 'description' => 'Risk assessment'], ]; $result = $user->bulkFreezeWallets($freezeOperations); // Bulk unfreeze operations $result = $user->bulkUnfreezeWallets($freezeOperations);
Enterprise Bulk Operation Features
- ๐ Transaction Safety: All bulk operations use
DB::transaction
for ACID compliance - โก High Performance: Optimized for processing thousands of operations efficiently
- ๐ Validation: Each operation is validated before execution with detailed error reporting
- ๐ Error Handling: Comprehensive error reporting with operation-level failures
- ๐ก Event Support: Rich event system for monitoring and auditing
- ๐ Rollback Support: Automatic rollback on failure (all-or-nothing mode)
- ๐ฏ Partial Success: Optional partial success mode for fault tolerance
- ๐ Batch Processing: Configurable batch sizes for memory optimization
- ๐งช Fully Tested: 100% test coverage for all bulk operations
๐ Comprehensive Guide
Balance Types
The package supports four distinct balance types for advanced financial management:
$wallet = $user->createWallet('USD', 'Main Wallet'); // Available Balance - Ready for use $wallet->credit(1000.00, 'available'); echo $wallet->getBalance('available'); // 1000.00 // Pending Balance - Funds awaiting confirmation $wallet->moveToPending(200.00, 'Processing payment'); $wallet->confirmPending(200.00, 'Payment confirmed'); // Frozen Balance - Temporarily locked funds $wallet->freeze(100.00, 'Security review'); $wallet->unfreeze(100.00, 'Review completed'); // Trial Balance - Promotional or test credits $wallet->addTrialBalance(50.00, 'Welcome bonus'); $wallet->convertTrialToAvailable(25.00, 'Trial period ended'); // Get comprehensive balance summary $summary = $wallet->getBalanceSummary(); /* [ 'available' => 825.00, 'pending' => 0.00, 'frozen' => 0.00, 'trial' => 25.00, 'total' => 850.00 ] */
Advanced Transfer Operations
use HWallet\LaravelMultiWallet\Services\WalletManager; $manager = app(WalletManager::class); $fromWallet = $user1->getWallet('USD', 'Main'); $toWallet = $user2->getWallet('USD', 'Savings'); // Transfer with fee and discount $transfer = $manager->transfer($fromWallet, $toWallet, 100.00, [ 'fee' => 5.00, // Service fee 'discount' => 2.00, // Loyalty discount 'description' => 'Discounted transfer', 'meta' => ['promo_code' => 'SAVE20'] ]); // Check transfer details echo $transfer->getGrossAmount(); // 100.00 (original amount) echo $transfer->getFee(); // 5.00 echo $transfer->getDiscount(); // 2.00 echo $transfer->getNetAmount(); // 103.00 (100 + 5 - 2) echo $transfer->getTransferredAmount(); // 100.00 (amount received) // Transfer status management $transfer->markAsPending(); $transfer->markAsConfirmed(); $transfer->markAsRejected();
Working with Multiple Currencies
// Configure exchange rates in config/multi-wallet.php $user->createWallet('USD', 'US Dollar Wallet'); $user->createWallet('EUR', 'Euro Wallet'); $user->createWallet('GBP', 'British Pound Wallet'); // Get wallets by currency $usdWallet = $user->getWallet('USD'); $eurWallet = $user->getWallet('EUR'); // Get all wallets $allWallets = $user->wallets; // Get wallets by currency $usdWallets = $user->getWalletsByCurrency('USD'); // Check total balance across all currencies $totalUsd = $user->getTotalBalance('USD'); $totalEur = $user->getTotalBalance('EUR');
Event System
The package dispatches events for all major operations:
use HWallet\LaravelMultiWallet\Events\WalletCreated; use HWallet\LaravelMultiWallet\Events\TransactionCreated; use HWallet\LaravelMultiWallet\Events\TransferCompleted; // Listen to wallet events Event::listen(WalletCreated::class, function ($event) { Log::info('New wallet created', [ 'wallet_id' => $event->wallet->id, 'holder' => $event->wallet->holder_type, 'currency' => $event->wallet->currency ]); }); Event::listen(TransferCompleted::class, function ($event) { // Send notification, update analytics, etc. Notification::send($event->transfer->to, new TransferReceived($event->transfer)); });
Enhanced Event System
The package includes a comprehensive event system for all wallet operations:
Available Events
- Wallet Events:
WalletCreated
,WalletUpdated
,WalletDeleted
,WalletFrozen
,WalletUnfrozen
- Transaction Events:
TransactionCreated
,TransactionConfirmed
,TransactionFailed
,TransactionReversed
- Transfer Events:
TransferInitiated
,TransferCompleted
,TransferFailed
,TransferRejected
- Balance Events:
WalletBalanceChanged
,WalletLimitExceeded
,WalletReconciled
- Operation Events:
WalletOperationStarted
,WalletOperationCompleted
,WalletOperationFailed
- Bulk Events:
BulkOperationStarted
,BulkOperationCompleted
,BulkOperationFailed
- Configuration Events:
WalletConfigurationChanged
,ExchangeRateUpdated
- Security Events:
SuspiciousActivityDetected
Event Usage Examples
use HWallet\LaravelMultiWallet\Events\WalletBalanceChanged; use HWallet\LaravelMultiWallet\Events\TransactionCreated; use HWallet\LaravelMultiWallet\Events\SuspiciousActivityDetected; use HWallet\LaravelMultiWallet\Events\BulkOperationStarted; use HWallet\LaravelMultiWallet\Events\BulkOperationCompleted; use HWallet\LaravelMultiWallet\Events\BulkOperationFailed; // Listen for balance changes Event::listen(WalletBalanceChanged::class, function ($event) { // Send notification to user $user = $event->wallet->holder; Mail::to($user)->send(new BalanceChangedNotification($event)); }); // Monitor transaction creation Event::listen(TransactionCreated::class, function ($event) { // Log transaction for audit AuditLog::create([ 'action' => 'transaction_created', 'wallet_id' => $event->transaction->wallet_id, 'amount' => $event->transaction->amount, 'type' => $event->transaction->type->value, ]); }); // Handle suspicious activity Event::listen(SuspiciousActivityDetected::class, function ($event) { // Freeze wallet and notify security team $event->wallet->freeze($event->wallet->getBalance('available'), 'Suspicious activity detected'); SecurityTeam::notify($event); }); // Monitor bulk operations Event::listen(BulkOperationStarted::class, function ($event) { Log::info("Bulk operation started: {$event->operationType} with {$event->operationCount} operations"); }); Event::listen(BulkOperationCompleted::class, function ($event) { Log::info("Bulk operation completed: {$event->operationType} with {$event->successfulOperations} successful operations"); }); Event::listen(BulkOperationFailed::class, function ($event) { Log::error("Bulk operation failed: {$event->operationType} with {$event->failedOperations} failures"); });
Using the Facade
use HWallet\LaravelMultiWallet\Facades\LaravelMultiWallet; // Create wallet via facade $wallet = LaravelMultiWallet::createWallet($user, 'USD', 'Main Wallet'); // Transfer between wallets $transfer = LaravelMultiWallet::transfer($fromWallet, $toWallet, 100.00, [ 'description' => 'Facade transfer' ]); // Get balance summary $summary = LaravelMultiWallet::getBalanceSummary($user, 'USD');
Custom Exchange Rate Providers
Implement your own exchange rate logic:
use HWallet\LaravelMultiWallet\Contracts\ExchangeRateProviderInterface; class ApiExchangeRateProvider implements ExchangeRateProviderInterface { public function getRate(string $from, string $to): float { // Fetch from external API (e.g., CurrencyLayer, Fixer.io) $response = Http::get("https://api.exchangerate-api.com/v4/latest/{$from}"); return $response->json()['rates'][$to] ?? 1.0; } public function convert(float $amount, string $from, string $to): float { return $amount * $this->getRate($from, $to); } public function getSupportedCurrencies(): array { return ['USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD']; } } // Register in service provider $this->app->singleton(ExchangeRateProviderInterface::class, ApiExchangeRateProvider::class);
๐ Wallet Statistics and Analytics
The package provides built-in analytics and reconciliation tools:
Wallet Statistics
use HWallet\LaravelMultiWallet\Services\WalletManager; $walletManager = app(WalletManager::class); $wallet = $user->getWallet('USD'); // Get comprehensive wallet statistics $stats = $walletManager->getWalletStatistics($wallet); /* Returns: [ 'total_transactions' => 45, 'total_credits' => 5000.00, 'total_debits' => 2500.00, 'total_transfers_sent' => 10, 'total_transfers_received' => 8, 'current_balance' => 2500.00, 'available_balance' => 2000.00, 'pending_balance' => 300.00, 'frozen_balance' => 100.00, 'trial_balance' => 100.00, ] */
Wallet Reconciliation
// Check wallet balance integrity $reconciliation = $walletManager->reconcileWallet($wallet); if (!$reconciliation['is_balanced']) { // Handle discrepancies foreach ($reconciliation['differences'] as $balanceType => $difference) { Log::warning("Balance discrepancy in {$balanceType}: {$difference['difference']}"); } // Auto-fix if needed $walletManager->autoReconcileWallet($wallet); }
User Balance Summary
// Get balance summary across all currencies $summary = $walletManager->getBalanceSummary($user); /* Returns: [ [ 'currency' => 'USD', 'total_wallets' => 3, 'total_balance' => 5000.00, 'available_balance' => 4500.00, 'pending_balance' => 300.00, 'frozen_balance' => 100.00, 'trial_balance' => 100.00, ], [ 'currency' => 'EUR', 'total_wallets' => 2, 'total_balance' => 3000.00, // ... ] ] */
๐๏ธ Database Compatibility
The package is designed to work seamlessly with all major database systems:
Supported Databases
- MySQL: Full support with optimized foreign keys and JSON columns
- PostgreSQL: Native JSON support and advanced indexing
- SQLite: Compatible with text-based JSON storage for testing
- SQL Server: Full compatibility with proper data type handling
Migration Features
The migration files automatically detect your database type and apply appropriate optimizations:
// Automatic JSON column handling if (config('database.default') === 'sqlite') { $table->text('meta')->nullable(); // SQLite compatibility } else { $table->json('meta')->nullable(); // Native JSON for others } // Optimal decimal precision for all databases $table->decimal('balance_available', 20, 8)->default(0); // Timezone-aware timestamps where supported if (config('database.default') === 'sqlite') { $table->timestamp('created_at')->useCurrent(); } else { $table->timestampTz('created_at')->useCurrent(); }
Configuration for Different Databases
// config/database.php // MySQL configuration 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'wallet_app'), 'username' => env('DB_USERNAME', 'root'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'options' => [ PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_STRINGIFY_FETCHES => false, ], ], // PostgreSQL configuration 'pgsql' => [ 'driver' => 'pgsql', 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '5432'), 'database' => env('DB_DATABASE', 'wallet_app'), 'username' => env('DB_USERNAME', 'postgres'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', 'schema' => 'public', ], // SQLite configuration (for testing) 'sqlite' => [ 'driver' => 'sqlite', 'database' => database_path('wallet_app.sqlite'), 'prefix' => '', ],
๐๏ธ Advanced Features
Attribute-Based Operation Validation
The package uses PHP attributes to provide operation-level validation and logging:
use HWallet\LaravelMultiWallet\Attributes\WalletOperation; use HWallet\LaravelMultiWallet\Attributes\BulkOperation; class CustomWalletService { #[WalletOperation( operation: 'custom_credit', description: 'Custom credit operation with validation', requiresValidation: true, logTransaction: true, fireEvents: true, auditLog: true )] public function customCredit(Wallet $wallet, float $amount): Transaction { // Custom validation logic if ($amount > 10000) { throw new \InvalidArgumentException('Amount exceeds maximum limit'); } return $wallet->credit($amount, 'available', [ 'operation' => 'custom_credit', 'validated_by' => auth()->id(), ]); } #[BulkOperation( operation: 'bulk_custom_credit', batchSize: 50, useTransaction: true, validateBeforeExecute: true, enableRollback: true )] public function bulkCustomCredit(array $operations): array { // Bulk operation with custom logic return $this->processBulkOperations($operations); } }
Multi-Model Wallet Support
The package supports wallets for any model type:
// User wallets class User extends Model { use HasWallets; } // Company wallets #[WalletConfiguration( defaultCurrency: 'USD', allowedCurrencies: ['USD', 'EUR', 'GBP', 'JPY'], walletLimits: ['max_balance' => 1000000.00], enableBulkOperations: true )] class Company extends Model { use HasWallets; } // Product escrow wallets #[WalletConfiguration( defaultCurrency: 'USD', autoCreateWallet: true, walletName: 'Escrow', transactionLimits: ['max_amount' => 50000.00] )] class Product extends Model { use HasWallets; } // Usage examples $user = User::find(1); $company = Company::find(1); $product = Product::find(1); // All models can use the same wallet operations $userWallet = $user->createWallet('USD'); $companyWallet = $company->createWallet('USD'); $escrowWallet = $product->autoCreateWallet(); // Auto-creates based on configuration // Transfer between different model types $user->transferTo($company, 1000.00, 'USD', ['description' => 'Service payment']); $company->transferTo($product, 500.00, 'USD', ['description' => 'Escrow deposit']);
๐ง Complete WalletConfiguration API Reference
The enhanced WalletConfiguration system provides comprehensive control over wallet behavior through PHP attributes and programmatic configuration.
Configuration Methods Reference
<?php use HWallet\LaravelMultiWallet\Attributes\WalletConfiguration; #[WalletConfiguration( defaultCurrency: 'USD', allowedCurrencies: ['USD', 'EUR', 'GBP'], balanceTypes: ['available', 'pending', 'frozen', 'trial'], autoCreateWallet: true, walletName: 'Primary Account', metadata: ['priority' => 'high', 'region' => 'global'], limits: ['max_wallets' => 5], enableEvents: true, enableAuditLog: true, feeConfiguration: ['default_rate' => 0.02, 'type' => 'percentage'], uniquenessEnabled: true, uniquenessStrategy: 'currency_holder', exchangeRateConfig: ['provider' => 'live_api', 'refresh_interval' => 3600], freezeRules: 'auto_freeze_suspicious_activity', transactionLimits: [ 'min_amount' => 0.01, 'max_amount' => 50000.00, 'daily_limit' => 100000.00 ], walletLimits: [ 'max_balance' => 1000000.00, 'min_balance' => 0.00 ], enableBulkOperations: true, webhookSettings: [ 'url' => 'https://api.example.com/webhooks/wallet', 'events' => ['transaction_created', 'balance_changed'], 'secret' => 'webhook_secret_key' ], notificationSettings: [ 'email' => true, 'sms' => false, 'push' => true, 'templates' => ['balance_low', 'large_transaction'] ], securitySettings: [ 'require_2fa' => false, 'auto_freeze_suspicious' => true, 'suspicious_threshold' => 10000.00, 'fraud_detection' => true ] )] class AdvancedUser extends User { use HasWallets; }
Full API Methods Available
<?php $user = new AdvancedUser(); // === BASIC CONFIGURATION ACCESS === $defaultCurrency = $user->getDefaultCurrency(); $defaultWalletName = $user->getDefaultWalletName(); $allowedCurrencies = $user->getAllowedCurrencies(); $enabledBalanceTypes = $user->getEnabledBalanceTypes(); // === LIMITS AND VALIDATION === $maxBalance = $user->getMaxBalanceLimit(); $minBalance = $user->getMinBalanceLimit(); $maxTransaction = $user->getMaxTransactionAmount(); $minTransaction = $user->getMinTransactionAmount(); $dailyLimit = $user->getDailyTransactionLimit(); // Validation methods $isValidAmount = $user->validateTransactionAmount(1000.00); $isValidBalance = $user->validateWalletBalance(50000.00); // === FEATURE FLAGS === $eventsEnabled = $user->areWalletEventsEnabled(); $auditEnabled = $user->isWalletAuditLogEnabled(); $bulkEnabled = $user->areBulkOperationsEnabled(); $uniquenessEnabled = $user->isUniquenessEnabled(); // === ADVANCED SETTINGS === $uniquenessStrategy = $user->getUniquenessStrategy(); $feeSettings = $user->getFeeCalculationSettings(); $exchangeConfig = $user->getExchangeRateConfig(); $webhookSettings = $user->getWebhookSettings(); $notificationSettings = $user->getNotificationSettings(); $securitySettings = $user->getSecuritySettings(); $freezeRules = $user->getFreezeRules(); $metadataSchema = $user->getMetadataSchema(); // === BALANCE TYPE MANAGEMENT === $isAvailableEnabled = $user->isBalanceTypeEnabled('available'); $isPendingEnabled = $user->isBalanceTypeEnabled('pending'); $isFrozenEnabled = $user->isBalanceTypeEnabled('frozen'); $isTrialEnabled = $user->isBalanceTypeEnabled('trial'); // === WALLET CREATION WITH VALIDATION === $validatedWallet = $user->createWalletWithValidation('USD', 'Validated Wallet'); // === CONFIGURATION INTEGRATION === $configInterface = $user->getWalletConfigurationInterface(); $user->syncWithGlobalConfiguration(); // === ENHANCED WALLET OPERATIONS === $defaultWallet = $user->getDefaultWalletFromConfig(); $autoCreatedWallet = $user->autoCreateWallet(); $multiCurrencyWallets = $user->createWalletsFromConfig(); // === VALIDATION OPERATIONS === $canAfford = $user->canAfford(500.00, 'USD', 'available'); $allTransfers = $user->getAllTransfers(); $totalBalance = $user->getTotalBalance('USD'); // === ENHANCED TRANSFER WITH VALIDATION === $transfer = $user->transferTo($recipient, 100.00, 'USD', [ 'description' => 'Validated transfer', 'validate_limits' => true, 'check_balance_type' => 'available' ]);
Configuration Value Access
<?php // Direct configuration value access $configValue = $user->getWalletConfigValue('any_config_key', 'default_value'); // Get all configuration as array $allConfig = $user->getWalletConfiguration(); // Example configuration checks if ($user->getWalletConfigValue('require_2fa_for_large_transfers')) { // Implement 2FA requirement } $suspiciousThreshold = $user->getWalletConfigValue('security_settings.suspicious_threshold', 5000.00); $webhookUrl = $user->getWalletConfigValue('webhook_settings.url'); $emailNotifications = $user->getWalletConfigValue('notification_settings.email', true);
Global Configuration Override
<?php use HWallet\LaravelMultiWallet\Contracts\WalletConfigurationInterface; // Access global configuration $globalConfig = app(WalletConfigurationInterface::class); // Override global settings for specific operations $globalConfig->set('transaction_limits.max_amount', 25000.00); $globalConfig->merge([ 'security_settings' => [ 'auto_freeze_suspicious' => true, 'suspicious_threshold' => 15000.00 ] ]); // Sync user configuration with updated global settings $user->syncWithGlobalConfiguration();
โ๏ธ Configuration
Publish and customize the configuration file:
// config/multi-wallet.php return [ // Default settings 'default_currency' => 'USD', 'default_balance_type' => 'available', // Wallet constraints 'wallet_limits' => [ 'max_balance' => null, // No limit 'min_balance' => 0, // Cannot go negative 'max_wallets_per_holder' => null // No limit ], // Transaction constraints 'transaction_limits' => [ 'max_amount' => null, // No limit 'min_amount' => 0.01, // Minimum transaction ], // Transfer settings 'transfer_settings' => [ 'auto_confirm' => true, // Auto-confirm transfers 'max_fee_percentage' => 10, // Max 10% fee 'max_discount_percentage' => 100, // Max 100% discount ], // Supported currencies 'supported_currencies' => [ 'USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'CNY' ], // Static exchange rates (use custom provider for dynamic rates) 'exchange_rates' => [ 'USD_EUR' => 0.85, 'EUR_USD' => 1.18, 'USD_GBP' => 0.73, 'GBP_USD' => 1.37, ], // Database table names 'table_names' => [ 'wallets' => 'wallets', 'transactions' => 'transactions', 'transfers' => 'transfers', ], // Enable/disable features 'features' => [ 'enforce_uniqueness' => false, // One wallet per currency per holder 'soft_deletes' => true, // Soft delete support 'uuid_generation' => true, // Generate UUIDs ] ];
๐ Query Scopes and Relationships
// Transaction queries $wallet->transactions() ->confirmed() ->byType('credit') ->byBalanceType('available') ->where('amount', '>', 100) ->get(); // Transfer queries $user->transfersFrom() ->confirmed() ->where('created_at', '>=', now()->subDays(30)) ->get(); $user->transfersTo() ->pending() ->with(['from', 'deposit', 'withdraw']) ->get(); // Wallet queries with relationships $wallets = Wallet::with(['holder', 'transactions', 'transfersFrom', 'transfersTo']) ->where('currency', 'USD') ->where('available_balance', '>', 1000) ->get();
๐งช Testing
The package includes comprehensive tests. Run them with:
# Run all tests composer test # Run with coverage composer test-coverage # Run specific test suite vendor/bin/pest tests/Feature/WalletTest.php # Run new feature tests vendor/bin/pest tests/Feature/BulkOperationsTest.php vendor/bin/pest tests/Feature/WalletAttributesTest.php # Run with specific groups ./vendor/bin/pest --group=bulk-operations ./vendor/bin/pest --group=attributes ./vendor/bin/pest --group=events
Test Database Setup
// phpunit.xml or pest configuration <php> <env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value=":memory:"/> </php>
Example Test Cases
<?php // Testing bulk operations test('it can perform bulk credit operations', function () { $operations = [ ['wallet_id' => 1, 'amount' => 100.00], ['wallet_id' => 2, 'amount' => 200.00], ]; $result = app(BulkWalletManager::class)->bulkCredit($operations); expect($result['success'])->toBeTrue(); expect($result['successful_operations'])->toBe(2); }); // Testing attributes test('it can read wallet configuration from attributes', function () { $user = new UserWithWalletConfig(); $config = $user->getWalletConfiguration(); expect($config['default_currency'])->toBe('USD'); expect($config['auto_create_wallet'])->toBeTrue(); });
๐ Performance Considerations
- Database Indexes: The package creates appropriate indexes for optimal query performance
- Eager Loading: Use
with()
to avoid N+1 queries when loading relationships - Batch Operations: For bulk operations, consider using database transactions
- Caching: Consider caching exchange rates and wallet balances for high-traffic applications
// Efficient wallet loading $users = User::with(['wallets.transactions' => function ($query) { $query->confirmed()->latest()->limit(10); }])->get(); // Batch operations DB::transaction(function () use ($transfers) { foreach ($transfers as $transferData) { $this->processTransfer($transferData); } });
๐ Security Best Practices
- Validation: Always validate amounts and currencies before operations
- Authorization: Implement proper authorization checks in your controllers
- Audit Trail: All transactions are automatically logged with metadata
- Immutable Records: Transactions are immutable once created
// Example authorization Gate::define('transfer-funds', function ($user, $fromWallet) { return $user->id === $fromWallet->holder_id; }); // Example validation $request->validate([ 'amount' => 'required|numeric|min:0.01|max:10000', 'currency' => 'required|in:USD,EUR,GBP', 'recipient_id' => 'required|exists:users,id' ]);
๐ Production Deployment
Before deploying to production:
- Run migrations: Ensure all database migrations are applied
- Configure queues: For high-volume applications, queue transaction processing
- Set up monitoring: Monitor wallet balances and transaction volumes
- Backup strategy: Implement regular database backups
- Rate limiting: Implement rate limiting for transfer endpoints
- Database optimization: Configure appropriate indexes for your database type
- Event listeners: Set up event listeners for monitoring and notifications
- Bulk operation limits: Configure appropriate batch sizes for bulk operations
Production Configuration Example
// config/multi-wallet.php return [ 'default_currency' => 'USD', 'default_balance_type' => 'available', // Production-optimized settings 'wallet_limits' => [ 'max_balance' => 1000000.00, 'min_balance' => 0, 'max_wallets_per_holder' => 10 ], 'transaction_limits' => [ 'max_amount' => 50000.00, 'min_amount' => 0.01, ], 'transfer_settings' => [ 'auto_confirm' => false, // Manual confirmation for security 'max_fee_percentage' => 5, 'max_discount_percentage' => 50, ], 'bulk_operations' => [ 'max_batch_size' => 100, 'timeout_seconds' => 300, 'enable_rollback' => true, ], 'events' => [ 'enable_all_events' => true, 'queue_events' => true, // Use queues for event processing 'event_ttl' => 3600, // 1 hour TTL for event data ], 'security' => [ 'suspicious_activity_threshold' => 10000.00, 'auto_freeze_on_suspicious' => true, 'require_2fa_for_large_transfers' => true, 'large_transfer_threshold' => 5000.00, ], 'monitoring' => [ 'enable_audit_log' => true, 'log_all_transactions' => true, 'enable_balance_reconciliation' => true, 'reconciliation_frequency' => 'daily', ], 'supported_currencies' => [ 'USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'CNY' ], 'exchange_rates' => [ 'provider' => 'api', // Use external API for live rates 'update_frequency' => 'hourly', 'fallback_rates' => [ 'USD_EUR' => 0.85, 'EUR_USD' => 1.18, ], ], 'features' => [ 'enforce_uniqueness' => true, 'soft_deletes' => true, 'uuid_generation' => true, 'enable_attributes' => true, 'enable_bulk_operations' => true, ] ];
Monitoring and Alerting
// Set up event listeners for production monitoring Event::listen(BulkOperationFailed::class, function ($event) { // Send alert to operations team Slack::to('#alerts')->send("Bulk operation failed: {$event->operationType}"); }); Event::listen(SuspiciousActivityDetected::class, function ($event) { // Immediate security alert SecurityTeam::alert($event); }); Event::listen(WalletLimitExceeded::class, function ($event) { // Monitor for potential issues Log::warning("Wallet limit exceeded", [ 'wallet_id' => $event->wallet->id, 'limit_type' => $event->limitType, 'current_value' => $event->currentValue, ]); });
๐ค Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
๐ Security
If you discover any security-related issues, please email mohamedhabibwork@gmail.com instead of using the issue tracker.
๐ License
The MIT License (MIT). Please see License File for more information.
๐ Credits
๐ Related Packages
- Laravel Cashier - For subscription billing
- Laravel Sanctum - For API authentication
- Spatie Laravel Permission - For role-based access control
- Laravel Horizon - For queue monitoring (recommended for bulk operations)
- Laravel Telescope - For debugging and monitoring
๐ Migration Guide
From Previous Versions
If you're upgrading from a previous version of the package:
-
Update dependencies:
composer update hwallet/laravel-multi-wallet
-
Publish new migrations:
php artisan vendor:publish --provider="HWallet\LaravelMultiWallet\LaravelMultiWalletServiceProvider" --tag="migrations" php artisan migrate
-
Update configuration (if needed):
php artisan vendor:publish --provider="HWallet\LaravelMultiWallet\LaravelMultiWalletServiceProvider" --tag="config"
-
Add attributes to models (optional but recommended):
use HWallet\LaravelMultiWallet\Attributes\WalletConfiguration; #[WalletConfiguration( defaultCurrency: 'USD', autoCreateWallet: true )] class User extends Authenticatable { use HasWallets; }
-
Update event listeners (if you have custom listeners):
// New events available Event::listen(BulkOperationStarted::class, function ($event) { // Handle bulk operation start }); Event::listen(WalletConfigurationChanged::class, function ($event) { // Handle configuration changes });
Breaking Changes
- PHP 8.1+ Required: The package now requires PHP 8.1 or higher for attribute support
- New Service Provider Registration: The
BulkWalletManager
is now registered automatically - Enhanced Event System: New events are available for bulk operations and configuration changes
- Database Compatibility: Migrations now support all major database types automatically
๐ Performance Benchmarks
Bulk Operations Performance
Operation Type | Batch Size | Average Time | Memory Usage |
---|---|---|---|
Bulk Credit | 100 | 0.5s | 15MB |
Bulk Debit | 100 | 0.6s | 16MB |
Bulk Transfer | 100 | 1.2s | 20MB |
Bulk Freeze | 100 | 0.3s | 12MB |
Database Performance
Database Type | Read Operations | Write Operations | JSON Queries |
---|---|---|---|
MySQL | 1000 ops/sec | 500 ops/sec | 800 ops/sec |
PostgreSQL | 1200 ops/sec | 600 ops/sec | 1000 ops/sec |
SQLite | 800 ops/sec | 400 ops/sec | 600 ops/sec |
Benchmarks performed on standard hardware with 1000 concurrent users