How we guarantee transparent, verifiable randomness for every pack.
Before you open a pack, we publish a serverSeedHash — the SHA-256 hash of a secret serverSeed generated in advance using crypto.randomBytes(32).toString('hex'). This acts as our public commitment:
Each card or rarity slot in the pack corresponds to one entry in a list of ranges (each having a minRangeand maxRange).
To generate random numbers, we use HMAC-SHA512 with this logic:
for digestIndex = 0, 1, 2...
digest = HMAC_SHA512(serverSeed, `${clientSeed}:${nonce}:${digestIndex}`)
digest gives 64 bytes → 16 random 4-byte values
each 4-byte chunk = one random number
map each to its range:
num = bytesToUInt32(chunk)
rand = floor((num / 2^32) * (range.max - range.min + 1)) + range.minEach digest yields 16 random numbers. If the pack needs more than 16 (for example, 24 numbers to decide rarities and bonuses), we increment digestIndex to get additional digests — no randomness is ever reused.
Those random numbers are then mapped to card outcomes based on your pack's configured rarity and odds.
After your pack opens, you'll receive:
You can also use the Run verifier page to verify your results. Use the Response Details → View details button in your Opening History page to copy the raw response and paste the ClientSeed, Nonce, ServerSeed and OddsUsed into the verifier.