@moneypot/hub 1.16.0-dev.3 → 1.16.0-dev.4
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/src/db/public.d.ts
CHANGED
|
@@ -5,17 +5,13 @@ export declare function dbGetCasinoCurrencyByKey(pgClient: QueryExecutor, { curr
|
|
|
5
5
|
currencyKey: string;
|
|
6
6
|
casinoId: string;
|
|
7
7
|
}): Promise<DbCurrency | undefined>;
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function dbLockPlayerBalance(pgClient: PgClientInTransaction, { userId, casinoId, experienceId, currencyKey, }: {
|
|
9
9
|
userId: string;
|
|
10
10
|
casinoId: string;
|
|
11
11
|
experienceId: string;
|
|
12
12
|
currencyKey: string;
|
|
13
|
-
}): Promise<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} |
|
|
18
|
-
found: true;
|
|
19
|
-
dbPlayerBalance: Pick<DbBalance, "id" | "amount">;
|
|
20
|
-
dbHouseBankroll: Pick<DbBankroll, "id" | "amount">;
|
|
21
|
-
}>;
|
|
13
|
+
}): Promise<Pick<DbBalance, "id" | "amount"> | null>;
|
|
14
|
+
export declare function dbLockHouseBankroll(pgClient: PgClientInTransaction, { casinoId, currencyKey }: {
|
|
15
|
+
casinoId: string;
|
|
16
|
+
currencyKey: string;
|
|
17
|
+
}): Promise<Pick<DbBankroll, "id" | "amount"> | null>;
|
package/dist/src/db/public.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { maybeOneRow } from "./util.js";
|
|
2
|
-
import { assert } from "tsafe";
|
|
3
2
|
export async function dbGetActiveSessionById(pgClient, sessionId) {
|
|
4
3
|
return pgClient
|
|
5
4
|
.query(`
|
|
@@ -19,40 +18,29 @@ export async function dbGetCasinoCurrencyByKey(pgClient, { currencyKey, casinoId
|
|
|
19
18
|
`, [currencyKey, casinoId])
|
|
20
19
|
.then(maybeOneRow);
|
|
21
20
|
}
|
|
22
|
-
export async function
|
|
23
|
-
|
|
24
|
-
const row = await pgClient
|
|
21
|
+
export async function dbLockPlayerBalance(pgClient, { userId, casinoId, experienceId, currencyKey, }) {
|
|
22
|
+
return pgClient
|
|
25
23
|
.query(`
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
`, [
|
|
46
|
-
.then(maybeOneRow)
|
|
47
|
-
|
|
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
|
-
};
|
|
24
|
+
SELECT *
|
|
25
|
+
FROM hub.balance
|
|
26
|
+
WHERE user_id = $1
|
|
27
|
+
AND casino_id = $2
|
|
28
|
+
AND experience_id = $3
|
|
29
|
+
AND currency_key = $4
|
|
30
|
+
FOR UPDATE
|
|
31
|
+
`, [userId, casinoId, experienceId, currencyKey])
|
|
32
|
+
.then(maybeOneRow)
|
|
33
|
+
.then((row) => row ?? null);
|
|
34
|
+
}
|
|
35
|
+
export async function dbLockHouseBankroll(pgClient, { casinoId, currencyKey }) {
|
|
36
|
+
return pgClient
|
|
37
|
+
.query(`
|
|
38
|
+
SELECT *
|
|
39
|
+
FROM hub.bankroll
|
|
40
|
+
WHERE casino_id = $1
|
|
41
|
+
AND currency_key = $2
|
|
42
|
+
FOR UPDATE
|
|
43
|
+
`, [casinoId, currencyKey])
|
|
44
|
+
.then(maybeOneRow)
|
|
45
|
+
.then((row) => row ?? null);
|
|
58
46
|
}
|
|
@@ -127,36 +127,35 @@ export const HubAuthenticatePlugin = extendSchema(() => {
|
|
|
127
127
|
const mpExperience = result.experience;
|
|
128
128
|
assert(mpExperience);
|
|
129
129
|
assert(mpExperience.userByUserId, "Expected mpExperience.userByUserId");
|
|
130
|
-
const
|
|
130
|
+
const authUser = await pgClient
|
|
131
131
|
.query({
|
|
132
132
|
text: `
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
133
|
+
INSERT INTO hub.user(casino_id, mp_user_id, uname)
|
|
134
|
+
VALUES ($1, $2, $3)
|
|
135
|
+
ON CONFLICT (casino_id, mp_user_id) DO UPDATE
|
|
136
|
+
SET uname = EXCLUDED.uname
|
|
137
|
+
RETURNING id, uname
|
|
138
|
+
`,
|
|
139
|
+
values: [casino.id, mpUserId, uname],
|
|
140
|
+
})
|
|
141
|
+
.then(exactlyOneRow);
|
|
142
|
+
const ownerUser = await pgClient
|
|
143
|
+
.query({
|
|
144
|
+
text: `
|
|
145
|
+
INSERT INTO hub.user(casino_id, mp_user_id, uname)
|
|
146
|
+
VALUES ($1, $2, $3)
|
|
147
|
+
ON CONFLICT (casino_id, mp_user_id) DO UPDATE
|
|
148
|
+
SET uname = EXCLUDED.uname
|
|
149
|
+
RETURNING id
|
|
149
150
|
`,
|
|
150
151
|
values: [
|
|
151
152
|
casino.id,
|
|
152
|
-
mpUserId,
|
|
153
|
-
uname,
|
|
154
153
|
mpExperience.userByUserId.id,
|
|
155
154
|
mpExperience.userByUserId.uname,
|
|
156
155
|
],
|
|
157
156
|
})
|
|
158
157
|
.then(exactlyOneRow);
|
|
159
|
-
const userId =
|
|
158
|
+
const userId = authUser.id;
|
|
160
159
|
const dbExperience = await pgClient
|
|
161
160
|
.query({
|
|
162
161
|
text: `
|
|
@@ -170,7 +169,7 @@ export const HubAuthenticatePlugin = extendSchema(() => {
|
|
|
170
169
|
casino.id,
|
|
171
170
|
mpExperience.id,
|
|
172
171
|
mpExperience.name,
|
|
173
|
-
|
|
172
|
+
ownerUser.id,
|
|
174
173
|
],
|
|
175
174
|
})
|
|
176
175
|
.then(exactlyOneRow);
|
|
@@ -191,7 +190,7 @@ export const HubAuthenticatePlugin = extendSchema(() => {
|
|
|
191
190
|
.then(exactlyOneRow);
|
|
192
191
|
const ret = {
|
|
193
192
|
userId,
|
|
194
|
-
uname:
|
|
193
|
+
uname: authUser.uname,
|
|
195
194
|
experienceId: dbExperience.id,
|
|
196
195
|
sessionKey: dbSession.key,
|
|
197
196
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { access, context, object, ObjectStep, sideEffect, } from "postgraphile/grafast";
|
|
2
|
-
import { gql,
|
|
2
|
+
import { gql, extendSchema } from "postgraphile/utils";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { GraphQLError } from "graphql";
|
|
5
|
-
import { DbHashKind,
|
|
5
|
+
import { DbHashKind, dbLockHouseBankroll, dbLockPlayerBalance, exactlyOneRow, maybeOneRow, 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 } from "../hash-chain/get-hash.js";
|
|
@@ -71,7 +71,7 @@ const BetConfigsSchema = z.record(BetKindSchema, z.object({
|
|
|
71
71
|
export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
72
72
|
BetConfigsSchema.parse(betConfigs);
|
|
73
73
|
const betKinds = Object.keys(betConfigs);
|
|
74
|
-
return
|
|
74
|
+
return extendSchema((build) => {
|
|
75
75
|
const outcomeBetTable = build.input.pgRegistry.pgResources.hub_outcome_bet;
|
|
76
76
|
const typeDefs = gql `
|
|
77
77
|
enum BetKind {
|
|
@@ -171,14 +171,14 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
171
171
|
throw new GraphQLError("Currency not found");
|
|
172
172
|
}
|
|
173
173
|
return withPgPoolTransaction(superuserPool, async (pgClient) => {
|
|
174
|
-
const
|
|
174
|
+
const dbPlayerBalance = await dbLockPlayerBalance(pgClient, {
|
|
175
175
|
userId: session.user_id,
|
|
176
176
|
casinoId: session.casino_id,
|
|
177
177
|
experienceId: session.experience_id,
|
|
178
178
|
currencyKey: dbCurrency.key,
|
|
179
179
|
});
|
|
180
|
-
if (!
|
|
181
|
-
throw new GraphQLError("No balance entry found for player
|
|
180
|
+
if (!dbPlayerBalance) {
|
|
181
|
+
throw new GraphQLError("No balance entry found for player");
|
|
182
182
|
}
|
|
183
183
|
const minProfit = Math.min(...input.outcomes.map((o) => o.profit));
|
|
184
184
|
const maxPlayerLoss = Math.abs(input.wager * minProfit);
|
|
@@ -194,21 +194,6 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
194
194
|
}
|
|
195
195
|
throw new GraphQLError("You cannot afford the worst outcome");
|
|
196
196
|
}
|
|
197
|
-
const maxProfitMultiplier = Math.max(...input.outcomes.map((o) => o.profit));
|
|
198
|
-
const maxPotentialPayout = input.wager * maxProfitMultiplier;
|
|
199
|
-
const riskResult = validateRisk({
|
|
200
|
-
currency: input.currency,
|
|
201
|
-
wager: input.wager,
|
|
202
|
-
bankroll: dbHouseBankroll.amount,
|
|
203
|
-
maxPotentialPayout,
|
|
204
|
-
riskPolicy: betConfig.riskPolicy,
|
|
205
|
-
displayUnitName: dbCurrency.display_unit_name,
|
|
206
|
-
displayUnitScale: dbCurrency.display_unit_scale,
|
|
207
|
-
outcomes: input.outcomes,
|
|
208
|
-
});
|
|
209
|
-
if (!riskResult.ok) {
|
|
210
|
-
throw new GraphQLError(riskResult.error);
|
|
211
|
-
}
|
|
212
197
|
const dbHashChain = await dbLockHubHashChain(pgClient, {
|
|
213
198
|
userId: session.user_id,
|
|
214
199
|
experienceId: session.experience_id,
|
|
@@ -289,26 +274,47 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
289
274
|
const outcome = input.outcomes[outcomeIdx];
|
|
290
275
|
const netPlayerAmount = input.wager * outcome.profit;
|
|
291
276
|
const houseBankrollDelta = -netPlayerAmount;
|
|
292
|
-
await pgClient
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
SET amount = amount + $1
|
|
296
|
-
WHERE id = $2
|
|
297
|
-
`,
|
|
298
|
-
values: [netPlayerAmount, dbPlayerBalance.id],
|
|
277
|
+
const dbHouseBankroll = await dbLockHouseBankroll(pgClient, {
|
|
278
|
+
casinoId: session.casino_id,
|
|
279
|
+
currencyKey: dbCurrency.key,
|
|
299
280
|
});
|
|
281
|
+
if (!dbHouseBankroll) {
|
|
282
|
+
throw new GraphQLError("No house bankroll found");
|
|
283
|
+
}
|
|
284
|
+
const maxProfitMultiplier = Math.max(...input.outcomes.map((o) => o.profit));
|
|
285
|
+
const maxPotentialPayout = input.wager * maxProfitMultiplier;
|
|
286
|
+
const riskResult = validateRisk({
|
|
287
|
+
currency: input.currency,
|
|
288
|
+
wager: input.wager,
|
|
289
|
+
bankroll: dbHouseBankroll.amount,
|
|
290
|
+
maxPotentialPayout,
|
|
291
|
+
riskPolicy: betConfig.riskPolicy,
|
|
292
|
+
displayUnitName: dbCurrency.display_unit_name,
|
|
293
|
+
displayUnitScale: dbCurrency.display_unit_scale,
|
|
294
|
+
outcomes: input.outcomes,
|
|
295
|
+
});
|
|
296
|
+
if (!riskResult.ok) {
|
|
297
|
+
throw new GraphQLError(riskResult.error);
|
|
298
|
+
}
|
|
300
299
|
await pgClient.query({
|
|
301
300
|
text: `
|
|
301
|
+
WITH balance_update AS (
|
|
302
|
+
UPDATE hub.balance
|
|
303
|
+
SET amount = amount + $1
|
|
304
|
+
WHERE id = $2
|
|
305
|
+
)
|
|
302
306
|
UPDATE hub.bankroll
|
|
303
|
-
SET amount = amount + $
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
WHERE id = $
|
|
307
|
+
SET amount = amount + $3,
|
|
308
|
+
wagered = wagered + $4,
|
|
309
|
+
bets = bets + 1
|
|
310
|
+
WHERE id = $5
|
|
307
311
|
`,
|
|
308
312
|
values: [
|
|
309
|
-
|
|
313
|
+
netPlayerAmount,
|
|
314
|
+
dbPlayerBalance.id,
|
|
310
315
|
houseBankrollDelta,
|
|
311
316
|
input.wager,
|
|
317
|
+
dbHouseBankroll.id,
|
|
312
318
|
],
|
|
313
319
|
});
|
|
314
320
|
const immutableData = structuredClone({
|