@moneypot/hub 1.4.4 → 1.4.5

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.
@@ -119,7 +119,6 @@ export type DbHashChain = {
119
119
  user_id: string;
120
120
  experience_id: string;
121
121
  casino_id: string;
122
- client_seed: string;
123
122
  max_iterations: number;
124
123
  current_iteration: number;
125
124
  active: boolean;
@@ -1,47 +1,31 @@
1
1
  import { context, object, sideEffect } from "@moneypot/hub/grafast";
2
2
  import { gql, makeExtendSchemaPlugin } from "@moneypot/hub/graphile";
3
3
  import { GraphQLError } from "graphql";
4
- import { z } from "zod";
5
4
  import { PgAdvisoryLock } from "../../pg-advisory-lock.js";
6
5
  import { exactlyOneRow, superuserPool, withPgPoolTransaction, } from "@moneypot/hub/db";
7
6
  import * as HashCommon from "../get-hash.js";
8
7
  import { DbHashKind } from "../../db/types.js";
9
8
  import * as config from "../../config.js";
10
- const InputSchema = z.object({
11
- clientSeed: z.string(),
12
- });
13
9
  export const HubCreateHashChainPlugin = makeExtendSchemaPlugin((build) => {
14
10
  const hashChainTable = build.input.pgRegistry.pgResources.hub_hash_chain;
15
11
  return {
16
12
  typeDefs: gql `
17
- input HubCreateHashChainInput {
18
- clientSeed: String!
19
- }
20
-
21
13
  type HubCreateHashChainPayload {
22
14
  hashChain: HubHashChain!
23
15
  }
24
16
 
25
17
  extend type Mutation {
26
- hubCreateHashChain(
27
- input: HubCreateHashChainInput!
28
- ): HubCreateHashChainPayload!
18
+ hubCreateHashChain: HubCreateHashChainPayload!
29
19
  }
30
20
  `,
31
21
  plans: {
32
22
  Mutation: {
33
- hubCreateHashChain: (_, { $input }) => {
23
+ hubCreateHashChain: () => {
34
24
  const $identity = context().get("identity");
35
- const $hashChainId = sideEffect([$input, $identity], ([rawInput, identity]) => {
25
+ const $hashChainId = sideEffect([$identity], ([identity]) => {
36
26
  if (identity?.kind !== "user") {
37
27
  throw new GraphQLError("Unauthorized");
38
28
  }
39
- const result = InputSchema.safeParse(rawInput);
40
- if (!result.success) {
41
- const message = result.error.errors[0].message;
42
- throw new GraphQLError(message);
43
- }
44
- const { clientSeed } = result.data;
45
29
  return withPgPoolTransaction(superuserPool, async (pgClient) => {
46
30
  await PgAdvisoryLock.forNewHashChain(pgClient, {
47
31
  userId: identity.session.user_id,
@@ -66,18 +50,16 @@ export const HubCreateHashChainPlugin = makeExtendSchemaPlugin((build) => {
66
50
  user_id,
67
51
  experience_id,
68
52
  casino_id,
69
- client_seed,
70
53
  active,
71
54
  max_iteration,
72
55
  current_iteration
73
56
  )
74
- VALUES ($1, $2, $3, $4, true, $5, $5)
57
+ VALUES ($1, $2, $3, true, $4, $4)
75
58
  RETURNING *
76
59
  `, [
77
60
  identity.session.user_id,
78
61
  identity.session.experience_id,
79
62
  identity.session.casino_id,
80
- clientSeed,
81
63
  config.HASHCHAINSERVER_MAX_ITERATIONS,
82
64
  ])
83
65
  .then(exactlyOneRow);
@@ -0,0 +1,9 @@
1
+ alter table hub.outcome_bet add column client_seed text;
2
+
3
+ update hub.outcome_bet
4
+ set client_seed = hash_chain.client_seed
5
+ from hub.hash_chain where outcome_bet.hash_chain_id = hash_chain.id;
6
+
7
+ alter table hub.outcome_bet alter column client_seed set not null;
8
+
9
+ alter table hub.hash_chain drop column client_seed;
@@ -12,6 +12,7 @@ declare const OutcomeSchema: z.ZodObject<{
12
12
  }>;
13
13
  declare const InputSchema: z.ZodObject<{
14
14
  kind: z.ZodString;
15
+ clientSeed: z.ZodString;
15
16
  wager: z.ZodNumber;
16
17
  currency: z.ZodString;
17
18
  outcomes: z.ZodEffects<z.ZodEffects<z.ZodArray<z.ZodObject<{
@@ -42,6 +43,7 @@ declare const InputSchema: z.ZodObject<{
42
43
  currency: string;
43
44
  hashChainId: string;
44
45
  kind: string;
46
+ clientSeed: string;
45
47
  wager: number;
46
48
  outcomes: {
47
49
  profit: number;
@@ -52,6 +54,7 @@ declare const InputSchema: z.ZodObject<{
52
54
  currency: string;
53
55
  hashChainId: string;
54
56
  kind: string;
57
+ clientSeed: string;
55
58
  wager: number;
56
59
  outcomes: {
57
60
  profit: number;
@@ -69,11 +72,12 @@ type FinalizeMetadataData = {
69
72
  hash: Uint8Array;
70
73
  outcomes: Outcome[];
71
74
  outcomeIdx: number;
75
+ roll: number;
72
76
  };
73
77
  export type OutcomeBetConfig = {
74
78
  houseEdge: number;
75
79
  saveOutcomes: boolean;
76
- allowLossBeyondWager: boolean;
80
+ allowLossBeyondWager?: boolean;
77
81
  initializeMetadataFromUntrustedUserInput?: (input: Input) => Result<Metadata, string>;
78
82
  finalizeMetadata?: (validatedMetadata: Metadata, data: FinalizeMetadataData) => Metadata;
79
83
  };
@@ -27,6 +27,7 @@ const OutcomeSchema = z
27
27
  const InputSchema = z
28
28
  .object({
29
29
  kind: z.string(),
30
+ clientSeed: z.string(),
30
31
  wager: z
31
32
  .number()
32
33
  .int("Wager must be an integer")
@@ -53,7 +54,7 @@ const BetConfigsSchema = z.record(BetKindSchema, z.object({
53
54
  .gte(0, "House edge must be >= 0")
54
55
  .lte(1, "House edge must be <= 1"),
55
56
  saveOutcomes: z.boolean(),
56
- allowLossBeyondWager: z.boolean().optional().default(false),
57
+ allowLossBeyondWager: z.boolean().default(false),
57
58
  initializeMetadataFromUntrustedUserInput: z
58
59
  .function()
59
60
  .optional(),
@@ -77,6 +78,7 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
77
78
  currency: String!
78
79
  outcomes: [HubOutcomeInput!]!
79
80
  hashChainId: UUID!
81
+ clientSeed: String!
80
82
  metadata: JSON
81
83
  }
82
84
 
@@ -246,13 +248,13 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
246
248
  }
247
249
  const finalHash = (() => {
248
250
  const serverHash = betHashResult.hash;
249
- const clientSeed = dbHashChain.client_seed;
251
+ const clientSeed = input.clientSeed;
250
252
  const finalHash = createHmac("sha256", serverHash)
251
253
  .update(clientSeed)
252
254
  .digest();
253
255
  return finalHash;
254
256
  })();
255
- const { outcome, outcomeIdx } = pickRandomOutcome({
257
+ const { outcome, outcomeIdx, roll } = pickRandomOutcome({
256
258
  outcomes: input.outcomes,
257
259
  hash: finalHash,
258
260
  });
@@ -293,10 +295,11 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
293
295
  const immutableData = structuredClone({
294
296
  wager: input.wager,
295
297
  currencyKey: dbCurrency.key,
296
- clientSeed: dbHashChain.client_seed,
298
+ clientSeed: input.clientSeed,
297
299
  hash: betHashResult.hash,
298
300
  outcomes: input.outcomes,
299
301
  outcomeIdx,
302
+ roll,
300
303
  });
301
304
  const finalizedMetadata = betConfig.finalizeMetadata
302
305
  ? betConfig.finalizeMetadata(initializedMetadata, immutableData)
@@ -310,6 +313,7 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
310
313
  user_id: session.user_id,
311
314
  casino_id: session.casino_id,
312
315
  experience_id: session.experience_id,
316
+ client_seed: input.clientSeed,
313
317
  metadata: finalizedMetadata || {},
314
318
  ...(betConfig.saveOutcomes
315
319
  ? {
@@ -335,9 +339,10 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
335
339
  profit,
336
340
  outcomes,
337
341
  outcome_idx,
342
+ client_seed,
338
343
  metadata
339
344
  )
340
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
345
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
341
346
  RETURNING id
342
347
  `,
343
348
  values: [
@@ -351,6 +356,7 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
351
356
  newBet.profit,
352
357
  newBet.outcomes.map((o) => `(${o.weight},${o.profit})`),
353
358
  newBet.outcome_idx,
359
+ newBet.client_seed,
354
360
  newBet.metadata,
355
361
  ],
356
362
  })
@@ -402,18 +408,19 @@ function pickRandomOutcome({ outcomes, hash, }) {
402
408
  }));
403
409
  const totalProb = outcomesWithProbability.reduce((sum, outcome) => sum + outcome.probability, 0);
404
410
  assert(Math.abs(totalProb - 1.0) < FLOAT_EPSILON, "Probabilities must sum to ~1");
405
- const randomValue = normalizeHash(hash);
411
+ const roll = normalizeHash(hash);
406
412
  let cumulativeProb = 0;
407
413
  for (let i = 0; i < outcomesWithProbability.length; i++) {
408
414
  const outcome = outcomesWithProbability[i];
409
415
  cumulativeProb += outcome.probability;
410
- if (randomValue <= cumulativeProb) {
411
- return { outcome, outcomeIdx: i };
416
+ if (roll <= cumulativeProb) {
417
+ return { outcome, outcomeIdx: i, roll };
412
418
  }
413
419
  }
414
420
  return {
415
421
  outcome: outcomes[outcomes.length - 1],
416
422
  outcomeIdx: outcomes.length - 1,
423
+ roll,
417
424
  };
418
425
  }
419
426
  async function finishHashChainInBackground({ hashChainId, }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moneypot/hub",
3
- "version": "1.4.4",
3
+ "version": "1.4.5",
4
4
  "author": "moneypot.com",
5
5
  "homepage": "https://moneypot.com/hub",
6
6
  "keywords": [