zeroant-wallet
v1.2.1
Published
A simple wallet SDK with Redis and MongoDB integration
Downloads
220
Readme
Light Wallet SDK
A lightweight, TypeScript-based wallet SDK for building credit, debit, and transfer flows with atomic operations, transaction logging, and secure wallet signatures. Designed with DRY + KISS + Clean Code principles for clarity and extensibility.
Supports three storage backends:
- Redis (Lua scripts) – high-throughput, in-memory atomicity
- MongoDB (multi-document transactions) – truly ACID, no Redis dependency
- PostgreSQL (SERIALIZABLE transactions + advisory locks) – relational ACID with NUMERIC precision
✨ Features
- 🔑 Wallet Creation with strong hasher-based walletId signature
- 💸 Credit, Debit, Transfer (P2P) APIs
- 🔄 Idempotent Transfers (deduplication + Redis-based locks)
- 🛡 Replay Protection (transfer nonce + TTL)
- 📜 Transaction Logging with replay-safe schema in MongoDB
- ⚡ Atomic Operations using Redis Lua scripts or MongoDB transactions
- 🧩 Extensible Adapters – swap storage backend without changing SDK code
- 🗄 Three Storage Backends – Redis (
LightWalletSDK), MongoDB (MongoWalletSDK), or PostgreSQL (PgWalletSDK) - 🐘 PostgreSQL Adapter – SERIALIZABLE isolation, advisory locks,
NUMERIC(20,8)precision, connection pooling, auto DDL - 📊 Aggregation Helpers (PG) –
sumByWallet(),countByStatus()for analytics - 🏗 Minimal SDK for clarity – adapt into your project structure
- 🚀 Ready to scale up to 10k TPS with Redis cluster + worker pools
📦 Installation
npm install zeroant-walletor with Yarn:
yarn add zeroant-walletPeer Dependencies
This package requires the following peer dependencies:
| Package | Minimum Version |
|-----------|----------------|
| ioredis | >=5.0.0 |
| mongodb | >=6.0.0 |
| pg | >=8.0.0 |
Install whichever you need based on your chosen storage backend:
# Redis + MongoDB (LightWalletSDK)
npm install ioredis mongodb
# MongoDB only (MongoWalletSDK)
npm install mongodb
# PostgreSQL only (PgWalletSDK)
npm install pg🛠 Setup
Option A: Redis + MongoDB (LightWalletSDK)
Uses Redis Lua scripts for atomic wallet state and MongoDB for transaction logging.
import { LightWalletSDK } from "zeroant-wallet";
const sdk = new LightWalletSDK({
redisUrl: "redis://localhost:6379",
mongoUrl: "mongodb://localhost:27017/lightwallet",
secret: process.env.SDK_SECRET!,
defaultCurrency: "USD",
});
await sdk.start();Option B: MongoDB Only (MongoWalletSDK)
Uses MongoDB multi-document transactions for truly atomic operations. No Redis required. Requires a MongoDB replica set (single-node RS works for development).
import { MongoWalletSDK } from "zeroant-wallet";
const sdk = new MongoWalletSDK({
wxMongoUrl: "mongodb://localhost:27017/wallet",
txMongoUrl: "mongodb://localhost:27017/wallet",
secret: process.env.SDK_SECRET!,
defaultCurrency: "USD",
});
await sdk.start();Option C: PostgreSQL Only (PgWalletSDK)
Uses PostgreSQL SERIALIZABLE transactions with advisory locks for atomic operations and NUMERIC(20,8) precision for balances. No Redis or MongoDB required.
import { PgWalletSDK } from "zeroant-wallet";
const sdk = new PgWalletSDK({
wxPgUrl: "postgresql://user:pass@localhost:5432/wallet",
txPgUrl: "postgresql://user:pass@localhost:5432/wallet",
secret: process.env.SDK_SECRET!,
defaultCurrency: "USD",
wxPoolConfig: { poolMax: 20, maxRetries: 5 },
});
await sdk.start();Option D: Custom Adapters (WalletSDK)
Compose your own adapters by implementing IStorageAdapter, ITxLogger, and IHasher.
import { WalletSDK, PgWalletAdapter, PgTxLogger, Hasher } from "zeroant-wallet";
const sdk = new WalletSDK(
{ defaultCurrency: "USD", allowNegativeBalance: false },
new PgWalletAdapter("postgresql://localhost:5432/wallet"),
new PgTxLogger("postgresql://localhost:5432/wallet"),
new Hasher("your-secret"),
);
await sdk.start();📚 API Reference
1. Create Wallet
const wallet = await sdk.createWallet("alice", "USD", 100, { plan: "premium" });
console.log(wallet.walletId, wallet.balance);Options:
owner: string (optional)currency: e.g.,"USD","NGN"initial: initial balance (default 0)meta: extra metadataallowNegativeBalance: per-wallet overdraft flagallowNegativeCredit: per-wallet credit flag
2. Credit Wallet
await sdk.credit(wallet.walletId, 50, "credit-1", { note: "Top-up" });3. Debit Wallet
await sdk.debit(wallet.walletId, 20, "debit-1", { note: "Purchase" });4. Transfer (P2P)
await sdk.transfer(alice.walletId, bob.walletId, 10, "tx-1", { note: "Payment" });5. Find Transaction
const tx = await sdk.findTx({ txId: "tx-1" });6. Verify Wallet Signature
const valid = sdk.verifyWalletSignature(wallet.walletId, wallet.signature);7. Shutdown SDK
await sdk.shutdown();8. Find Many Transactions
const txs = await sdk.findManyTx(
{ from: "aliceWalletId" },
{ limit: 10, sort: "desc", skip: 10 }
);query:
Partial<Transaction>– e.g.{ from: walletId },{ currency: "USD" }filters:
TransactionFilter(optional)limit– number of resultssort–"asc"or"desc"skip– for pagination
Returns an array of matching transactions. Useful for audit trails, statements, and reporting.
🔒 Error Handling
SDK throws typed errors:
WalletErrorDuplicateTransactionErrWalletNotFoundErrInsufficientFundsErr
Example:
try {
await sdk.debit(wallet.walletId, 5000);
} catch (e) {
if (e instanceof InsufficientFundsErr) {
console.error("Balance too low!");
}
}🏗 Scaling Notes
- Use Redis Cluster for high throughput.
- Enable Lua scripts for atomic ops.
- Run multiple worker nodes consuming the Redis stream for async jobs.
- Use connection pooling for MongoDB, Redis, and PostgreSQL.
- Carefully tune resource limits to reach 10k TPS.
- Log transactions asynchronously to avoid bottlenecks.
- PostgreSQL: Tune
poolMax(default 10) and useSERIALIZABLEretry config (maxRetries, default 3). UseNUMERIC(20,8)precision for financial-grade accuracy.
🧪 Testing
Integration test example (using Jest):
it("should transfer funds between two wallets", async () => {
const alice = await sdk.createWallet("alice", "USD", 100);
const bob = await sdk.createWallet("bob", "USD", 0);
const tx = await sdk.transfer(alice.walletId, bob.walletId, 50);
expect(tx.status).toBe("success");
const aliceWallet = await sdk.getWallet(alice.walletId);
const bobWallet = await sdk.getWallet(bob.walletId);
expect(aliceWallet?.balance).toBe(50);
expect(bobWallet?.balance).toBe(50);
});📂 Project Structure
src/
├── wallet.sdk.ts # Core SDK, interfaces, types, errors
├── redis-wx.adapter.ts # Redis WX adapter (Lua scripts)
├── mongo-wx.adapter.ts # MongoDB WX adapter (transactions)
├── pg-wx.adapter.ts # PostgreSQL WX adapter (SERIALIZABLE txns)
├── mongo-tx.logger.ts # MongoDB transaction logger
├── pg-tx.logger.ts # PostgreSQL transaction logger
├── default.hasher.ts # HMAC-SHA256 signature hasher
├── light-wallet.sdk.ts # LightWalletSDK factory (Redis + MongoDB)
├── mongo-wallet.sdk.ts # MongoWalletSDK factory (MongoDB only)
├── pg-wallet.sdk.ts # PgWalletSDK factory (PostgreSQL only)
├── index.ts # Public exports
└── test/
├── sdk.unit.test.ts # WalletSDK core unit tests
├── redis-wx.unit.test.ts # Redis adapter unit tests
├── mongo-wx.unit.test.ts # MongoDB adapter unit tests
├── pg-wx.unit.test.ts # PostgreSQL adapter unit tests
├── mongo-wallet-sdk.unit.test.ts # MongoWalletSDK unit tests
├── mongo-tx.unit.test.ts # MongoDB TX logger unit tests
├── pg-tx.unit.test.ts # PostgreSQL TX logger unit tests
├── hasher.unit.test.ts # Hasher unit tests
├── light-wallet.integration.test.ts # LightWalletSDK integration tests
└── mongo-wallet.integration.test.ts # MongoWalletSDK integration tests🛡 License
MIT © 2025
