Provably Fair Numbers (PFN)
High-performance cryptographically secure random number generator for gaming applications with provable fairness guarantees.
Features
- Provably Fair: Uses HMAC-SHA256 for cryptographic security
- Two Versions: V1 (original) and V2 (performance optimized)
- Multiple Methods:
random(),randomInt(),crash(),shuffle(), etc. - Deterministic: Same inputs always produce same outputs
- Gaming Focused: Specialized methods for crash games, weighted selections
- Well Tested: Comprehensive test suite with 30+ test cases
Installation
npm install
Quick Start
Basic Usage
const { ProvablyFairNumbers } = require('./index.js')
// Create instance with client and server seeds
const pfn = new ProvablyFairNumbers('client-seed-123', 'server-seed-456')
// Generate uniform random float [0,1)
const randomNum = pfn.random()
// Generate random integer in range [1, 6] (dice roll)
const diceRoll = pfn.randomInt(1, 6)
// Generate crash game multiplier (1% house edge)
const multiplier = pfn.crash(1)
Advanced Usage
// Weighted random selection
const outcome = pfn.weightedRandom({
'win': 0.1, // 10% chance
'lose': 0.9 // 90% chance
})
// Shuffle array using Fisher-Yates algorithm
const deck = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
const shuffled = pfn.shuffle(deck)
// Generate array of unique random numbers
const lotteryNumbers = pfn.randomIntRange(1, 49, 6, true) // 6 unique numbers from 1-49
API Reference
Constructor
new ProvablyFairNumbers(clientSeed, serverSeed, nonce = 0, index = null)
Parameters:
clientSeed(string|array): Client seed or array of seedsserverSeed(string): Server seed for HMACnonce(number): Starting nonce value (default: 0)index(number|null): Index mode instead of nonce (default: null)
Core Methods
random()
Returns uniform random float in [0,1)
const value = pfn.random() // e.g., 0.723456789
randomInt(min, max)
Returns unbiased integer in [min, max] (inclusive)
const roll = pfn.randomInt(1, 6) // Dice roll: 1-6
randomFloat(min, max, precision)
Returns random float with specified precision
const price = pfn.randomFloat(10.00, 100.00, 2) // e.g., 45.67
randomLong()
Returns random 256-bit BigInt for advanced cryptographic use
const bigNum = pfn.randomLong() // BigInt value
crash(houseEdge, max)
Returns crash game multiplier with specified house edge
const multiplier = pfn.crash(1, 1000) // 1% house edge, max 1000x
shuffle(array)
Returns Fisher-Yates shuffled copy of array (modifies original)
const shuffled = pfn.shuffle([1, 2, 3, 4, 5]) // e.g., [3, 1, 5, 2, 4]
weightedRandom(spec)
Returns weighted random selection from object
const result = pfn.weightedRandom({a: 1, b: 2, c: 3}) // 'c' has 50% chance
randomIntRange(min, max, size, unique)
Returns array of random integers
const numbers = pfn.randomIntRange(1, 10, 5, true) // 5 unique numbers 1-10
State Management Methods
next(), nextInt(), nextFloat()
Increment nonce and return next random value
const val1 = pfn.next() // Advances nonce, returns random()
const val2 = pfn.nextInt(1, 10) // Advances nonce, returns randomInt(1, 10)
Performance Comparison
V2 provides significant performance improvements with optimized algorithms:
| Operation | V1 Time | V2 Time | Improvement |
|---|---|---|---|
| 10K sequential calls | ~23ms | ~21ms | 9% faster |
| 100 shuffle operations | ~12ms | ~11ms | 9% faster |
| 10K BigInt operations | ~40ms | ~34ms | 15% faster |
V2 includes advanced optimizations: buffer management, bitwise operations, and direct memory access for superior performance while maintaining identical statistical properties.
// V2 Performance Benefits
const pfnV2 = new ProvablyFairNumbersV2('client-seed', 'server-seed')
// Much faster for sequential operations (typical in gaming)
for (let i = 0; i < 10000; i++) {
pfnV2.random() // 22% faster than V1
}
// Efficient shuffling with Fisher-Yates algorithm
const deck = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
const shuffled = pfnV2.shuffle(deck) // Unbiased shuffle algorithm
Security & Fairness
- Cryptographic Security: Uses HMAC-SHA256 with server seed
- Provably Fair: Server seed can be revealed after use for verification
- Deterministic: Same inputs always produce identical outputs
- No Predictability: Each number is cryptographically secure
- Gaming Standards: Meets industry standards for fair gaming
Testing
Run Unit Tests
npm test
Run Performance Tests
npm run test:performance
Performance comparison tests covering:
- Basic functionality (random generation, ranges)
- Statistical properties (uniformity, bounds)
- Edge cases (min=max, large ranges, negative values)
- Deterministic behavior (same seeds = same results)
- Error handling (invalid parameters)
- V1 vs V2 performance benchmarks
- Shuffle optimizations for different array sizes
- Export verification and compatibility
- Performance benchmarks
- Gaming-specific features (crash game, weighted random)
npm run performance
# or directly:
node __tests__/test-both-versions.cjs
Compares V1 vs V2 performance across different operations with detailed benchmarks.
Test Coverage
- 30+ test cases covering all methods
- Edge case testing for robustness
- Performance validation ensuring efficiency
- Security verification maintaining cryptographic properties
- V1 vs V2 compatibility ensuring identical statistical properties
Version Differences
V1 (pfn.js)
- Original implementation
- Good performance for single operations
- Simple, straightforward code
V2 (pfn-v2.js)
- High-performance optimized algorithms
- 9% faster for sequential operations
- 15% faster for BigInt operations
- 9% faster shuffle performance
- Advanced buffer management and bitwise operations
- Direct memory access for superior efficiency
- Maintains identical statistical properties to V1
- Overall performance: Faster than V1 with significant BigInt improvements
Exports
// Default export (V2 - recommended)
const { ProvablyFairNumbers } = require('./index.js')
// Specific versions
const { ProvablyFairNumbers } = require('./pfn.js') // V1
const { ProvablyFairNumbersV2 } = require('./pfn-v2.js') // V2
// All versions
const {
ProvablyFairNumbers, // V2 (default)
ProvablyFairNumbersV1 // V1 (original)
} = require('./index.js')
License
Apache-2.0 License - see LICENSE file for details.