@block52/poker-vm-sdk 1.3.1 → 1.3.3
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.
- package/dist/deck.d.ts +30 -0
- package/dist/deck.d.ts.map +1 -1
- package/dist/index.d.ts +32 -0
- package/dist/index.esm.js +96 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -1
- package/dist/types/game.d.ts +2 -0
- package/dist/types/game.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -56053,6 +56053,11 @@ exports.NonPlayerActionType = void 0;
|
|
|
56053
56053
|
NonPlayerActionType["JOIN"] = "join";
|
|
56054
56054
|
NonPlayerActionType["LEAVE"] = "leave";
|
|
56055
56055
|
NonPlayerActionType["NEW_HAND"] = "new-hand";
|
|
56056
|
+
// Entry big blind auto-posted when a post-now joiner activates off the blind
|
|
56057
|
+
// seats (poker-vm#2553). Recorded in ANTE; counted toward the pot + the
|
|
56058
|
+
// player's bet (they're matched) but excluded from the first-to-act /
|
|
56059
|
+
// has-acted scans (it's a non-player action, like DEAD_SMALL_BLIND).
|
|
56060
|
+
NonPlayerActionType["POST"] = "post";
|
|
56056
56061
|
NonPlayerActionType["SIT_IN"] = "sit-in";
|
|
56057
56062
|
// Sit in and wait for the big blind — distinct action from SIT_IN (post now)
|
|
56058
56063
|
// so each has a single responsibility. Sets WAITING_FOR_BIG_BLIND. (#2139)
|
|
@@ -57193,6 +57198,92 @@ class Deck {
|
|
|
57193
57198
|
// Explicitly update hash after shuffling
|
|
57194
57199
|
this.createHash();
|
|
57195
57200
|
}
|
|
57201
|
+
/**
|
|
57202
|
+
* Shuffle deterministically from a 32-byte client entropy seed, byte-for-byte
|
|
57203
|
+
* matching the Cosmos chain so the PVM and the chain derive the SAME deck for
|
|
57204
|
+
* the same seed. This is a faithful port of
|
|
57205
|
+
* `pokerchain/x/poker/types/deck.go:ShuffleFromVRF` (poker-vm#2460): without
|
|
57206
|
+
* it the PVM forks from the chain on a client-seed new-hand (#2418).
|
|
57207
|
+
*
|
|
57208
|
+
* DEPRECATED interim: the client-chosen seed is grindable. Superseded by the
|
|
57209
|
+
* validator-entropy VRF re-hardening tracked in poker-vm#2459.
|
|
57210
|
+
*
|
|
57211
|
+
* @param seedHex 32-byte seed as 64 hex chars (the FE's `seed=` value).
|
|
57212
|
+
*/
|
|
57213
|
+
shuffleFromSeed(seedHex) {
|
|
57214
|
+
const seed = Buffer.from(seedHex, "hex");
|
|
57215
|
+
if (seed.length !== Deck.PLAYER_SEED_LEN) {
|
|
57216
|
+
throw new Error(`player seed must be ${Deck.PLAYER_SEED_LEN} bytes, got ${seed.length}`);
|
|
57217
|
+
}
|
|
57218
|
+
this.seedHash = crypto$1.createHash("sha256").update(seed).digest("hex");
|
|
57219
|
+
// HKDF-SHA256 expand (salt = HashLen zero bytes, info = VRF_INFO),
|
|
57220
|
+
// consumed as an on-demand byte stream — mirrors Go hkdf.New(...).Read.
|
|
57221
|
+
const read = Deck.hkdfExpandReader(seed, Buffer.alloc(32), Buffer.from(Deck.VRF_INFO));
|
|
57222
|
+
// Fisher-Yates with crypto/rand.Int rejection sampling (Go semantics),
|
|
57223
|
+
// so the HKDF stream is consumed identically to the chain.
|
|
57224
|
+
for (let i = this.cards.length - 1; i > 0; i--) {
|
|
57225
|
+
const j = Deck.randInt(read, i + 1);
|
|
57226
|
+
[this.cards[i], this.cards[j]] = [this.cards[j], this.cards[i]];
|
|
57227
|
+
}
|
|
57228
|
+
this.createHash();
|
|
57229
|
+
}
|
|
57230
|
+
/**
|
|
57231
|
+
* Streaming HKDF-Expand (RFC 5869, SHA-256), matching Go
|
|
57232
|
+
* `hkdf.New(sha256.New, ikm, salt, info).Read`:
|
|
57233
|
+
* PRK = HMAC(salt, ikm); output = T(1)||T(2)||…, T(n) = HMAC(PRK, T(n-1)||info||n).
|
|
57234
|
+
* salt is HashLen zero bytes (Go's nil-salt default). Returns a reader that
|
|
57235
|
+
* yields the next `n` stream bytes on each call.
|
|
57236
|
+
*/
|
|
57237
|
+
static hkdfExpandReader(ikm, salt, info) {
|
|
57238
|
+
const prk = crypto$1.createHmac("sha256", salt).update(ikm).digest();
|
|
57239
|
+
let buffer = Buffer.alloc(0);
|
|
57240
|
+
let t = Buffer.alloc(0);
|
|
57241
|
+
let counter = 1;
|
|
57242
|
+
return (n) => {
|
|
57243
|
+
while (buffer.length < n) {
|
|
57244
|
+
if (counter > 255) {
|
|
57245
|
+
throw new Error("HKDF stream exhausted (>255 blocks)");
|
|
57246
|
+
}
|
|
57247
|
+
t = crypto$1.createHmac("sha256", prk)
|
|
57248
|
+
.update(Buffer.concat([t, info, Buffer.from([counter])]))
|
|
57249
|
+
.digest();
|
|
57250
|
+
buffer = Buffer.concat([buffer, t]);
|
|
57251
|
+
counter++;
|
|
57252
|
+
}
|
|
57253
|
+
const out = Buffer.from(buffer.subarray(0, n)); // copy before advancing
|
|
57254
|
+
buffer = buffer.subarray(n);
|
|
57255
|
+
return out;
|
|
57256
|
+
};
|
|
57257
|
+
}
|
|
57258
|
+
/**
|
|
57259
|
+
* Uniform integer in [0, max) by rejection sampling — a port of Go
|
|
57260
|
+
* `crypto/rand.Int`. The byte count, high-byte mask and reject test match
|
|
57261
|
+
* the stdlib exactly so the HKDF byte stream is consumed the same way the
|
|
57262
|
+
* chain consumes it. `max` here is always ≤ 52, so the result fits a number.
|
|
57263
|
+
*/
|
|
57264
|
+
static randInt(read, max) {
|
|
57265
|
+
const nMax = max - 1; // largest valid value; bit length is taken over max-1
|
|
57266
|
+
if (nMax === 0) {
|
|
57267
|
+
return 0; // max === 1: only 0 is valid, no bytes consumed
|
|
57268
|
+
}
|
|
57269
|
+
const bitLen = 32 - Math.clz32(nMax);
|
|
57270
|
+
const k = Math.ceil(bitLen / 8);
|
|
57271
|
+
let b = bitLen % 8;
|
|
57272
|
+
if (b === 0) {
|
|
57273
|
+
b = 8;
|
|
57274
|
+
}
|
|
57275
|
+
for (;;) {
|
|
57276
|
+
const bytes = read(k);
|
|
57277
|
+
bytes[0] &= (1 << b) - 1; // clear high bits of the top byte
|
|
57278
|
+
let n = 0;
|
|
57279
|
+
for (const byte of bytes) {
|
|
57280
|
+
n = n * 256 + byte; // big-endian, matching big.Int.SetBytes
|
|
57281
|
+
}
|
|
57282
|
+
if (n < max) {
|
|
57283
|
+
return n;
|
|
57284
|
+
}
|
|
57285
|
+
}
|
|
57286
|
+
}
|
|
57196
57287
|
getCardMnemonic(suit, rank) {
|
|
57197
57288
|
const rankNum = Number(rank);
|
|
57198
57289
|
const rankStr = Deck.RANK_MAP[rankNum] !== undefined ? Deck.RANK_MAP[rankNum] : rankNum.toString();
|
|
@@ -57319,6 +57410,10 @@ Deck.SUIT_MAP = {
|
|
|
57319
57410
|
[exports.SUIT.HEARTS]: "H",
|
|
57320
57411
|
[exports.SUIT.SPADES]: "S"
|
|
57321
57412
|
};
|
|
57413
|
+
// Matches pokerchain types.PlayerSeedLen and VRFInputPrefix — the two sides
|
|
57414
|
+
// MUST agree on these or the derived decks diverge.
|
|
57415
|
+
Deck.PLAYER_SEED_LEN = 32;
|
|
57416
|
+
Deck.VRF_INFO = "poker/deck/v1";
|
|
57322
57417
|
|
|
57323
57418
|
/**
|
|
57324
57419
|
* The community board for a Texas Hold'em hand.
|