THE RAIN SDK v2.1 — SEVEN PACKAGES, TAKE WHAT YOU NEED
NPM: READY, UNPUBLISHED — OWNER DECIDES SCOPESOURCE: sdk-v2 MIRROR BRANCH ON GITHUBRUNS IN PRODUCTION ON 2 DEPLOYMENTSPRE-AUDIT
npm status, exactly: npm pack --dry-run is clean for rng-core (24 files, 21.8 kB), rng-session (13, 20.8 kB), rng-node (34, 35.4 kB); @rain/* names are free (404) but the rain org's ownership can't be read anonymously — alternatives @rain-risk-markets/*, @rainriskmarkets/* verified free. Publishing is one command away and is the owner's decision (PUBLISHING). Until then: github.com/Quecko-Org/rain-playmarket-fe-dev · sdk-v2 ↗ (mirror branch; dedicated repo pending).
v1 shipped one package, @rain/risk-markets-sdk, with four modules (games · predictions · vaults · core). v2 splits it along the trust boundary so an integrator can adopt RAIN RNG alone without inheriting the casino. See the v1 → v2 changelog.
| PACKAGE | WHAT IT DOES | WHO IT'S FOR | STATUS |
|---|---|---|---|
@rain/rng-core | The formula and nothing else: outcome(), verifyRound(), chain-link check, typed inputs. Pure functions, zero I/O, zero dependencies beyond keccak. MIT + attribution. | Anyone who wants to verify or reuse RAIN RNG — casinos, auditors, agent builders. | LIVE (same code as the house nodes) |
@rain/rng-session | Two-party session: hash-chain generation (default 65,536-deep since 2.1, WebCrypto secret, automatic rotation at 90 %), commit-reveal choreography, pipelining (prefetch(), maxInFlight), seed derivation from one wallet signature, EIP-712 signing helpers, snapshot/restore. Transport-agnostic. | Products that run their own counterparty (house node, agent, matchmaking server). | LIVE |
@rain/rng-node NEW 2.1 | The house counterparty as a service: HTTP + WebSocket + long-poll transports, persist-before-reveal store (memory / Postgres), runtime KATs before first reveal and every 24 h (/selftest, /healthz.kat, 503 in error state), fingerprint self-check against lab/FINGERPRINTS.json, Dockerfile. This is what ran the real-network latency test. | Operators hosting their own RNG node; labs (it is the unit under test). | BUILT · lab-tested · not yet in a reference deployment |
rng-py (rain_rng) NEW 2.1 | Pure-Python, stdlib-only mirror of rng-core: keccak-f[1600], the ceremony, HMAC_DRBG, ChaCha20, intBelow/shuffle. Byte-identical to the TypeScript on shared vectors (26 pytest). engine/rng.py drop-in. | Python game servers and auditors who want a second implementation. | BUILT · vectors cross-checked |
@rain/channels | Typed client for ChannelManager V4 / ChannelManagerAA: open (EOA or ERC-1271 smart account with session key), act() dual-signed states, checkpoint, cooperativeClose, forceClose / challenge / finalize, reclaimStale, self-heal. Token-agnostic deployment registry with EIP-55 validation (v1 core). | Operators running an instance; products that want on-chain-enforced settlement. | LIVE |
@rain/games | Rules engines that byte-mirror the on-chain verifiers: blackjack, roulette, baccarat, crash, dice, quick slots, Engine V2 slot runtime (KeccakRng), Craps, step games. IRulesVerifier scaffolding + differential-fuzz harness for new games. | Game studios; white-label operators adding titles. | LIVE (13 + 8 + Craps + Crash in production) |
@rain/markets | Pari-mutuel Outperform client (CryptoRace v1.1: enter, quote, claim, round state, oracle attestation decoding) + the unmodified rain-sdk-v2 passthrough for Rain prediction markets (v1 predictions). Calls labelled trustless vs api-backed. | Trading firms, market builders, parametric-cover distributors. | LIVE (Outperform) · LIVE via Rain markets |
Trustless vs api-backed — labelled on every call. Channel opens/closes/disputes, every tx builder, every vault/bond/verifier read: trustless (direct contract, your RPC). Listings, order books, price feeds, profiles: api-backed (rain.one API, house node, or the Outperform keeper) — convenience reads, never settlement.
▸INSTALL
# npm: ready, unpublished (owner decides the scope) — until then clone the sdk-v2 branch and consume as a workspace/tarball dependency
# git clone -b sdk-v2 https://github.com/Quecko-Org/rain-playmarket-fe-dev.git && npm ci && npm run build
npm i @rain/rng-core # just the formula + verifier + drbg()/intBelow/shuffle (2.1)
npm i @rain/rng-core @rain/rng-session # run your own two-party sessions (pipelining, rotation)
npm i @rain/rng-node # host the counterparty (HTTP/WS, KATs, Postgres)
pip install ./packages/rng-py # Python mirror (rain_rng)
npm i @rain/channels @rain/games # open channels on Arbitrum + mirror the live games
npm i @rain/markets # Outperform + rain-sdk-v2 passthrough
# peer: ethers ^6
▸QUICKSTART — BY PERSONA
A · CASINO / AUDITOR — VERIFY A ROUND (rng-core)
import { outcome, verifyRound } from '@rain/rng-core';
const r = outcome({ pRev, hRev, sessionSeed, channelId, k }); // uint256 — same keccak as the verifiers
const ok = verifyRound({ pRev, hRev, sessionSeed, channelId, k, hAnchor, claimed: r }); // true ⇔ VERIFIED
console.log(r % 37n, ok); // e.g. roulette number, and whether the house told the truth
B · AI-AGENT BUILDER — A FAIR COIN BETWEEN TWO MACHINES (rng-session)
import { RngSession } from '@rain/rng-session';
const me = await RngSession.create({ role: 'player', secret: crypto.getRandomValues(new Uint8Array(32)) });
const open = me.commit(); // { seed, chainRoot } — send to the counterparty, receive theirs
me.open({ theirCommit: peer.commit, theirChainRoot: peer.chainRoot, channelId }); // fixes sessionSeed
const { myReveal } = me.nextReveal(); // round k — send with your decision
const r = me.settle({ theirReveal }); // verifies their chain link, returns uint256 r (throws on a bad reveal)
C · OPERATOR / PRODUCT — ONE CHANNEL, ALL GAMES (channels + games)
import { registerDeployment, ChannelSession } from '@rain/channels';
import { dice } from '@rain/games';
const PLAYMARKET = registerDeployment({ name: 'playmarket-usdttt', chainId: 42161,
channelManager: '0x60743006c2a5Dd5b9907CA37e7381854ff860959', houseBond: '0x3D2d25373836C9d102E83f4200e87d087B29b998',
token: '0x528F42C8560BBDa048690fB0982B07A9Ae52551A', tokenDecimals: 6,
verifiers: { mux: '0xDf214594D021a36bD61aB398c20c4A14cDD0b48e', engineV2: '0x5d6048AB261e6151AB44fE6053e7AEb35Cb5C1B1' } });
const s = new ChannelSession({ deployment: PLAYMARKET, account: smartAccount /* ERC-1271 + session key */, wsUrl });
await s.open({ deposit: 100_000_000n }); // one tx (gas-sponsored on #2), channel Active + sessionSeed emitted
const { game, fairness } = await s.act('dice', dice.BET, { line: 50, stake: 1_000_000n }); // 1 RTT, dual-signed, verified locally
await s.close(); // CASH OUT ALL — one settle tx
D · TRADING FIRM — 5-MINUTE OUTPERFORM MARKETS (markets)
import { Outperform } from '@rain/markets';
const op = new Outperform({ chainId: 42161, address: '0x340991442B5BFCD80a46D709748be28b788414B7', signer });
const round = await op.current(); // trustless read: coins, open prices, pool, lock time
const q = await op.quote({ coin: 'BNB', stake: 5_000_000n }); // shares @ current curve, dividend to earlier holders
await op.enter({ coin: 'BNB', stake: 5_000_000n }); // on-chain; settlement by keeper + house-signed oracle v1 (not provably fair — disclosed)
API names above are the v2 surface as built; signatures may still move before npm publication. Every example runs against the live Arbitrum One contracts listed on the front page.
▸TOKEN-AGNOSTIC DEPLOYMENT CONFIG
The protocol is token-agnostic by construction: ChannelManager takes the settlement token and vault as constructor parameters. Deployment #1 runs RUSD (0x260c7019E760763988843Bc5b873d749b5937469), deployment #2 runs USDTTT (0x528F42C8560BBDa048690fB0982B07A9Ae52551A) — both play-money. Register your own:
import { registerDeployment, RainVault } from "@rain/channels";
const acme = registerDeployment({
name: "acme-usdc-arbitrum", chainId: 42161,
token: "0x...USDC", tokenDecimals: 6,
channelManager: "0x...", houseBond: "0x...",
verifiers: { mux: "0x..." },
rpcUrl: "https://arb1.arbitrum.io/rpc",
});
const limits = await new RainVault(acme).currentLimits(); // trustless: unitCap = float × 1733 ppm, bond/32, liquidity/8
Every address is EIP-55 checksum-validated on load — the repo has had two past checksum bugs, so validation is mandatory, not optional.
▸GAME-BUILDER GUIDE — THE IRulesVerifier CONTRACT
@rain/games), and house-node support.interface IRulesVerifier {
struct ChannelCtx { bytes32 channelId; bytes32 sessionSeed; bytes32 playerChainRoot; bytes32 houseChainRoot; }
struct FinFields { uint96 playerBal; uint96 houseBal; uint96 feeAccrued; uint96 lostGross; uint96 grossAtRisk; uint8 phase; }
function verifyTransition(ChannelCtx calldata ctx, bytes calldata prevGame, bytes calldata nextGame,
uint8 action, bytes32[] calldata reveals)
external view returns (bool valid, FinFields memory prevFin, FinFields memory nextFin);
function finOf(bytes calldata game) external view returns (FinFields memory);
}
- Pure and deterministic. No storage, no oracle, no block data — it's a fraud-proof court, not a game server.
- Randomness only from reveals.
r = keccak256(pRev, hRev, sessionSeed, channelId, k); for engine-driven games seed a deterministic engine withrand commitengineHashon-chain (Engine V2 pattern: 192 BET / 193 SETTLE in the mux). - Bet before randomness. BET dual-signs the wager with
grossAtRisk = stakeand a solvency lock (maxPayout − stake ≤ houseBal); SETTLE consumes exactly one reveal pair. - A legal transition must never be punishable. Differential-fuzz your Solidity against the TS mirror —
proveBadTransitionfalse positives are a critical bug. - Register through the mux. Action ranges: 0–31 blackjack · 32–63 roulette · 64–95 baccarat · 96–127 crash · 128–159 quick games · 160–191 step games · 192–223 Engine V2. GameMuxVerifier9 0xDf214594D021a36bD61aB398c20c4A14cDD0b48e is the live dispatcher on #2; dispatch isolation is tested.
Reality check: setVerifier is owner-gated and the house nodes are foundation-run. Third-party games are the designed path, not yet a permissionless one.
▸HOUSE-NODE OPERATOR PATH
- Bond. Deposit into HouseBond (#1 0x37E41E1d1EE2F96cE0203af06d639448547ade84 · #2 0x3D2d25373836C9d102E83f4200e87d087B29b998). Your bond caps the limits you can offer (table limit ≤ slashable/32). Withdrawals take 7 days and stay slashable while pending.
- Approval. Operator registration is governance-gated in v1 (single foundation-run node; HA/watchtower/HSM out of scope — accepted risks).
- Run the node. Write-ahead persistence before any countersignature, per-hand checkpoints, grace timers, house-reveals-first ordering. Liveness faults cost
max(2× open gross, floor)to the player plus an equal burn — automatically, from your bond.
▸CHANGELOG — v1 → v2
v1 (@rain/risk-markets-sdk, Jul 2026) | v2 (layered, Sep 2026 — playmarket era) |
|---|---|
rain.core — deployment registry | → @rain/channels (registry + ChannelManagerAA / ERC-1271 smart-account open, session key as validation entity, gas sponsorship hooks) |
rain.games — blackjack + roulette ChannelSession | → @rain/channels (ChannelSession.act(gameType, …) — one channel, all games) + @rain/games (13 table engines, dice/quick slots, Engine V2 runtime, Craps, Live Crash, step games) |
| randomness embedded in the channels client | → extracted as @rain/rng-core (pure) + @rain/rng-session (choreography); MIT + attribution; usable without the casino |
rain.predictions — rain-sdk-v2 passthrough | → @rain/markets (+ Outperform pari-mutuel client, CryptoRace v1.1, oracle attestation decoding) |
rain.vaults — limits derivation | → folded into @rain/channels (RainVault.currentLimits(), HouseBond views) |
| Pyth Entropy session seed (ChannelManager V3) | → oracle-free two-party session seed (V4 / AA, since v2.6.0) — SessionSeedCommitReveal event is the anchor |
| wallet popup per session open | → email login via smart accounts on #2: zero popups, zero gas |
| — | + white-label brand layer, wizard, self-serve portal, multi-brand back-office (/partners) |
v2.0 → v2.1 (2026-09-13, “LAB-GRADE DRAWS, WEB2 LATENCY”)
drbg(r, gameId)in@rain/rng-core: one RAIN seed per spin → SP 800-90A HMAC_DRBG/SHA-256 (or ChaCha20) draw layer,intBelowrejection sampling + Fisher–Yatesshuffle; never spans rounds.- Pipelining in
@rain/rng-session(prefetch(),maxInFlight); default chain 65,536 with automatic rotation at 90 %. - New
@rain/rng-node(house counterparty service with KATs, fingerprint check) andrng-py(Python mirror). No on-chain protocol change —outcome/gameSeedbyte-identical to 2.0 and the Arbitrum verifiers. - Lab package
lab/— see the pre-submission package. Full text: CHANGELOG.
Site version banner: v2.8 (RNG package). Both deployments remain play-money and pre-audit.