@block52/poker-vm-sdk 1.6.0 → 1.8.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.
- package/dist/index.d.ts +28 -3
- package/dist/index.esm.js +89 -8
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +89 -8
- package/dist/index.js.map +1 -1
- package/dist/pokerSolver.d.ts +15 -3
- package/dist/pokerSolver.d.ts.map +1 -1
- package/dist/pokerchain.poker.v1/types/pokerchain/poker/v1/tx.d.ts +8 -0
- package/dist/pokerchain.poker.v1/types/pokerchain/poker/v1/tx.d.ts.map +1 -1
- package/dist/signingClient.d.ts +7 -0
- package/dist/signingClient.d.ts.map +1 -1
- package/dist/types/game.d.ts +5 -1
- package/dist/types/game.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -44952,6 +44952,14 @@ interface MsgCreateGame {
|
|
|
44952
44952
|
* (block52/pokerchain#407)
|
|
44953
44953
|
*/
|
|
44954
44954
|
bettingLimit: string;
|
|
44955
|
+
/**
|
|
44956
|
+
* Scheduled start for a sit-and-go, unix seconds (field 21). With it,
|
|
44957
|
+
* min_players may be below max_players: the tournament starts when the table
|
|
44958
|
+
* fills or at this time with at least min_players registered, and is
|
|
44959
|
+
* cancelled with refunds if fewer have registered 15 minutes after it.
|
|
44960
|
+
* 0 = unscheduled: starts only when full. (poker-vm#2680)
|
|
44961
|
+
*/
|
|
44962
|
+
startTime: Long;
|
|
44955
44963
|
}
|
|
44956
44964
|
declare const MsgCreateGame: MessageFns<MsgCreateGame>;
|
|
44957
44965
|
/** MsgJoinGame defines the MsgJoinGame message. */
|
|
@@ -45249,7 +45257,8 @@ declare enum NonPlayerActionType {
|
|
|
45249
45257
|
SIT_OUT = "sit-out",
|
|
45250
45258
|
TIMEOUT = "timeout",
|
|
45251
45259
|
TIME_BANK = "time-bank",
|
|
45252
|
-
TOP_UP = "top-up"
|
|
45260
|
+
TOP_UP = "top-up",
|
|
45261
|
+
START = "start"
|
|
45253
45262
|
}
|
|
45254
45263
|
declare const AllPlayerActions: {
|
|
45255
45264
|
DEAD_SMALL_BLIND: NonPlayerActionType.DEAD_SMALL_BLIND;
|
|
@@ -45265,6 +45274,7 @@ declare const AllPlayerActions: {
|
|
|
45265
45274
|
TIMEOUT: NonPlayerActionType.TIMEOUT;
|
|
45266
45275
|
TIME_BANK: NonPlayerActionType.TIME_BANK;
|
|
45267
45276
|
TOP_UP: NonPlayerActionType.TOP_UP;
|
|
45277
|
+
START: NonPlayerActionType.START;
|
|
45268
45278
|
SMALL_BLIND: PlayerActionType.SMALL_BLIND;
|
|
45269
45279
|
BIG_BLIND: PlayerActionType.BIG_BLIND;
|
|
45270
45280
|
FOLD: PlayerActionType.FOLD;
|
|
@@ -45364,6 +45374,7 @@ type GameOptions = {
|
|
|
45364
45374
|
protocolFeeBps?: number;
|
|
45365
45375
|
blindLevelDuration?: number;
|
|
45366
45376
|
blindLevel?: number;
|
|
45377
|
+
scheduledStartTime?: number;
|
|
45367
45378
|
sngStartTime?: number;
|
|
45368
45379
|
levelStartTime?: number;
|
|
45369
45380
|
timeBankMs?: number;
|
|
@@ -45399,6 +45410,7 @@ type GameOptionsDTO = {
|
|
|
45399
45410
|
blindLevel?: number;
|
|
45400
45411
|
nextSmallBlind?: string;
|
|
45401
45412
|
nextBigBlind?: string;
|
|
45413
|
+
scheduledStartTime?: number;
|
|
45402
45414
|
sngStartTime?: number;
|
|
45403
45415
|
levelStartTime?: number;
|
|
45404
45416
|
timeBankMs?: number;
|
|
@@ -46073,6 +46085,16 @@ declare class PokerSolver {
|
|
|
46073
46085
|
* Find the best 5-card hand from 7 cards
|
|
46074
46086
|
*/
|
|
46075
46087
|
static findBestHand(cards: Card[]): HandEvaluation;
|
|
46088
|
+
/**
|
|
46089
|
+
* Find the best Omaha hand: EXACTLY 2 of the 4 hole cards and EXACTLY 3 of
|
|
46090
|
+
* the 5 board cards — C(4,2) x C(5,3) = 60 candidates, ranked like Hold'em.
|
|
46091
|
+
* Mirrors the engine's FindBestOmahaHand (poker-vm#2650).
|
|
46092
|
+
*/
|
|
46093
|
+
static findBestOmahaHand(holeCards: Card[], communityCards: Card[]): HandEvaluation;
|
|
46094
|
+
/**
|
|
46095
|
+
* Best hand for a variant from hole cards and a full 5-card board.
|
|
46096
|
+
*/
|
|
46097
|
+
private static bestHandForVariant;
|
|
46076
46098
|
/**
|
|
46077
46099
|
* Evaluate a hand with any number of cards (2-7)
|
|
46078
46100
|
* This is useful for showing hand strength during all betting rounds
|
|
@@ -46154,12 +46176,14 @@ declare class PokerSolver {
|
|
|
46154
46176
|
static calculateWinPercentages(handA: Card[], handB: Card[], communityCards?: Card[], simulations?: number): [number, number, number];
|
|
46155
46177
|
/**
|
|
46156
46178
|
* Calculate win percentages for multiple players (2+) using Monte Carlo simulation
|
|
46157
|
-
* @param hands Array of hole cards for each player (each
|
|
46179
|
+
* @param hands Array of hole cards for each player (2 each for Hold'em, 4 for Omaha)
|
|
46158
46180
|
* @param communityCards Current community cards (0-5 cards)
|
|
46159
46181
|
* @param simulations Number of simulations to run (default: 10000)
|
|
46182
|
+
* @param variant The table's variant; omitted = Texas Hold'em. Omaha hands are
|
|
46183
|
+
* scored with the two-plus-three rule (ui#769).
|
|
46160
46184
|
* @returns Object containing win percentages for each player and overall tie percentage
|
|
46161
46185
|
*/
|
|
46162
|
-
static calculateMultiPlayerEquity(hands: Card[][], communityCards?: Card[], simulations?: number): {
|
|
46186
|
+
static calculateMultiPlayerEquity(hands: Card[][], communityCards?: Card[], simulations?: number, variant?: GameVariant): {
|
|
46163
46187
|
winPercentages: number[];
|
|
46164
46188
|
tiePercentage: number;
|
|
46165
46189
|
};
|
|
@@ -46609,6 +46633,7 @@ interface SNGConfig {
|
|
|
46609
46633
|
startingStack: bigint;
|
|
46610
46634
|
blindLevelDuration: number;
|
|
46611
46635
|
entryFee?: bigint;
|
|
46636
|
+
startTime?: number;
|
|
46612
46637
|
}
|
|
46613
46638
|
/**
|
|
46614
46639
|
* Signing Cosmos Client that extends the read-only CosmosClient with transaction capabilities
|
package/dist/index.esm.js
CHANGED
|
@@ -2846,6 +2846,7 @@ function createBaseMsgCreateGame() {
|
|
|
2846
2846
|
entryFee: Long.UZERO,
|
|
2847
2847
|
name: "",
|
|
2848
2848
|
bettingLimit: "",
|
|
2849
|
+
startTime: Long.ZERO,
|
|
2849
2850
|
};
|
|
2850
2851
|
}
|
|
2851
2852
|
const MsgCreateGame = {
|
|
@@ -2907,6 +2908,9 @@ const MsgCreateGame = {
|
|
|
2907
2908
|
if (message.bettingLimit !== "") {
|
|
2908
2909
|
writer.uint32(162).string(message.bettingLimit);
|
|
2909
2910
|
}
|
|
2911
|
+
if (!message.startTime.equals(Long.ZERO)) {
|
|
2912
|
+
writer.uint32(168).int64(message.startTime.toString());
|
|
2913
|
+
}
|
|
2910
2914
|
return writer;
|
|
2911
2915
|
},
|
|
2912
2916
|
decode(input, length) {
|
|
@@ -3049,6 +3053,13 @@ const MsgCreateGame = {
|
|
|
3049
3053
|
message.bettingLimit = reader.string();
|
|
3050
3054
|
continue;
|
|
3051
3055
|
}
|
|
3056
|
+
case 21: {
|
|
3057
|
+
if (tag !== 168) {
|
|
3058
|
+
break;
|
|
3059
|
+
}
|
|
3060
|
+
message.startTime = Long.fromString(reader.int64().toString());
|
|
3061
|
+
continue;
|
|
3062
|
+
}
|
|
3052
3063
|
}
|
|
3053
3064
|
if ((tag & 7) === 4 || tag === 0) {
|
|
3054
3065
|
break;
|
|
@@ -3078,6 +3089,7 @@ const MsgCreateGame = {
|
|
|
3078
3089
|
entryFee: isSet$2b(object.entryFee) ? Long.fromValue(object.entryFee) : Long.UZERO,
|
|
3079
3090
|
name: isSet$2b(object.name) ? globalThis.String(object.name) : "",
|
|
3080
3091
|
bettingLimit: isSet$2b(object.bettingLimit) ? globalThis.String(object.bettingLimit) : "",
|
|
3092
|
+
startTime: isSet$2b(object.startTime) ? Long.fromValue(object.startTime) : Long.ZERO,
|
|
3081
3093
|
};
|
|
3082
3094
|
},
|
|
3083
3095
|
toJSON(message) {
|
|
@@ -3139,6 +3151,9 @@ const MsgCreateGame = {
|
|
|
3139
3151
|
if (message.bettingLimit !== "") {
|
|
3140
3152
|
obj.bettingLimit = message.bettingLimit;
|
|
3141
3153
|
}
|
|
3154
|
+
if (!message.startTime.equals(Long.ZERO)) {
|
|
3155
|
+
obj.startTime = (message.startTime || Long.ZERO).toString();
|
|
3156
|
+
}
|
|
3142
3157
|
return obj;
|
|
3143
3158
|
},
|
|
3144
3159
|
create(base) {
|
|
@@ -3184,6 +3199,9 @@ const MsgCreateGame = {
|
|
|
3184
3199
|
message.gameVariant = object.gameVariant ?? "";
|
|
3185
3200
|
message.name = object.name ?? "";
|
|
3186
3201
|
message.bettingLimit = object.bettingLimit ?? "";
|
|
3202
|
+
message.startTime = (object.startTime !== undefined && object.startTime !== null)
|
|
3203
|
+
? Long.fromValue(object.startTime)
|
|
3204
|
+
: Long.ZERO;
|
|
3187
3205
|
message.entryFee = (object.entryFee !== undefined && object.entryFee !== null)
|
|
3188
3206
|
? Long.fromValue(object.entryFee)
|
|
3189
3207
|
: Long.UZERO;
|
|
@@ -56091,6 +56109,10 @@ var NonPlayerActionType;
|
|
|
56091
56109
|
// current turn. Rejected off-turn, past the deadline, or with no bank left.
|
|
56092
56110
|
NonPlayerActionType["TIME_BANK"] = "time-bank";
|
|
56093
56111
|
NonPlayerActionType["TOP_UP"] = "top-up";
|
|
56112
|
+
// Scheduled single-table tournament (poker-vm#2680): any registered player
|
|
56113
|
+
// starts the sit-and-go once gameOptions.scheduledStartTime has passed and
|
|
56114
|
+
// at least minPlayers are seated. Offered in legalActions when it is due.
|
|
56115
|
+
NonPlayerActionType["START"] = "start";
|
|
56094
56116
|
})(NonPlayerActionType || (NonPlayerActionType = {}));
|
|
56095
56117
|
const AllPlayerActions = { ...PlayerActionType, ...NonPlayerActionType };
|
|
56096
56118
|
/**
|
|
@@ -56772,6 +56794,41 @@ class PokerSolver {
|
|
|
56772
56794
|
}
|
|
56773
56795
|
return bestHand;
|
|
56774
56796
|
}
|
|
56797
|
+
/**
|
|
56798
|
+
* Find the best Omaha hand: EXACTLY 2 of the 4 hole cards and EXACTLY 3 of
|
|
56799
|
+
* the 5 board cards — C(4,2) x C(5,3) = 60 candidates, ranked like Hold'em.
|
|
56800
|
+
* Mirrors the engine's FindBestOmahaHand (poker-vm#2650).
|
|
56801
|
+
*/
|
|
56802
|
+
static findBestOmahaHand(holeCards, communityCards) {
|
|
56803
|
+
if (holeCards.length !== 4) {
|
|
56804
|
+
throw new Error("Omaha requires exactly 4 hole cards");
|
|
56805
|
+
}
|
|
56806
|
+
if (communityCards.length !== 5) {
|
|
56807
|
+
throw new Error("Omaha requires exactly 5 community cards");
|
|
56808
|
+
}
|
|
56809
|
+
let bestHand = null;
|
|
56810
|
+
for (const pair of this.getCombinationsFlexible(holeCards, 2)) {
|
|
56811
|
+
for (const triple of this.getCombinationsFlexible(communityCards, 3)) {
|
|
56812
|
+
const evaluation = this.evaluateHand([...pair, ...triple]);
|
|
56813
|
+
if (!bestHand || this.compareHands(evaluation, bestHand) > 0) {
|
|
56814
|
+
bestHand = evaluation;
|
|
56815
|
+
}
|
|
56816
|
+
}
|
|
56817
|
+
}
|
|
56818
|
+
if (!bestHand) {
|
|
56819
|
+
throw new Error("Failed to evaluate hand");
|
|
56820
|
+
}
|
|
56821
|
+
return bestHand;
|
|
56822
|
+
}
|
|
56823
|
+
/**
|
|
56824
|
+
* Best hand for a variant from hole cards and a full 5-card board.
|
|
56825
|
+
*/
|
|
56826
|
+
static bestHandForVariant(variant, holeCards, communityCards) {
|
|
56827
|
+
if (variant === GameVariant.OMAHA) {
|
|
56828
|
+
return this.findBestOmahaHand(holeCards, communityCards);
|
|
56829
|
+
}
|
|
56830
|
+
return this.findBestHand([...holeCards, ...communityCards]);
|
|
56831
|
+
}
|
|
56775
56832
|
/**
|
|
56776
56833
|
* Evaluate a hand with any number of cards (2-7)
|
|
56777
56834
|
* This is useful for showing hand strength during all betting rounds
|
|
@@ -57166,12 +57223,14 @@ class PokerSolver {
|
|
|
57166
57223
|
}
|
|
57167
57224
|
/**
|
|
57168
57225
|
* Calculate win percentages for multiple players (2+) using Monte Carlo simulation
|
|
57169
|
-
* @param hands Array of hole cards for each player (each
|
|
57226
|
+
* @param hands Array of hole cards for each player (2 each for Hold'em, 4 for Omaha)
|
|
57170
57227
|
* @param communityCards Current community cards (0-5 cards)
|
|
57171
57228
|
* @param simulations Number of simulations to run (default: 10000)
|
|
57229
|
+
* @param variant The table's variant; omitted = Texas Hold'em. Omaha hands are
|
|
57230
|
+
* scored with the two-plus-three rule (ui#769).
|
|
57172
57231
|
* @returns Object containing win percentages for each player and overall tie percentage
|
|
57173
57232
|
*/
|
|
57174
|
-
static calculateMultiPlayerEquity(hands, communityCards = [], simulations = 10000) {
|
|
57233
|
+
static calculateMultiPlayerEquity(hands, communityCards = [], simulations = 10000, variant) {
|
|
57175
57234
|
// Validate inputs
|
|
57176
57235
|
if (hands.length < 2) {
|
|
57177
57236
|
throw new Error("Need at least 2 hands to calculate equity");
|
|
@@ -57179,9 +57238,10 @@ class PokerSolver {
|
|
|
57179
57238
|
if (hands.length > 10) {
|
|
57180
57239
|
throw new Error("Maximum 10 hands supported");
|
|
57181
57240
|
}
|
|
57241
|
+
const holeCount = holeCardsPerPlayer(variant);
|
|
57182
57242
|
for (let i = 0; i < hands.length; i++) {
|
|
57183
|
-
if (hands[i].length !==
|
|
57184
|
-
throw new Error(`Hand ${i} must have exactly
|
|
57243
|
+
if (hands[i].length !== holeCount) {
|
|
57244
|
+
throw new Error(`Hand ${i} must have exactly ${holeCount} cards`);
|
|
57185
57245
|
}
|
|
57186
57246
|
}
|
|
57187
57247
|
if (communityCards.length > 5) {
|
|
@@ -57208,10 +57268,7 @@ class PokerSolver {
|
|
|
57208
57268
|
// Deal remaining community cards
|
|
57209
57269
|
const fullCommunityCards = [...communityCards, ...shuffledDeck.slice(0, cardsNeeded)];
|
|
57210
57270
|
// Evaluate all hands
|
|
57211
|
-
const evaluations = hands.map(hand =>
|
|
57212
|
-
const fullHand = [...hand, ...fullCommunityCards];
|
|
57213
|
-
return this.findBestHand(fullHand);
|
|
57214
|
-
});
|
|
57271
|
+
const evaluations = hands.map(hand => this.bestHandForVariant(variant, hand, fullCommunityCards));
|
|
57215
57272
|
// Find winners using existing findWinners method
|
|
57216
57273
|
const winnerIndices = this.findWinners(evaluations);
|
|
57217
57274
|
// Update win counters
|
|
@@ -70969,6 +71026,26 @@ function gaslessFee(gasLimit = DEFAULT_GAS_LIMIT) {
|
|
|
70969
71026
|
gas: gasLimit.toString()
|
|
70970
71027
|
};
|
|
70971
71028
|
}
|
|
71029
|
+
/**
|
|
71030
|
+
* Fail fast on a sit-and-go field the chain would refuse (poker-vm#2680):
|
|
71031
|
+
* seats 2..9, min <= max, and a flexible field (min < max) needs a scheduled
|
|
71032
|
+
* start in the future. Mirrors x/poker/keeper/msg_server_create_game.go.
|
|
71033
|
+
*/
|
|
71034
|
+
function assertCreatableSngField(minPlayers, maxPlayers, sngConfig, nowSeconds = Math.floor(Date.now() / 1000)) {
|
|
71035
|
+
if (maxPlayers < 2 || maxPlayers > 9) {
|
|
71036
|
+
throw new Error(`sit-and-go maxPlayers must be 2..9; got ${maxPlayers}.`);
|
|
71037
|
+
}
|
|
71038
|
+
if (minPlayers < 2 || minPlayers > maxPlayers) {
|
|
71039
|
+
throw new Error(`sit-and-go minPlayers must be 2..maxPlayers (${maxPlayers}); got ${minPlayers}.`);
|
|
71040
|
+
}
|
|
71041
|
+
const startTime = sngConfig?.startTime;
|
|
71042
|
+
if (minPlayers !== maxPlayers && !startTime) {
|
|
71043
|
+
throw new Error("sit-and-go with minPlayers < maxPlayers needs sngConfig.startTime (a scheduled start).");
|
|
71044
|
+
}
|
|
71045
|
+
if (startTime !== undefined && startTime <= nowSeconds) {
|
|
71046
|
+
throw new Error(`sngConfig.startTime ${startTime} must be in the future (now ${nowSeconds}).`);
|
|
71047
|
+
}
|
|
71048
|
+
}
|
|
70972
71049
|
/**
|
|
70973
71050
|
* Signing Cosmos Client that extends the read-only CosmosClient with transaction capabilities
|
|
70974
71051
|
*/
|
|
@@ -71100,6 +71177,7 @@ class SigningCosmosClient extends CosmosClient {
|
|
|
71100
71177
|
if (!sngConfig.blindLevelDuration || sngConfig.blindLevelDuration <= 0) {
|
|
71101
71178
|
throw new Error(`${gameFormat} games require a positive blindLevelDuration; got ${sngConfig.blindLevelDuration}.`);
|
|
71102
71179
|
}
|
|
71180
|
+
assertCreatableSngField(minPlayers, maxPlayers, sngConfig);
|
|
71103
71181
|
}
|
|
71104
71182
|
assertCreatableBettingLimit(bettingLimit);
|
|
71105
71183
|
await this.initializeSigningClient();
|
|
@@ -71137,6 +71215,9 @@ class SigningCosmosClient extends CosmosClient {
|
|
|
71137
71215
|
// Betting structure (block52/pokerchain#407). "" = the variant's default
|
|
71138
71216
|
// on chain, and an empty proto3 string is not encoded at all.
|
|
71139
71217
|
bettingLimit: bettingLimit ?? "",
|
|
71218
|
+
// Scheduled start (poker-vm#2680), unix seconds. 0 = unscheduled, and
|
|
71219
|
+
// a zero proto3 int64 is not encoded at all.
|
|
71220
|
+
startTime: sngConfig?.startTime ? Long.fromNumber(sngConfig.startTime) : Long.ZERO,
|
|
71140
71221
|
});
|
|
71141
71222
|
// Create the transaction message
|
|
71142
71223
|
const msg = {
|