PHPackages                             byjg/wallets - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. byjg/wallets

ActiveLibrary

byjg/wallets
============

A robust PHP library for managing digital wallets and financial transactions with full audit trails, transaction chain integrity, and support for reserved funds.

6.0.0(5mo ago)24MITPHPPHP &gt;=8.3 &lt;8.6CI passing

Since Sep 7Pushed 2mo agoCompare

[ Source](https://github.com/byjg/php-wallets)[ Packagist](https://packagist.org/packages/byjg/wallets)[ GitHub Sponsors](https://github.com/byjg)[ RSS](/packages/byjg-wallets/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (4)Versions (5)Used By (0)

   sidebar\_key wallets   tags    php

 finance

    Wallets
=======

[](#wallets)

A robust PHP library for managing digital wallets and financial transactions with full audit trails, transaction chain integrity, and support for reserved funds.

[![Sponsor](https://camo.githubusercontent.com/fab14b7f7f475072ada0473f193d6f322561fd4a2958e0cc89910d053347cf27/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53706f6e736f722d2532336561346161613f6c6f676f3d67697468756273706f6e736f7273266c6f676f436f6c6f723d7768697465266c6162656c436f6c6f723d306431313137)](https://github.com/sponsors/byjg)[![Build Status](https://github.com/byjg/php-wallets/actions/workflows/phpunit.yml/badge.svg?branch=master)](https://github.com/byjg/php-wallets/actions/workflows/phpunit.yml)[![Opensource ByJG](https://camo.githubusercontent.com/425c1bbccc0f292bf4d20569ae74a6b2e384fd648f1af8911bc61de9a8dcfc0b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6f70656e736f757263652d62796a672d737563636573732e737667)](http://opensource.byjg.com)[![GitHub source](https://camo.githubusercontent.com/88e61eb211719144efdd570290a0456b6e13099c2df8d973f1bb43fe33bf0039/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4769746875622d736f757263652d696e666f726d6174696f6e616c3f6c6f676f3d676974687562)](https://github.com/byjg/php-wallets/)[![GitHub license](https://camo.githubusercontent.com/580bb4d5a3e45df54b7650dc681d7591b7d0697985b5819af43ba93ab709fec0/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f62796a672f7068702d77616c6c6574732e737667)](https://opensource.byjg.com/opensource/licensing.html)[![GitHub release](https://camo.githubusercontent.com/34e093b4b8147c0054af65689cf4e04be4d071a0a8f32840d3473bea343794b5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f62796a672f7068702d77616c6c6574732e737667)](https://github.com/byjg/php-wallets/releases/)

Features
--------

[](#features)

- **Multiple wallets per user** - Each user can have multiple wallets for different currencies
- **Multiple currencies** - Support for any currency type (fiat, crypto, points, etc.)
- **Reserved funds** - Pre-authorize and block funds for pending transactions
- **Transaction chain integrity** - Immutable transaction history with UUID linking and checksums
- **Atomic operations** - All balance updates are atomic and transactional
- **Flexible scale** - Support for different decimal places (cents, satoshis, whole units)
- **Overdraft support** - Optional negative balances with configurable minimum values
- **Audit trail** - Complete transaction history with balance snapshots
- **Idempotent operations** - UUID-based transaction deduplication
- **Extensible** - Easily extend wallets and transactions with custom fields

Installation
------------

[](#installation)

```
composer require byjg/wallets
```

Quick Start
-----------

[](#quick-start)

```
use ByJG\Wallets\Service\WalletService;
use ByJG\Wallets\Service\WalletTypeService;
use ByJG\Wallets\Service\TransactionService;
use ByJG\Wallets\Entity\WalletTypeEntity;
use ByJG\Wallets\Repository\WalletRepository;
use ByJG\Wallets\Repository\WalletTypeRepository;
use ByJG\Wallets\Repository\TransactionRepository;
use ByJG\Wallets\DTO\TransactionDTO;
use ByJG\AnyDataset\Db\Factory;

// Initialize database connection
$dbDriver = Factory::getDbInstance('mysql://user:pass@localhost/dbname');

// Initialize repositories
$walletTypeRepo = new WalletTypeRepository($dbDriver);
$transactionRepo = new TransactionRepository($dbDriver);
$walletRepo = new WalletRepository($dbDriver);

// Initialize services
$walletTypeService = new WalletTypeService($walletTypeRepo);
$transactionService = new TransactionService($transactionRepo, $walletRepo);
$walletService = new WalletService($walletRepo, $walletTypeService, $transactionService);

// Create a wallet type
$walletType = new WalletTypeEntity();
$walletType->setWalletTypeId('USD');
$walletType->setName('US Dollar');
$walletTypeService->update($walletType);

// Create a wallet with $100.00 initial balance (10000 cents)
$walletId = $walletService->createWallet('USD', 'user-123', 10000, 2);

// Add funds: $50.00
$transaction = $transactionService->addFunds(
    TransactionDTO::create($walletId, 5000)
        ->setDescription('Deposit from bank account')
);

// Withdraw funds: $30.00
$transaction = $transactionService->withdrawFunds(
    TransactionDTO::create($walletId, 3000)
        ->setDescription('Purchase payment')
);

// Reserve funds for pending withdrawal: $20.00
$reserve = $transactionService->reserveFundsForWithdraw(
    TransactionDTO::create($walletId, 2000)
        ->setDescription('Pre-authorization')
);

// Accept the reservation
$transactionService->acceptFundsById($reserve->getTransactionId());

// Get wallet balance
$wallet = $walletService->getById($walletId);
echo "Available: " . ($wallet->getAvailable() / 100) . " USD\n";
```

Documentation
-------------

[](#documentation)

- [Getting Started](docs/getting-started.md) - Installation, database setup, and quick start guide
- [Wallet Management](docs/wallet-management.md) - Create, retrieve, and manage wallets
- [Transaction Operations](docs/transaction-operations.md) - Add, withdraw, and query transactions
- [Reserved Funds](docs/reserved-funds.md) - Pre-authorize and manage pending transactions
- [Extending Entities](docs/extending-entities.md) - Add custom fields to wallets and transactions
- [Database Schema](docs/database-schema.md) - Complete database schema documentation

Full documentation is available at

Core Concepts
-------------

[](#core-concepts)

### Integer Storage with Scale

[](#integer-storage-with-scale)

All monetary amounts are stored as **integers** (BIGINT) representing the smallest currency unit:

```
// USD with scale=2 (cents)
$walletId = $walletService->createWallet('USD', 'user-123', 10000, 2);
// 10000 represents $100.00

// Bitcoin with scale=8 (satoshis)
$btcWalletId = $walletService->createWallet('BTC', 'user-123', 100000000, 8);
// 100000000 represents 1.00000000 BTC

// Loyalty points with scale=0 (whole units)
$pointsWalletId = $walletService->createWallet('POINTS', 'user-123', 1000, 0);
// 1000 represents 1000 points
```

### Balance Components

[](#balance-components)

Each wallet maintains three balance components:

- **balance** - Total funds (reserved + available)
- **reserved** - Funds held for pending transactions
- **available** - Funds available for immediate use

```
$wallet = $walletService->getById($walletId);
echo "Balance: " . $wallet->getBalance();      // 10000 (total)
echo "Reserved: " . $wallet->getReserved();    // 2000 (blocked)
echo "Available: " . $wallet->getAvailable();  // 8000 (usable)
```

### Transaction Types

[](#transaction-types)

TypeCodeDescriptionBalanceBInitial balance or resetDepositDAdd funds immediatelyWithdrawWRemove funds immediatelyDeposit BlockedDBReserve for incoming fundsWithdraw BlockedWBReserve funds for withdrawalRejectRReverse a reserved transaction### Transaction Chain Integrity

[](#transaction-chain-integrity)

Every transaction links to the previous via `uuid` and `previousuuid`, creating an immutable audit trail:

```
$tx1 = $transactionService->addFunds($dto1);  // previousuuid = null
$tx2 = $transactionService->addFunds($dto2);  // previousuuid = $tx1->uuid
$tx3 = $transactionService->withdrawFunds($dto3);  // previousuuid = $tx2->uuid
```

Each transaction includes a SHA-256 checksum for data integrity verification.

Use Cases
---------

[](#use-cases)

### E-commerce Platform

[](#e-commerce-platform)

```
// Reserve funds when order is placed
$reserve = $transactionService->reserveFundsForWithdraw(
    TransactionDTO::create($walletId, 9999)
        ->setDescription('Order #12345')
        ->setReferenceSource('ecommerce')
        ->setReferenceId('order-12345')
);

// Capture payment when order ships
$transactionService->acceptFundsById($reserve->getTransactionId());

// Or cancel and release funds if order is cancelled
// $transactionService->rejectFundsById($reserve->getTransactionId());
```

### Multi-Currency Wallets

[](#multi-currency-wallets)

```
// Create multiple wallets for same user
$usdWallet = $walletService->createWallet('USD', 'user-123', 100000, 2);
$eurWallet = $walletService->createWallet('EUR', 'user-123', 50000, 2);
$btcWallet = $walletService->createWallet('BTC', 'user-123', 5000000, 8);

// Transfer between wallets (with exchange rate logic in your app)
$walletService->transferFunds($usdWallet, $eurWallet, 10000);
```

### Gaming/Betting Platform

[](#gamingbetting-platform)

```
// Reserve bet amount
$betReserve = $transactionService->reserveFundsForWithdraw(
    TransactionDTO::create($walletId, 5000)
        ->setDescription('Bet on Game #789')
);

// User wins - reject withdrawal and add winnings
$transactionService->rejectFundsById($betReserve->getTransactionId());
$transactionService->addFunds(
    TransactionDTO::create($walletId, 10000)
        ->setDescription('Bet winnings')
);

// User loses - accept withdrawal
// $transactionService->acceptFundsById($betReserve->getTransactionId());
```

Testing
-------

[](#testing)

```
# Start MySQL container
docker run --name mysql-container --rm \
  -e MYSQL_ROOT_PASSWORD=password \
  -p 3306:3306 -d mysql:8.0

# Run migrations
vendor/bin/migrate up mysql://root:password@localhost/test -path=db

# Run tests
vendor/bin/phpunit
```

API Reference
-------------

[](#api-reference)

### WalletService

[](#walletservice)

- `createWallet(string $walletTypeId, string $userId, int $balance, int $scale = 2, int $minValue = 0, ?string $extra = null): int`
- `getById(int $walletId): WalletEntity`
- `getByUserId(string $userId, string $walletType = ""): array`
- `getByWalletTypeId(string $walletTypeId): array`
- `overrideBalance(int $walletId, int $newBalance, int $newScale = 2, int $newMinValue = 0, string $description = "Reset Balance"): ?int`
- `partialBalance(int $walletId, int $balance, string $description = "Partial Balance"): TransactionEntity`
- `closeWallet(int $walletId): ?int`
- `transferFunds(int $walletSource, int $walletTarget, int $amount): array`

### TransactionService

[](#transactionservice)

- `addFunds(TransactionDTO $dto): TransactionEntity`
- `withdrawFunds(TransactionDTO $dto): TransactionEntity`
- `reserveFundsForWithdraw(TransactionDTO $dto): TransactionEntity`
- `reserveFundsForDeposit(TransactionDTO $dto): TransactionEntity`
- `acceptFundsById(int $transactionId): int`
- `acceptFundsByUuid(string $uuid): int`
- `rejectFundsById(int $transactionId): int`
- `rejectFundsByUuid(string $uuid): int`
- `acceptPartialFundsById(int $transactionId, TransactionDTO $transactionDTO, TransactionDTO $transactionRefundDTO): TransactionEntity`
- `getById(int $transactionId): TransactionEntity`
- `getByWallet(int $walletId, int $limit = null, int $offset = null): array`
- `getByDate(int $walletId, string $startDate, string $endDate, int $limit = null, int $offset = null): array`
- `getByReference(string $referenceSource, string $referenceId): array`
- `getByUuid(string $uuid): ?TransactionEntity`
- `existsTransactionByUuid(string $uuid): bool`
- `getReservedTransactions(int $walletId): array`

Dependencies
------------

[](#dependencies)

 ```
flowchart TD
    byjg/wallets --> ext-pdo
    byjg/wallets --> ext-openssl
    byjg/wallets --> byjg/micro-orm
```

      Loading ---

[Open source ByJG](http://opensource.byjg.com)

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance79

Regular maintenance activity

Popularity6

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 90.2% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~26 days

Total

4

Last Release

174d ago

Major Versions

5.0.2 → 6.0.02025-11-25

PHP version history (2 changes)5.0.x-devPHP &gt;=8.1 &lt;8.4

6.0.0PHP &gt;=8.3 &lt;8.6

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/981924?v=4)[Joao Gilberto Magalhaes](/maintainers/byjg)[@byjg](https://github.com/byjg)

---

Top Contributors

[![byjg](https://avatars.githubusercontent.com/u/981924?v=4)](https://github.com/byjg "byjg (110 commits)")[![leonardomunsa](https://avatars.githubusercontent.com/u/61881081?v=4)](https://github.com/leonardomunsa "leonardomunsa (12 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/byjg-wallets/health.svg)

```
[![Health](https://phpackages.com/badges/byjg-wallets/health.svg)](https://phpackages.com/packages/byjg-wallets)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
