timefrontiers/php-wallet
Composer 安装命令:
composer require timefrontiers/php-wallet
包简介
Blockchain-like immutable wallet and transaction system with file-based ledger
README 文档
README
Blockchain-like immutable wallet and transaction system with file-based ledger.
Features
- Immutable Ledger: Append-only file-based ledger as source of truth
- Rolling Files: Monthly ledger archives prevent file bloat
- Checkpointing: Periodic snapshots for fast recovery
- Integrity Verification: Checksums detect tampering
- Batch Transactions: Efficient bulk transfers
- Payment Integration: Interface-based external payment verification
- Flexible Database: Pass credentials at initialization
Installation
composer require timefrontiers/php-wallet
Quick Start
use TimeFrontiers\Wallet\{Config, Wallet, Transaction}; // Database credentials $db_cred = [ 'server' => 'localhost', 'username' => 'wallet_user', 'password' => 'secure_password', 'database' => 'myapp_wallet', // Your database name (with any prefix) ]; // Configure ledger path Config::setLedgerPath('/var/data/.txhive/ledgers'); // Create/load wallets with credentials $alice = new Wallet('USR123456', 'NGN', $db_cred); $bob = new Wallet('USR789012', 'NGN', $db_cred); // Check balance echo $alice->balance(); // 5000.00 // Transfer $hashes = Transaction::transfer($alice, $bob, 1000.00, 'Payment for services'); // Batch transfer $result = Transaction::batch($alice) ->credit($bob, 500, 'Bonus') ->credit('219555555555555', 200, 'Refund') ->execute();
Database Setup
1. Create Your Database
Create your database manually with any required prefix:
CREATE DATABASE myprefix_wallet;
2. Run the Schema
The schema file is included in the package at schema/schema.sql:
mysql -u root -p myprefix_wallet < vendor/timefrontiers/php-wallet/schema/schema.sql
Or run directly in MySQL:
USE myprefix_wallet; SOURCE /path/to/vendor/timefrontiers/php-wallet/schema/schema.sql;
Schema Tables
| Table | Purpose |
|---|---|
wallets |
Wallet addresses and ownership |
wallet_history |
Immutable transaction log (triggers prevent UPDATE/DELETE) |
tranx_alert |
Notification queue |
wallet_batches |
Batch transaction metadata (optional) |
exchange_rates |
Dynamic rate history (optional) |
ledger_integrity |
File checksum tracking (optional) |
balance_snapshots |
Daily balance history (optional) |
Schema Views
| View | Purpose |
|---|---|
v_wallet_balances |
Quick balance lookup |
v_recent_transactions |
Last 1000 transactions |
v_pending_alerts |
Unsent notifications |
Database Connection
Option 1: Pass Credentials to Constructor
$db_cred = [ 'server' => 'localhost', 'username' => 'db_user', 'password' => 'db_pass', 'database' => 'myprefix_wallet', ]; $wallet = new Wallet('USR123456', 'NGN', $db_cred);
Option 2: Pass PDO Instance
$pdo = new PDO('mysql:host=localhost;dbname=myprefix_wallet', 'user', 'pass'); $wallet = new Wallet('USR123456', 'NGN', $pdo);
Option 3: Set Shared Connection
// Set once at application startup Wallet::setDatabase([ 'server' => 'localhost', 'username' => 'db_user', 'password' => 'db_pass', 'database' => 'myprefix_wallet', ]); // Now credentials are optional $wallet = new Wallet('USR123456', 'NGN');
Using Wallet's Connection
Each wallet instance has its own db connection:
$wallet = new Wallet('USR123456', 'NGN', $db_cred); // Access the connection $db = $wallet->db(); // Transaction methods use wallet's connection automatically Transaction::transfer($from, $to, 100, 'Payment');
Configuration
use TimeFrontiers\Wallet\Config; // Ledger storage path Config::setLedgerPath('/var/data/.txhive/ledgers'); // Decimal precision (default: 8) Config::setPrecision(8); // Wallet address format (default: prefix=219, length=15) Config::setAddressPrefix('219'); Config::setAddressLength(15); // Batch ID format (default: prefix=127, length=15) Config::setBatchPrefix('127'); Config::setBatchLength(15); // Strict integrity mode (fail on ledger/DB mismatch) Config::setStrictIntegrity(true); // Payment verifier Config::setPaymentVerifier(new MyPaymentVerifier()); // Exchange rates Config::setExchangeProvider(new FixedRateProvider([ 'NGN:DWL' => 1.0, 'USD:NGN' => 1550.0, ]));
Code Generation
Codes are generated with configurable prefix and length:
// Wallet address: 219 + 12 random digits = 219123456789012 Config::setAddressPrefix('219'); Config::setAddressLength(15); $address = Config::generateAddress(); // Batch ID: 127 + 12 random digits = 127987654321098 Config::setBatchPrefix('127'); Config::setBatchLength(15); $batch = Config::generateBatch(); // Generic code generation $code = Config::generateCode('PRE', 18); // PRE + 15 digits // Validation Config::isValidAddress('219123456789012'); // true Config::isValidBatch('127987654321098'); // true
Wallet Operations
Create/Load Wallet
// By user + currency (creates if not exists) $wallet = new Wallet('USR123456', 'NGN', $db_cred); // By address (must exist) $wallet = new Wallet('219123456789012', '', $db_cred); // Check existence Wallet::exists('219123456789012', $pdo); // Find user's wallets $wallets = Wallet::findByUser('USR123456', $pdo);
Balance
// Get balance (from ledger - source of truth) $balance = $wallet->balance(); // Verify against database (throws IntegrityException on mismatch) $balance = $wallet->balance(verify: true); // Check sufficient funds $wallet->hasSufficientBalance(1000.00); // bool
Transactions
Transfer Between Wallets
$hashes = Transaction::transfer($from, $to, 1000.00, 'Payment'); // Returns: ['credit_hash', 'debit_hash']
Credit from External Payment
use TimeFrontiers\Wallet\Payment\MockPaymentVerifier; $verifier = new MockPaymentVerifier(); $verifier->addPayment('PAY123456', 5000.00, 'NGN', 'paid'); $hash = Transaction::creditFromPayment( $wallet, 'PAY123456', 5000.00, 'Top-up via Stripe', $verifier );
Batch Transfers
$result = Transaction::batch($source_wallet) ->credit('219111111111111', 100.00, 'Bonus') ->credit('219222222222222', 50.00, 'Refund') ->credit('219333333333333', 25.00, 'Cashback') ->execute(); // Result $result->batchId(); // '127123456789012' $result->totalAmount(); // 175.00 $result->creditCount(); // 3 $result->hashes(); // All tx hashes $result->creditHashes(); // Credit hashes only $result->debitHash(); // Single debit hash
Bulk Credits
$result = Transaction::batch($source) ->creditMany([ ['address' => '219111111111111', 'amount' => 100, 'narration' => 'Bonus'], ['address' => '219222222222222', 'amount' => 50, 'narration' => 'Refund'], ]) ->execute();
Query Transactions
// Find by hash $tx = Transaction::find('abc123...', $pdo); // Find by address $txs = Transaction::findByAddress('219123456789012', type: 'credit', limit: 50, db: $pdo); // Find by batch $txs = Transaction::findByBatch('127123456789012', $pdo);
Ledger System
File Structure
/.txhive/ledgers/USR123456/
├── 219123456789012.ledger # Current active
├── 219123456789012.2024-01.ledger # January archive
├── 219123456789012.2024-02.ledger # February archive
└── 219123456789012.checksum # Integrity hash
Direct Ledger Access
$ledger = $wallet->ledger(); // Read operations $ledger->balance(); $ledger->count(); $ledger->count('credit'); $ledger->totals(); $ledger->first(); $ledger->last(); $ledger->getTransaction('abc123'); $ledger->getTransactions('credit'); // Verification $ledger->verify(); // Archives $ledger->archives();
Recovery
// Rebuild ledger from database $transactions = Transaction::findByAddress($address, db: $pdo); $wallet->ledger()->rebuild($transactions);
Payment Integration
Implement Custom Verifier
use TimeFrontiers\Wallet\Payment\PaymentVerifierInterface; class StripePaymentVerifier implements PaymentVerifierInterface { public function verify(string $reference, float $amount, string $currency): bool { $payment = \Stripe\PaymentIntent::retrieve($reference); return $payment->status === 'succeeded' && $payment->amount >= $amount * 100 && strtoupper($payment->currency) === $currency; } public function availableBalance(string $reference): float { // Return available balance } public function markSpent(string $reference, float $amount, string $tx_hash): bool { // Record the claim } public function getPayment(string $reference): ?array { // Return payment details } public function isValidReference(string $reference): bool { return preg_match('/^pi_[a-zA-Z0-9]+$/', $reference); } }
Error Handling
use TimeFrontiers\Wallet\Exception\{ WalletException, WalletNotFoundException, InsufficientBalanceException, IntegrityException, PaymentVerificationException, TransactionException }; try { Transaction::transfer($from, $to, 1000000, 'Big payment'); } catch (InsufficientBalanceException $e) { echo "Need {$e->required()}, have {$e->available()}"; echo "Shortfall: {$e->shortfall()}"; } catch (IntegrityException $e) { echo "Ledger: {$e->ledgerBalance()}, DB: {$e->dbBalance()}"; } catch (PaymentVerificationException $e) { echo "Payment {$e->reference()} failed"; }
Security
Why File Ledger is More Secure
| Aspect | File Ledger | Database |
|---|---|---|
| Attack Surface | Server access only | SQL injection, leaked creds |
| Remote Tampering | Requires server access | Multiple vectors |
| Access Control | OS permissions | App + DB users |
| Detection | Checksums | Requires audit logs |
Best Practices
- Store ledgers outside web root:
/var/data/.txhive/ - Restrict file permissions:
chmod 600on ledger files - Use strict integrity mode: Fail on mismatch
- Regular backups: Archive ledger files
- Monitor alerts table: Process pending notifications
License
timefrontiers/php-wallet 适用场景与选型建议
timefrontiers/php-wallet 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 9 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 04 月 16 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php」 「ledger」 「transaction」 「wallet」 「immutable」 「blockchain」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 timefrontiers/php-wallet 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 timefrontiers/php-wallet 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 timefrontiers/php-wallet 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
DUKPT implementation in PHP
The BlockTrail PHP SDK, for integration of Bitcoin functionality through the BlockTrail API
General Ledger and Journal Accounting Package for Laravel with JSON API
Send mails after DB transaction is committed
This is a transaction.
PHP SDK for Ledga.io - Programmatic double-entry ledgers for finance, gaming and multi-tenant SaaS
统计信息
- 总下载量: 9
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 36
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-04-16