@omnitronix/bonnys-fortune-game-engine 1.2.6 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +0 -0
  2. package/dist/bonnys-fortune-v1.game-engine.js +2 -2
  3. package/dist/bonnys-fortune-v1.game-engine.js.map +1 -1
  4. package/dist/config/reel-strips-config/reels-BASE.csv +0 -0
  5. package/dist/config/reel-strips-config/reels-BONUS.csv +0 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/logic/handlers/base-game.handler.js +1 -19
  8. package/dist/logic/handlers/base-game.handler.js.map +1 -1
  9. package/dist/logic/handlers/collect-feature-bonus.handler.js +2 -2
  10. package/dist/logic/handlers/collect-feature-bonus.handler.js.map +1 -1
  11. package/dist/logic/handlers/free-spins-bonus.handler.js +2 -4
  12. package/dist/logic/handlers/free-spins-bonus.handler.js.map +1 -1
  13. package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js +2 -4
  14. package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js.map +1 -1
  15. package/dist/logic/handlers/treasure-hunt-bonus.handler.js +2 -4
  16. package/dist/logic/handlers/treasure-hunt-bonus.handler.js.map +1 -1
  17. package/dist/rng/rng-client.factory.js +3 -46
  18. package/dist/rng/rng-client.factory.js.map +1 -1
  19. package/package.json +1 -1
  20. package/dist/__tests__/rng-gli19-compliance.test.js +0 -222
  21. package/dist/__tests__/rng-gli19-compliance.test.js.map +0 -1
  22. package/dist/__tests__/rng-seed-security.test.js +0 -263
  23. package/dist/__tests__/rng-seed-security.test.js.map +0 -1
  24. package/dist/__tests__/rng-seed-type.test.js +0 -282
  25. package/dist/__tests__/rng-seed-type.test.js.map +0 -1
  26. package/dist/__tests__/rng-stress-boundary.test.js +0 -386
  27. package/dist/__tests__/rng-stress-boundary.test.js.map +0 -1
@@ -1,263 +0,0 @@
1
- "use strict";
2
- /**
3
- * RNG Seed Security Tests - Bonny's Fortune
4
- * Comprehensive Attack Vector Coverage for GLI-19 Compliance
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const bonnys_fortune_v1_game_engine_1 = require("../bonnys-fortune-v1.game-engine");
8
- const bonnys_fortune_types_1 = require("../logic/bonnys-fortune.types");
9
- describe('RNG Seed Security - Attack Vector Tests', () => {
10
- let engine;
11
- beforeEach(() => {
12
- engine = new bonnys_fortune_v1_game_engine_1.BonnysFortuneV1GameEngine();
13
- });
14
- async function initSession() {
15
- return engine.processCommand(null, null, {
16
- id: 'init-security',
17
- type: 'INIT_SESSION_STATE',
18
- payload: { betAmountThresholds: [1, 2, 5, 10], defaultBetAmount: 1 },
19
- });
20
- }
21
- async function executeSpin(publicState, privateState) {
22
- return engine.processCommand(publicState, privateState, {
23
- id: `spin-${Math.random().toString(36).slice(2)}`,
24
- type: 'SPIN',
25
- payload: { sessionId: 'test', betAmount: 1, gameCode: 'bonnys-fortune', gameVersion: '1.0.0', lines: 10, creditsPerLine: 1 },
26
- });
27
- }
28
- async function executeBonusRound(publicState, privateState) {
29
- const pendingBonus = privateState.pendingBonuses?.[0];
30
- if (!pendingBonus) {
31
- throw new Error('No pending bonus found');
32
- }
33
- return engine.processCommand(publicState, privateState, {
34
- id: `bonus-${Math.random().toString(36).slice(2)}`,
35
- type: 'START_BONUS_ROUND',
36
- payload: {
37
- sessionId: 'test',
38
- betAmount: pendingBonus.betAmount || 1,
39
- bonusId: pendingBonus.bonusId,
40
- bonusType: pendingBonus.bonusType,
41
- gameCode: 'bonnys-fortune',
42
- gameVersion: '1.0.0',
43
- },
44
- });
45
- }
46
- async function executeSpinWithBonusHandling(publicState, privateState) {
47
- const results = [];
48
- let pub = publicState;
49
- let priv = privateState;
50
- const spin = await executeSpin(pub, priv);
51
- results.push(spin);
52
- pub = spin.publicState;
53
- priv = spin.privateState;
54
- // Handle bonus rounds - any non-BASE_GAME_SPIN with pending bonuses
55
- while (priv.nextSpinType !== bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN && priv.pendingBonuses?.length > 0) {
56
- const bonus = await executeBonusRound(pub, priv);
57
- results.push(bonus);
58
- pub = bonus.publicState;
59
- priv = bonus.privateState;
60
- }
61
- return { results, publicState: pub, privateState: priv };
62
- }
63
- function canonicalizeForHash(outcome) {
64
- const entries = Object.entries(outcome)
65
- .map(([actionId, record]) => ({
66
- actionId,
67
- result: Number(record.result),
68
- seed: String(record.seed),
69
- min: Number(record.min),
70
- max: Number(record.max),
71
- }))
72
- .sort((a, b) => a.actionId.localeCompare(b.actionId));
73
- return JSON.stringify(entries);
74
- }
75
- // ============================================================
76
- // MALFORMED SEED INJECTION
77
- // ============================================================
78
- describe('Malformed Seed Injection', () => {
79
- it('should handle whitespace-padded seeds differently', () => {
80
- const outcome1 = { test: { result: 5, seed: 123, min: 0, max: 10 } };
81
- const outcome2 = { test: { result: 5, seed: ' 123', min: 0, max: 10 } };
82
- expect(canonicalizeForHash(outcome1)).not.toBe(canonicalizeForHash(outcome2));
83
- });
84
- it('should escape special JSON characters in actionIds', () => {
85
- const outcome = { 'action\n"test': { result: 5, seed: 123, min: 0, max: 10 } };
86
- const canonical = canonicalizeForHash(outcome);
87
- expect(() => JSON.parse(canonical)).not.toThrow();
88
- });
89
- it('should handle zero-width unicode characters', () => {
90
- const outcome = { test: { result: 5, seed: '123\u200B456', min: 0, max: 10 } };
91
- const canonical = canonicalizeForHash(outcome);
92
- expect(canonical.length).toBeGreaterThan(0);
93
- });
94
- it('should not interpret hex strings as numbers', () => {
95
- const outcome = { test: { result: 5, seed: '0xFF', min: 0, max: 10 } };
96
- expect(canonicalizeForHash(outcome)).toContain('"seed":"0xFF"');
97
- });
98
- it('should not interpret octal strings as numbers', () => {
99
- const outcome = { test: { result: 5, seed: '0777', min: 0, max: 10 } };
100
- expect(canonicalizeForHash(outcome)).toContain('"seed":"0777"');
101
- });
102
- });
103
- // ============================================================
104
- // TYPE CONFUSION
105
- // ============================================================
106
- describe('Type Confusion', () => {
107
- it('should handle array seeds', () => {
108
- const outcome = { test: { result: 5, seed: [123], min: 0, max: 10 } };
109
- expect(canonicalizeForHash(outcome)).toContain('"seed":"123"');
110
- });
111
- it('should handle null seeds', () => {
112
- const outcome = { test: { result: 5, seed: null, min: 0, max: 10 } };
113
- expect(canonicalizeForHash(outcome)).toContain('"seed":"null"');
114
- });
115
- it('should handle undefined seeds', () => {
116
- const outcome = { test: { result: 5, seed: undefined, min: 0, max: 10 } };
117
- expect(canonicalizeForHash(outcome)).toContain('"seed":"undefined"');
118
- });
119
- it('should handle boolean seeds', () => {
120
- const outcome = { test: { result: 5, seed: true, min: 0, max: 10 } };
121
- expect(canonicalizeForHash(outcome)).toContain('"seed":"true"');
122
- });
123
- it('should handle BigInt seeds', () => {
124
- const outcome = { test: { result: 5, seed: BigInt(123), min: 0, max: 10 } };
125
- expect(canonicalizeForHash(outcome)).toContain('"seed":"123"');
126
- });
127
- it('should handle Symbol seeds', () => {
128
- const symbol = Symbol('test');
129
- expect(String(symbol)).toBe('Symbol(test)');
130
- });
131
- it('should handle object with custom toString', () => {
132
- const malicious = { toString: () => '123', valueOf: () => 456 };
133
- const outcome = { test: { result: 5, seed: malicious, min: 0, max: 10 } };
134
- expect(canonicalizeForHash(outcome)).toContain('"seed":"123"');
135
- });
136
- });
137
- // ============================================================
138
- // INTEGER BOUNDARIES
139
- // ============================================================
140
- describe('Integer Boundaries', () => {
141
- it('should handle MAX_SAFE_INTEGER', () => {
142
- const outcome = { test: { result: 5, seed: Number.MAX_SAFE_INTEGER, min: 0, max: 10 } };
143
- expect(canonicalizeForHash(outcome)).toContain(`"seed":"${Number.MAX_SAFE_INTEGER}"`);
144
- });
145
- it('should handle MIN_SAFE_INTEGER', () => {
146
- const outcome = { test: { result: 5, seed: Number.MIN_SAFE_INTEGER, min: -100, max: 100 } };
147
- expect(canonicalizeForHash(outcome)).toContain(`"seed":"${Number.MIN_SAFE_INTEGER}"`);
148
- });
149
- it('should handle zero seed', () => {
150
- const outcome = { test: { result: 5, seed: 0, min: 0, max: 10 } };
151
- expect(canonicalizeForHash(outcome)).toContain('"seed":"0"');
152
- });
153
- it('should handle negative seeds', () => {
154
- const outcome = { test: { result: 5, seed: -12345, min: -100, max: 100 } };
155
- expect(canonicalizeForHash(outcome)).toContain('"seed":"-12345"');
156
- });
157
- it('should handle NaN in result', () => {
158
- const outcome = { test: { result: NaN, seed: 123, min: 0, max: 10 } };
159
- expect(canonicalizeForHash(outcome)).toContain('"result":null');
160
- });
161
- it('should handle Infinity', () => {
162
- const outcome = { test: { result: Infinity, seed: 123, min: 0, max: 10 } };
163
- expect(canonicalizeForHash(outcome)).toContain('"result":null');
164
- });
165
- });
166
- // ============================================================
167
- // HASH COLLISION PREVENTION
168
- // ============================================================
169
- describe('Hash Collision Prevention', () => {
170
- it('should produce different hashes for adjacent seeds', () => {
171
- const outcome1 = { action: { result: 5, seed: 123, min: 0, max: 10 } };
172
- const outcome2 = { action: { result: 5, seed: 124, min: 0, max: 10 } };
173
- expect(canonicalizeForHash(outcome1)).not.toBe(canonicalizeForHash(outcome2));
174
- });
175
- it('should produce different hashes for different actionIds', () => {
176
- const outcome1 = { action_a: { result: 5, seed: 123, min: 0, max: 10 } };
177
- const outcome2 = { action_b: { result: 5, seed: 123, min: 0, max: 10 } };
178
- expect(canonicalizeForHash(outcome1)).not.toBe(canonicalizeForHash(outcome2));
179
- });
180
- it('should produce same hash for number and string seeds after canonicalization', () => {
181
- const outcome1 = { action: { result: 5, seed: 123, min: 0, max: 10 } };
182
- const outcome2 = { action: { result: 5, seed: '123', min: 0, max: 10 } };
183
- expect(canonicalizeForHash(outcome1)).toBe(canonicalizeForHash(outcome2));
184
- });
185
- it('should resist JSON injection in actionId', () => {
186
- const outcome1 = { 'a","seed":"999': { result: 5, seed: 123, min: 0, max: 10 } };
187
- const outcome2 = { 'a': { result: 5, seed: 999, min: 0, max: 10 } };
188
- expect(canonicalizeForHash(outcome1)).not.toBe(canonicalizeForHash(outcome2));
189
- });
190
- });
191
- // ============================================================
192
- // PROTOTYPE POLLUTION
193
- // ============================================================
194
- describe('Prototype Pollution Prevention', () => {
195
- it('should handle constructor as actionId', () => {
196
- const outcome = { 'constructor': { result: 5, seed: 123, min: 0, max: 10 } };
197
- const canonical = canonicalizeForHash(outcome);
198
- expect(() => JSON.parse(canonical)).not.toThrow();
199
- });
200
- it('should handle toString as actionId', () => {
201
- const outcome = { 'toString': { result: 5, seed: 123, min: 0, max: 10 } };
202
- expect(() => canonicalizeForHash(outcome)).not.toThrow();
203
- });
204
- it('should not pollute prototype', () => {
205
- const outcome = { 'normal': { result: 6, seed: 456, min: 0, max: 10 } };
206
- canonicalizeForHash(outcome);
207
- expect({}.__proto__.result).toBeUndefined();
208
- });
209
- });
210
- // ============================================================
211
- // ENGINE RNG VALIDATION
212
- // ============================================================
213
- describe('Engine RNG Validation', () => {
214
- it('should return numeric seeds from engine', async () => {
215
- const init = await initSession();
216
- const spin = await executeSpin(init.publicState, init.privateState);
217
- expect(spin.success).toBe(true);
218
- if (spin.rngOutcome) {
219
- for (const [, record] of Object.entries(spin.rngOutcome)) {
220
- expect(typeof record.seed).toBe('number');
221
- expect(Number.isSafeInteger(record.seed)).toBe(true);
222
- }
223
- }
224
- });
225
- it('should have valid result within range', async () => {
226
- const init = await initSession();
227
- const spin = await executeSpin(init.publicState, init.privateState);
228
- if (spin.rngOutcome) {
229
- for (const [, record] of Object.entries(spin.rngOutcome)) {
230
- expect(record.result).toBeGreaterThanOrEqual(record.min);
231
- expect(record.result).toBeLessThanOrEqual(record.max);
232
- }
233
- }
234
- });
235
- it('should have unique actionIds', async () => {
236
- const init = await initSession();
237
- const spin = await executeSpin(init.publicState, init.privateState);
238
- if (spin.rngOutcome) {
239
- const actionIds = Object.keys(spin.rngOutcome);
240
- expect(actionIds.length).toBe(new Set(actionIds).size);
241
- }
242
- });
243
- it('should maintain type consistency across 50 spins', async () => {
244
- const init = await initSession();
245
- let pub = init.publicState;
246
- let priv = init.privateState;
247
- for (let i = 0; i < 50; i++) {
248
- const { results, publicState, privateState } = await executeSpinWithBonusHandling(pub, priv);
249
- // Verify RNG structure for all results (spin + any bonus rounds)
250
- for (const result of results) {
251
- if (result.rngOutcome) {
252
- for (const [, record] of Object.entries(result.rngOutcome)) {
253
- expect(typeof record.seed).toBe('number');
254
- }
255
- }
256
- }
257
- pub = publicState;
258
- priv = privateState;
259
- }
260
- });
261
- });
262
- });
263
- //# sourceMappingURL=rng-seed-security.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rng-seed-security.test.js","sourceRoot":"","sources":["../../src/__tests__/rng-seed-security.test.ts"],"names":[],"mappings":"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"}
@@ -1,282 +0,0 @@
1
- "use strict";
2
- /**
3
- * RNG Seed Type Tests - GLI-19 Compliance Verification
4
- *
5
- * These tests verify that the RNG seed type fix is working correctly:
6
- * 1. Seeds are returned as numbers (internal format)
7
- * 2. Seeds can be safely converted to strings (wire format)
8
- * 3. Hash canonicalization produces deterministic results
9
- * 4. Edge cases are handled correctly
10
- *
11
- * GLI-19 Sections:
12
- * - 3.4: Tamper-evident audit trails
13
- * - 3.4.2: Tamper detection
14
- * - 4.2.1: Deterministic replay
15
- */
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- const bonnys_fortune_v1_game_engine_1 = require("../bonnys-fortune-v1.game-engine");
18
- describe('RNG Seed Type - GLI-19 Compliance', () => {
19
- let engine;
20
- beforeEach(() => {
21
- engine = new bonnys_fortune_v1_game_engine_1.BonnysFortuneV1GameEngine();
22
- });
23
- // Helper to initialize session
24
- async function initSession(betAmount = 1.0) {
25
- const command = {
26
- id: 'init',
27
- type: 'INIT_SESSION_STATE',
28
- payload: {
29
- betAmount,
30
- currency: 'EUR',
31
- },
32
- };
33
- return engine.processCommand(null, null, command);
34
- }
35
- // Helper to execute spin
36
- async function executeSpin(publicState, privateState) {
37
- const spinCommand = {
38
- id: `spin-${Date.now()}`,
39
- type: 'SPIN',
40
- payload: {
41
- sessionId: 'test-session',
42
- betAmount: 1.0,
43
- },
44
- };
45
- return engine.processCommand(publicState, privateState, spinCommand);
46
- }
47
- describe('Seed Type Verification', () => {
48
- it('should return rngOutcome with numeric seeds', async () => {
49
- const init = await initSession();
50
- const spin = await executeSpin(init.publicState, init.privateState);
51
- expect(spin.success).toBe(true);
52
- expect(spin.rngOutcome).toBeDefined();
53
- // Verify all seeds are numbers
54
- for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
55
- expect(typeof record.seed).toBe('number');
56
- expect(Number.isInteger(record.seed)).toBe(true);
57
- expect(Number.isSafeInteger(record.seed)).toBe(true);
58
- }
59
- });
60
- it('should have seeds within safe integer range', async () => {
61
- const init = await initSession();
62
- // Run multiple spins to get variety of seeds
63
- let currentPublic = init.publicState;
64
- let currentPrivate = init.privateState;
65
- for (let i = 0; i < 10; i++) {
66
- const spin = await executeSpin(currentPublic, currentPrivate);
67
- if (spin.rngOutcome) {
68
- for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
69
- expect(record.seed).toBeLessThanOrEqual(Number.MAX_SAFE_INTEGER);
70
- expect(record.seed).toBeGreaterThanOrEqual(Number.MIN_SAFE_INTEGER);
71
- }
72
- }
73
- currentPublic = spin.publicState;
74
- currentPrivate = spin.privateState;
75
- }
76
- });
77
- it('should have consistent rngOutcome structure', async () => {
78
- const init = await initSession();
79
- const spin = await executeSpin(init.publicState, init.privateState);
80
- expect(spin.rngOutcome).toBeDefined();
81
- for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
82
- // Verify structure
83
- expect(typeof actionId).toBe('string');
84
- expect(actionId.length).toBeGreaterThan(0);
85
- // Verify record fields
86
- expect(typeof record.result).toBe('number');
87
- expect(typeof record.seed).toBe('number');
88
- expect(typeof record.min).toBe('number');
89
- expect(typeof record.max).toBe('number');
90
- // Verify result is within range
91
- expect(record.result).toBeGreaterThanOrEqual(record.min);
92
- expect(record.result).toBeLessThanOrEqual(record.max);
93
- }
94
- });
95
- });
96
- describe('Wire Format Conversion', () => {
97
- it('seeds should be safely convertible to strings', async () => {
98
- const init = await initSession();
99
- const spin = await executeSpin(init.publicState, init.privateState);
100
- for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
101
- const seedAsString = String(record.seed);
102
- const backToNumber = Number(seedAsString);
103
- // Round-trip conversion must be lossless
104
- expect(backToNumber).toBe(record.seed);
105
- }
106
- });
107
- it('string conversion should not lose precision', async () => {
108
- // Run 50 independent sessions to test various seed values
109
- // Each session gets fresh state to avoid bonus state complications
110
- for (let i = 0; i < 50; i++) {
111
- const init = await initSession();
112
- const spin = await executeSpin(init.publicState, init.privateState);
113
- if (spin.rngOutcome) {
114
- for (const [, record] of Object.entries(spin.rngOutcome)) {
115
- const original = record.seed;
116
- const asString = String(original);
117
- const restored = Number(asString);
118
- expect(restored).toBe(original);
119
- expect(asString).not.toContain('e'); // No scientific notation
120
- expect(asString).not.toContain('.'); // Must be integer
121
- }
122
- }
123
- }
124
- });
125
- });
126
- describe('Hash Canonicalization Verification', () => {
127
- /**
128
- * Simulates the canonicalization that RGS uses for hashing.
129
- * This must produce identical output for number vs string seeds.
130
- */
131
- function canonicalizeForHash(outcome) {
132
- const entries = Object.entries(outcome)
133
- .map(([actionId, record]) => ({
134
- actionId,
135
- result: Number(record.result),
136
- seed: String(record.seed),
137
- min: Number(record.min),
138
- max: Number(record.max),
139
- }))
140
- .sort((a, b) => a.actionId.localeCompare(b.actionId));
141
- return JSON.stringify(entries);
142
- }
143
- it('should produce same canonical form for number and string seeds', async () => {
144
- const init = await initSession();
145
- const spin = await executeSpin(init.publicState, init.privateState);
146
- // Get canonical with number seeds (as returned by engine)
147
- const canonicalNumber = canonicalizeForHash(spin.rngOutcome);
148
- // Convert seeds to strings (simulating wire format)
149
- const withStringSeeds = {};
150
- for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
151
- withStringSeeds[actionId] = {
152
- ...record,
153
- seed: String(record.seed),
154
- };
155
- }
156
- const canonicalString = canonicalizeForHash(withStringSeeds);
157
- // CRITICAL: Both must produce identical canonical form
158
- expect(canonicalNumber).toBe(canonicalString);
159
- });
160
- it('should produce deterministic canonical form across multiple calls', async () => {
161
- const init = await initSession();
162
- const spin = await executeSpin(init.publicState, init.privateState);
163
- const canonical1 = canonicalizeForHash(spin.rngOutcome);
164
- const canonical2 = canonicalizeForHash(spin.rngOutcome);
165
- const canonical3 = canonicalizeForHash(spin.rngOutcome);
166
- expect(canonical1).toBe(canonical2);
167
- expect(canonical2).toBe(canonical3);
168
- });
169
- it('should sort entries alphabetically by actionId', async () => {
170
- // Create outcome with known actionIds in reverse order
171
- const outcome = {
172
- z_action: { result: 1, seed: 100, min: 0, max: 10 },
173
- a_action: { result: 2, seed: 200, min: 0, max: 10 },
174
- m_action: { result: 3, seed: 300, min: 0, max: 10 },
175
- };
176
- const canonical = canonicalizeForHash(outcome);
177
- const parsed = JSON.parse(canonical);
178
- expect(parsed[0].actionId).toBe('a_action');
179
- expect(parsed[1].actionId).toBe('m_action');
180
- expect(parsed[2].actionId).toBe('z_action');
181
- });
182
- });
183
- describe('Bonus Round RNG Tracking', () => {
184
- it('should track RNG outcomes during bonus trigger', async () => {
185
- const init = await initSession();
186
- // Trigger a bonus via debug command
187
- const triggerResult = await engine.processCommand(init.publicState, init.privateState, {
188
- id: 'debug-trigger',
189
- type: 'DEBUG_TRIGGER_BONUS',
190
- payload: {
191
- bonusType: 'bonusGame1', // Treasure Hunt
192
- betAmount: 1.0,
193
- },
194
- });
195
- expect(triggerResult.success).toBe(true);
196
- // Debug trigger may or may not have rngOutcome depending on implementation
197
- });
198
- it('should maintain seed type consistency across bonus spins', async () => {
199
- const init = await initSession();
200
- // Trigger free spins bonus
201
- const trigger = await engine.processCommand(init.publicState, init.privateState, {
202
- id: 'debug-trigger',
203
- type: 'DEBUG_TRIGGER_BONUS',
204
- payload: {
205
- bonusType: 'bonusGame2', // Free Spins
206
- betAmount: 1.0,
207
- },
208
- });
209
- if (trigger.rngOutcome) {
210
- for (const [, record] of Object.entries(trigger.rngOutcome)) {
211
- expect(typeof record.seed).toBe('number');
212
- }
213
- }
214
- });
215
- });
216
- describe('Edge Cases', () => {
217
- it('should handle zero seed correctly', () => {
218
- const outcome = {
219
- test_action: { result: 5, seed: 0, min: 0, max: 10 },
220
- };
221
- const canonical = JSON.stringify(Object.entries(outcome)
222
- .map(([actionId, record]) => ({
223
- actionId,
224
- result: record.result,
225
- seed: String(record.seed),
226
- min: record.min,
227
- max: record.max,
228
- }))
229
- .sort((a, b) => a.actionId.localeCompare(b.actionId)));
230
- expect(canonical).toContain('"seed":"0"');
231
- });
232
- it('should handle negative seed correctly', () => {
233
- const outcome = {
234
- test_action: { result: 5, seed: -12345, min: -100, max: 100 },
235
- };
236
- const canonical = JSON.stringify(Object.entries(outcome)
237
- .map(([actionId, record]) => ({
238
- actionId,
239
- result: record.result,
240
- seed: String(record.seed),
241
- min: record.min,
242
- max: record.max,
243
- })));
244
- expect(canonical).toContain('"seed":"-12345"');
245
- });
246
- it('should handle MAX_SAFE_INTEGER seed correctly', () => {
247
- const maxSafe = Number.MAX_SAFE_INTEGER;
248
- const outcome = {
249
- test_action: { result: 5, seed: maxSafe, min: 0, max: 100 },
250
- };
251
- const seedString = String(maxSafe);
252
- const backToNumber = Number(seedString);
253
- expect(backToNumber).toBe(maxSafe);
254
- });
255
- });
256
- describe('Multiple Spins Consistency', () => {
257
- it('should maintain type consistency across 100 spins', async () => {
258
- const allSeeds = [];
259
- // Run 100 independent sessions to avoid bonus state complications
260
- // Each session gets fresh state
261
- for (let i = 0; i < 100; i++) {
262
- const init = await initSession();
263
- const spin = await executeSpin(init.publicState, init.privateState);
264
- if (spin.rngOutcome) {
265
- for (const [, record] of Object.entries(spin.rngOutcome)) {
266
- expect(typeof record.seed).toBe('number');
267
- allSeeds.push(record.seed);
268
- }
269
- }
270
- }
271
- // Verify all seeds are safe integers
272
- expect(allSeeds.every(s => Number.isSafeInteger(s))).toBe(true);
273
- // Log statistics for analysis document
274
- console.log(`\n=== RNG Seed Statistics (100 spins) - Bonny's Fortune ===`);
275
- console.log(`Total seeds collected: ${allSeeds.length}`);
276
- console.log(`Min seed: ${Math.min(...allSeeds)}`);
277
- console.log(`Max seed: ${Math.max(...allSeeds)}`);
278
- console.log(`All safe integers: ${allSeeds.every(s => Number.isSafeInteger(s))}`);
279
- });
280
- });
281
- });
282
- //# sourceMappingURL=rng-seed-type.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rng-seed-type.test.js","sourceRoot":"","sources":["../../src/__tests__/rng-seed-type.test.ts"],"names":[],"mappings":"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"}