npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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

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/core

Quick 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&currency_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