@billdog.io/virtual-currency
v1.1.1-beta.5
Published
BillDog Virtual Currency SDK - Manage virtual currencies, balances, transactions, and exchanges with optional server sync
Maintainers
Readme
@billdog.io/virtual-currency
Virtual Currency SDK for BillDog - Manage in-app virtual currencies, balances, transactions, and exchanges.
Version: 1.1.1-beta.5
Features
- 🪙 Multi-currency support - Manage coins, gems, tokens, or any virtual currency
- 🔄 Server sync - Optional real-time sync with BillDog backend
- 📴 Offline queue - Writes that cannot reach the server are queued (with their idempotency key) and synced when connectivity returns; a write the server refuses (403, 400, 404) is thrown, never queued or applied locally
- 📜 Transaction history - Track all balance changes
- 🎯 Event callbacks - React to balance changes and transactions
Installation
npm install @billdog.io/virtual-currency @billdog.io/coreQuick Start
Local-Only Mode (Default)
import { VirtualCurrencyManager } from '@billdog.io/virtual-currency';
const vcm = new VirtualCurrencyManager();
// Initialize currencies
vcm.initializeCurrency('coins', 'Gold Coins', 100);
vcm.initializeCurrency('gems', 'Gems', 0);
// Add balance
await vcm.addBalance('coins', 50, 'Daily reward');
console.log(await vcm.getBalance('coins')); // 150
// Spend currency
await vcm.deductBalance('coins', 25, 'Item purchase');
// Get all currencies
const currencies = await vcm.getAllCurrencies();Server-Synced Mode
import { VirtualCurrencyManager } from '@billdog.io/virtual-currency';
const vcm = new VirtualCurrencyManager({
syncWithServer: true,
apiKey: 'your-billdog-api-key',
customerId: 'customer-123', // optional: omit for a guest's own device wallet
enableOfflineQueue: true,
enableLogging: true,
});
// Sync from server on init
await vcm.syncFromServer();
// All operations now sync to server
const newBalance = await vcm.addBalance('coins', 50, 'Level complete');
// Converting between currencies: BillDog holds no exchange rate. From your server, apply both
// legs atomically with POST /virtual-currency/adjustments:
// { app_user_id, legs: [{ currency_id: 'COINS', amount: -100 }, { currency_id: 'GEMS', amount: 10 }] }
// Process any queued offline operations
await vcm.processOfflineQueue();Configuration
interface VirtualCurrencyConfig {
// Local storage
storageKey?: string; // Default: 'billdog_virtual_currencies'
enableTransactionHistory?: boolean; // Default: true
maxTransactionHistory?: number; // Default: 100
// Server sync
syncWithServer?: boolean; // Default: false
apiKey?: string; // Required when sync enabled
customerId?: string; // Optional: your app user id; omit for a guest
// Offline handling
enableOfflineQueue?: boolean; // Default: true
maxOfflineQueueSize?: number; // Default: 100
// Debug
enableLogging?: boolean; // Default: false
}API Reference
Balance Operations
getBalance(currencyId: string): Promise<number>
Get balance for a currency. Fetches from server if sync enabled.
addBalance(currencyId, amount, reason?, metadata?): Promise<number>
Add to currency balance. Returns new balance.
deductBalance(currencyId, amount, reason?, metadata?): Promise<number>
Subtract from balance. Throws if insufficient funds.
grantCurrency(currencyId, amount, reason?): Promise<number>
Admin grant operation. Adds currency without spend verification.
Currency Management
initializeCurrency(id, name, initialBalance?): void
Initialize a new currency (local-only operation).
getAllCurrencies(): Promise<VirtualCurrency[]>
Get all currencies with current balances.
exchangeCurrency(from, to, amount): Promise<ExchangeResult> (deprecated)
Retired: always answers success: false and changes nothing. BillDog holds no exchange rate; apply both legs from your server with POST /virtual-currency/adjustments.
Transaction History
getTransactionHistory(currencyId?, limit?): Promise<Transaction[]>
Get transaction history, optionally filtered by currency.
Sync Operations
syncFromServer(): Promise<void>
Pull latest balances from server to local cache.
processOfflineQueue(): Promise<ProcessResult>
Process any queued offline operations.
getOfflineQueueSize(): number
Get number of pending offline operations.
Event Handling
vcm.setEventHandler({
onBalanceChanged(currencyId, newBalance, oldBalance) {
console.log(`${currencyId}: ${oldBalance} → ${newBalance}`);
},
onTransactionCompleted(transaction) {
console.log('Transaction:', transaction);
},
onExchangeCompleted(result) {
console.log('Exchange:', result);
},
onSyncCompleted() {
console.log('Synced with server');
},
onSyncFailed(error) {
console.error('Sync failed:', error);
},
onOfflineQueueProcessed(success, failed) {
console.log(`Processed: ${success} success, ${failed} failed`);
},
});Types
interface VirtualCurrency {
id: string;
name: string;
code: string;
symbol?: string;
balance: number;
lastUpdated?: Date;
}
interface VirtualCurrencyTransaction {
id: string;
currencyId: string;
amount: number;
type: 'earn' | 'spend' | 'purchase' | 'grant' | 'exchange';
reason?: string;
timestamp: Date;
metadata?: Record<string, unknown>;
}
interface ExchangeResult {
success: boolean;
fromCurrencyId: string;
toCurrencyId: string;
fromAmount: number;
toAmount: number;
exchangeRate: number;
newFromBalance: number;
newToBalance: number;
error?: string;
}Server Endpoints
When syncWithServer: true, the SDK calls these consolidated endpoints:
| Operation | Method | Endpoint |
|-----------|--------|----------|
| Get balance | GET | /virtual-currency/balances?customer_id=X¤cy_id=Y |
| Get all balances | GET | /virtual-currency/balances?customer_id=X |
| Record transaction | POST | /virtual-currency/transactions |
| Get history | GET | /virtual-currency/transactions/history?customer_id=X |
| Exchange | POST | /virtual-currency/exchange |
All requests include X-BillDog-API-Key header for authentication.
License
MIT
