Search by

omidgfx / laravel-open-wallet

omidgfx

Database-portable wallet ledger for Laravel applications

Package info

github.com/omidgfx/laravel-open-wallet

pkg:composer/omidgfx/laravel-open-wallet

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-10-28 08:05 UTC

This package is auto-updated.

Last update: 2026-10-28 08:35:00 UTC


README

A standalone wallet ledger for Laravel applications. It provides wallet ownership, signed immutable ledger entries, balance snapshots, atomic credits/debits, and double-entry transfers. It contains no application-specific workflows or user/profile assumptions.

Requirements and database support

Requires PHP 8.2+ and Laravel 10–13. Storage uses Laravel Eloquent, the Schema builder, and transactions. The supplied migration avoids database-specific SQL, database-generated UUID functions, and cross-table foreign keys. It is designed for Laravel SQL connections such as SQLite, MySQL/MariaDB, PostgreSQL, and SQL Server, subject to the capabilities of each server and Laravel driver. MongoDB and other non-SQL stores need a storage adapter and are not claimed as supported by this SQL migration.

Money is stored as signed 64-bit integer minor units (for example, cents). Pass integers only. Debits are negative ledger rows; credits are positive. Transfers create a matching pair, each with the post-operation balance.

Install

composer require open-wallet/laravel-wallet
php artisan vendor:publish --tag=open-wallet-config
php artisan vendor:publish --tag=open-wallet-migrations
php artisan migrate

The migration can instead be loaded automatically by the provider. Publish it when you need to customize its table/column schema before migrating.

Use

use App\Models\User;
use OpenWallet\WalletManager;

$user = User::findOrFail(42);
$wallets = app(WalletManager::class);
$wallet = $wallets->createWallet($user, 'cash');
$wallets->credit($wallet, 5_000, 'deposit', metadata: ['source' => 'gateway']);
$wallets->debit($wallet, 1_200, 'purchase');
$wallets->transfer($wallet, $merchantWallet, 800, 'purchase', subject: $order);
$entries = $wallets->entries($wallet, perPage: 50);

Configure allowed wallet types in wallet_types. entry_types is optional; when non-empty, it restricts accepted entry labels. allow_negative_balance_for contains wallet type names that may go below zero. Every other type rejects overdrafts inside the transaction.

For a non-Eloquent holder, use createWallet(HolderClass::class, $holderId, 'cash'). Eloquent morph maps are respected through getMorphClass().

Configuration

config/open-wallet.php controls:

  • Database connection (connection; null uses Laravel's default connection).
  • Table names and every non-primary wallet/entry column name.
  • Allowed wallet and entry type labels.
  • Wallet types permitted to have negative balances.
  • Transaction deadlock retry count (lock_retries).
  • Morph key string size (default 64), UUID generator, and maximum page size.

Keep database column names and table names valid for the selected database. If you change the config after publishing migrations, update the migration to match before running it. The id primary keys remain conventional auto-incrementing integers.

Consistency and concurrency

Every balance mutation runs in a transaction and locks wallet rows in ascending primary-key order for transfers. Laravel/database engines differ in how they implement row locks; production correctness under concurrent writers depends on using a transactional engine that honors SELECT ... FOR UPDATE (or an equivalent supported by Laravel). SQLite is useful for development but does not provide the same row-level locking guarantees as PostgreSQL, MySQL/InnoDB, or SQL Server. Use one configured connection for both wallet tables so balance updates and ledger rows commit atomically.

The ledger is append-only by package convention. Application database credentials should prevent updates/deletes to ledger rows if tamper resistance is required. Reconcile cached balances against entry sums periodically in applications with strict accounting requirements.

API

WalletManager exposes createWallet, walletFor, credit, debit, transfer, and entries. Wallet records and ledger entries are available as OpenWallet\Models\Wallet and OpenWallet\Models\WalletEntry. Invalid amounts and overdrafts throw package exceptions under OpenWallet\Exceptions.