@moneypot/hub 1.4.0 → 1.4.2
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/README.md +1 -1
- package/dist/src/db/public.d.ts +16 -1
- package/dist/src/db/public.js +38 -0
- package/dist/src/plugins/hub-make-outcome-bet.js +2 -39
- package/dist/src/plugins/hub-put-alert.js +5 -1
- package/dist/src/plugins/listen-with-filter.d.ts +3 -3
- package/dist/src/plugins/listen-with-filter.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/src/db/public.d.ts
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import * as pg from "pg";
|
|
2
|
-
import { DbCurrency, DbSession } from "./types.js";
|
|
2
|
+
import { DbBalance, DbBankroll, DbCurrency, DbSession } from "./types.js";
|
|
3
|
+
import { PgClientInTransaction } from "./index.js";
|
|
3
4
|
export declare function getActiveSessionById(pgClient: pg.PoolClient, sessionId: string): Promise<DbSession | undefined>;
|
|
4
5
|
export declare function getCasinoCurrencyByKey(pgClient: pg.PoolClient, { currencyKey, casinoId }: {
|
|
5
6
|
currencyKey: string;
|
|
6
7
|
casinoId: string;
|
|
7
8
|
}): Promise<DbCurrency | undefined>;
|
|
9
|
+
export declare function dbLockPlayerBalanceAndHouseBankroll(pgClient: PgClientInTransaction, { userId, casinoId, experienceId, currencyKey, }: {
|
|
10
|
+
userId: string;
|
|
11
|
+
casinoId: string;
|
|
12
|
+
experienceId: string;
|
|
13
|
+
currencyKey: string;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
found: false;
|
|
16
|
+
dbPlayerBalance: null;
|
|
17
|
+
dbHouseBankroll: null;
|
|
18
|
+
} | {
|
|
19
|
+
found: true;
|
|
20
|
+
dbPlayerBalance: DbBalance["amount"];
|
|
21
|
+
dbHouseBankroll: DbBankroll["amount"];
|
|
22
|
+
}>;
|
package/dist/src/db/public.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { maybeOneRow } from "./util.js";
|
|
2
|
+
import { assert } from "tsafe";
|
|
2
3
|
export async function getActiveSessionById(pgClient, sessionId) {
|
|
3
4
|
return pgClient
|
|
4
5
|
.query("select * from hub.active_session where id = $1", [
|
|
@@ -18,3 +19,40 @@ export async function getCasinoCurrencyByKey(pgClient, { currencyKey, casinoId }
|
|
|
18
19
|
})
|
|
19
20
|
.then(maybeOneRow);
|
|
20
21
|
}
|
|
22
|
+
export async function dbLockPlayerBalanceAndHouseBankroll(pgClient, { userId, casinoId, experienceId, currencyKey, }) {
|
|
23
|
+
assert(pgClient._inTransaction, "pgClient must be in a transaction");
|
|
24
|
+
const row = await pgClient
|
|
25
|
+
.query(`
|
|
26
|
+
WITH locked_balance AS (
|
|
27
|
+
SELECT amount
|
|
28
|
+
FROM hub.balance
|
|
29
|
+
WHERE user_id = $1
|
|
30
|
+
AND casino_id = $2
|
|
31
|
+
AND experience_id = $3
|
|
32
|
+
AND currency_key = $4
|
|
33
|
+
|
|
34
|
+
FOR UPDATE
|
|
35
|
+
)
|
|
36
|
+
SELECT
|
|
37
|
+
pb.amount as player_balance,
|
|
38
|
+
br.amount as house_bankroll
|
|
39
|
+
FROM locked_balance pb
|
|
40
|
+
JOIN hub.bankroll br
|
|
41
|
+
ON br.casino_id = $2
|
|
42
|
+
AND br.currency_key = $4
|
|
43
|
+
|
|
44
|
+
FOR UPDATE OF br
|
|
45
|
+
`, [userId, casinoId, experienceId, currencyKey])
|
|
46
|
+
.then(maybeOneRow);
|
|
47
|
+
return row
|
|
48
|
+
? {
|
|
49
|
+
found: true,
|
|
50
|
+
dbPlayerBalance: row.player_balance,
|
|
51
|
+
dbHouseBankroll: row.house_bankroll,
|
|
52
|
+
}
|
|
53
|
+
: {
|
|
54
|
+
found: false,
|
|
55
|
+
dbPlayerBalance: null,
|
|
56
|
+
dbHouseBankroll: null,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -2,7 +2,7 @@ import { access, context, object, ObjectStep, polymorphicBranch, sideEffect, } f
|
|
|
2
2
|
import { gql, makeExtendSchemaPlugin } from "postgraphile/utils";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { GraphQLError } from "graphql";
|
|
5
|
-
import { DbHashKind, exactlyOneRow, maybeOneRow, superuserPool, withPgPoolTransaction, } from "../db/index.js";
|
|
5
|
+
import { DbHashKind, dbLockPlayerBalanceAndHouseBankroll, exactlyOneRow, maybeOneRow, superuserPool, withPgPoolTransaction, } from "../db/index.js";
|
|
6
6
|
import { assert } from "tsafe";
|
|
7
7
|
import { dbInsertHubHash, dbLockHubHashChain, } from "../hash-chain/db-hash-chain.js";
|
|
8
8
|
import { getIntermediateHash, getPreimageHash, } from "../hash-chain/get-hash.js";
|
|
@@ -150,7 +150,7 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
150
150
|
throw new GraphQLError("Currency not found");
|
|
151
151
|
}
|
|
152
152
|
return withPgPoolTransaction(superuserPool, async (pgClient) => {
|
|
153
|
-
const { dbPlayerBalance, dbHouseBankroll, found } = await
|
|
153
|
+
const { dbPlayerBalance, dbHouseBankroll, found } = await dbLockPlayerBalanceAndHouseBankroll(pgClient, {
|
|
154
154
|
userId: session.user_id,
|
|
155
155
|
casinoId: session.casino_id,
|
|
156
156
|
experienceId: session.experience_id,
|
|
@@ -409,43 +409,6 @@ function pickRandomOutcome({ outcomes, hash, }) {
|
|
|
409
409
|
outcomeIdx: outcomes.length - 1,
|
|
410
410
|
};
|
|
411
411
|
}
|
|
412
|
-
async function dbLockBalanceAndBankroll(pgClient, { userId, casinoId, experienceId, currencyKey, }) {
|
|
413
|
-
assert(pgClient._inTransaction, "pgClient must be in a transaction");
|
|
414
|
-
const row = await pgClient
|
|
415
|
-
.query(`
|
|
416
|
-
WITH locked_balance AS (
|
|
417
|
-
SELECT amount
|
|
418
|
-
FROM hub.balance
|
|
419
|
-
WHERE user_id = $1
|
|
420
|
-
AND casino_id = $2
|
|
421
|
-
AND experience_id = $3
|
|
422
|
-
AND currency_key = $4
|
|
423
|
-
|
|
424
|
-
FOR UPDATE
|
|
425
|
-
)
|
|
426
|
-
SELECT
|
|
427
|
-
pb.amount as player_balance,
|
|
428
|
-
br.amount as house_bankroll
|
|
429
|
-
FROM locked_balance pb
|
|
430
|
-
JOIN hub.bankroll br
|
|
431
|
-
ON br.casino_id = $2
|
|
432
|
-
AND br.currency_key = $4
|
|
433
|
-
|
|
434
|
-
FOR UPDATE OF br
|
|
435
|
-
`, [userId, casinoId, experienceId, currencyKey])
|
|
436
|
-
.then(maybeOneRow);
|
|
437
|
-
return row
|
|
438
|
-
? {
|
|
439
|
-
found: true,
|
|
440
|
-
dbPlayerBalance: row.player_balance,
|
|
441
|
-
dbHouseBankroll: row.house_bankroll,
|
|
442
|
-
}
|
|
443
|
-
: {
|
|
444
|
-
found: false,
|
|
445
|
-
dbPlayerBalance: null,
|
|
446
|
-
dbHouseBankroll: null,
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
412
|
async function finishHashChainInBackground({ hashChainId, }) {
|
|
450
413
|
console.log("Finishing hash chain in background", { hashChainId });
|
|
451
414
|
const preimageHashResult = await getPreimageHash({
|
|
@@ -28,7 +28,11 @@ export const HubPutAlertPlugin = makeExtendSchemaPlugin(() => {
|
|
|
28
28
|
return "";
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
|
-
return listenWithFilter($pgSubscriber, $channelKey, jsonParse, $identity, (
|
|
31
|
+
return listenWithFilter($pgSubscriber, $channelKey, jsonParse, $identity, (item, identity) => {
|
|
32
|
+
if (typeof item !== "string") {
|
|
33
|
+
console.warn(`hubPutAlert: item is not a string: ${JSON.stringify(item)}`);
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
32
36
|
if (identity?.kind !== "user") {
|
|
33
37
|
return false;
|
|
34
38
|
}
|
|
@@ -5,7 +5,7 @@ export declare class ListenWithFilterStep<TTopics extends {
|
|
|
5
5
|
[topic: string]: any;
|
|
6
6
|
}, TTopic extends keyof TTopics, TPayloadStep extends Step, TFilterInput> extends Step<TTopics[TTopic][]> {
|
|
7
7
|
itemPlan: (itemPlan: __ItemStep<TTopics[TTopic]>) => TPayloadStep;
|
|
8
|
-
filterFn: (
|
|
8
|
+
filterFn: (item: unknown, filterInput: TFilterInput) => boolean;
|
|
9
9
|
static $$export: {
|
|
10
10
|
moduleName: string;
|
|
11
11
|
exportName: string;
|
|
@@ -14,9 +14,9 @@ export declare class ListenWithFilterStep<TTopics extends {
|
|
|
14
14
|
private pubsubDep;
|
|
15
15
|
private topicDep;
|
|
16
16
|
private filterInputDep;
|
|
17
|
-
constructor(pubsubOrPlan: Step<GrafastSubscriber<TTopics> | null> | GrafastSubscriber<TTopics> | null, topicOrPlan: Step<TTopic> | string, itemPlan: ((itemPlan: __ItemStep<TTopics[TTopic]>) => TPayloadStep) | undefined, filterInputPlan: Step<TFilterInput>, filterFn: (
|
|
17
|
+
constructor(pubsubOrPlan: Step<GrafastSubscriber<TTopics> | null> | GrafastSubscriber<TTopics> | null, topicOrPlan: Step<TTopic> | string, itemPlan: ((itemPlan: __ItemStep<TTopics[TTopic]>) => TPayloadStep) | undefined, filterInputPlan: Step<TFilterInput>, filterFn: (item: unknown, filterInput: TFilterInput) => boolean);
|
|
18
18
|
execute({ indexMap, values, stream, }: ExecutionDetails<readonly [GrafastSubscriber<TTopics>, TTopic]>): GrafastResultStreamList<TTopics[TTopic]>;
|
|
19
19
|
}
|
|
20
20
|
export declare function listenWithFilter<TTopics extends {
|
|
21
21
|
[topic: string]: any;
|
|
22
|
-
}, TTopic extends keyof TTopics, TPayloadStep extends Step, TFilterInput>(pubsubOrPlan: Step<GrafastSubscriber<TTopics> | null> | GrafastSubscriber<TTopics> | null, topicOrPlan: Step<TTopic> | string, itemPlan: ((itemPlan: __ItemStep<TTopics[TTopic]>) => TPayloadStep) | undefined, filterInputPlan: Step<TFilterInput>, filterFn: (
|
|
22
|
+
}, TTopic extends keyof TTopics, TPayloadStep extends Step, TFilterInput>(pubsubOrPlan: Step<GrafastSubscriber<TTopics> | null> | GrafastSubscriber<TTopics> | null, topicOrPlan: Step<TTopic> | string, itemPlan: ((itemPlan: __ItemStep<TTopics[TTopic]>) => TPayloadStep) | undefined, filterInputPlan: Step<TFilterInput>, filterFn: (item: unknown, filterInput: TFilterInput) => boolean): ListenWithFilterStep<TTopics, TTopic, TPayloadStep, TFilterInput>;
|
|
@@ -47,7 +47,7 @@ export class ListenWithFilterStep extends Step {
|
|
|
47
47
|
[Symbol.asyncIterator]: async function* () {
|
|
48
48
|
const iterator = await origStream;
|
|
49
49
|
for await (const item of iterator) {
|
|
50
|
-
if (filterFn(
|
|
50
|
+
if (filterFn(item, filterInput)) {
|
|
51
51
|
yield item;
|
|
52
52
|
}
|
|
53
53
|
}
|