@moneypot/hub 1.11.0 → 1.12.0-dev.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 +8 -2
- package/dist/src/audit-log.d.ts +33 -0
- package/dist/src/audit-log.js +47 -0
- package/dist/src/db/index.js +37 -13
- package/dist/src/pg-versions/011-audit-log.sql +95 -0
- package/dist/src/plugins/hub-make-outcome-bet.js +26 -18
- package/dist/src/server/graphile.config.js +0 -4
- package/dist/src/take-request/process-take-request.d.ts +1 -1
- package/dist/src/take-request/process-take-request.js +25 -2
- package/package.json +3 -2
- package/dist/src/plugins/hub-claim-faucet.d.ts +0 -1
- package/dist/src/plugins/hub-claim-faucet.js +0 -93
package/README.md
CHANGED
|
@@ -76,10 +76,16 @@ insert into hub.api_key default values returning key;
|
|
|
76
76
|
|
|
77
77
|
## Changelog
|
|
78
78
|
|
|
79
|
-
### 1.
|
|
79
|
+
### 1.12.x
|
|
80
|
+
|
|
81
|
+
- Added `hub.audit_log` table to track balance and bankroll changes.
|
|
82
|
+
- Read more: <https://docs.moneypot.com/hub/balance-audit>
|
|
83
|
+
- Removed built-in hub faucet and old withdraw system.
|
|
84
|
+
|
|
85
|
+
### 1.11.x
|
|
80
86
|
|
|
81
87
|
- Migrated database-related "globals" into a `ServerContext` object.
|
|
82
|
-
- Changed `configureApp(app: ExpressServer)` to `configureApp(args: { app: ExpressServer,
|
|
88
|
+
- Changed `configureApp(app: ExpressServer)` to `configureApp(args: { app: ExpressServer, superuserPool: pg.Pool })`
|
|
83
89
|
- In a postgraphile plugin, you can access the superuser database pool via `const $superuserPool = context().get("superuserPool");`
|
|
84
90
|
|
|
85
91
|
### 1.9.x
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DbBalance, DbBankroll } from "./db/types.js";
|
|
2
|
+
import { QueryExecutor } from "./db/util.js";
|
|
3
|
+
export type AuditLogType = "player-balance" | "house-bankroll" | "both";
|
|
4
|
+
export type HubAuditAction = "hub:init" | "hub:deposit" | "hub:take_request:pending" | "hub:take_request:refund" | "hub:outcome_bet";
|
|
5
|
+
export type HubAuditRefType = "hub.deposit" | "hub.outcome_bet" | "hub.take_request";
|
|
6
|
+
export type AuditAction = HubAuditAction | (string & {});
|
|
7
|
+
export type AuditRefType = HubAuditRefType | (string & {});
|
|
8
|
+
export type BaseAudit = {
|
|
9
|
+
action: AuditAction;
|
|
10
|
+
metadata?: Record<string, unknown> | null;
|
|
11
|
+
} & ({
|
|
12
|
+
refType: AuditRefType;
|
|
13
|
+
refId: string;
|
|
14
|
+
} | {
|
|
15
|
+
refType?: null;
|
|
16
|
+
refId?: null;
|
|
17
|
+
});
|
|
18
|
+
export type NewBalanceAudit = {
|
|
19
|
+
balanceId: DbBalance["id"];
|
|
20
|
+
balanceOld: DbBalance["amount"];
|
|
21
|
+
balanceNew: DbBalance["amount"];
|
|
22
|
+
balanceDelta: DbBalance["amount"];
|
|
23
|
+
};
|
|
24
|
+
export type NewBankrollAudit = {
|
|
25
|
+
bankrollId: DbBankroll["id"];
|
|
26
|
+
bankrollOld: DbBankroll["amount"];
|
|
27
|
+
bankrollNew: DbBankroll["amount"];
|
|
28
|
+
bankrollDelta: DbBankroll["amount"];
|
|
29
|
+
};
|
|
30
|
+
export type NewBothAudit = NewBalanceAudit & NewBankrollAudit;
|
|
31
|
+
export declare function insertAuditLog(pgClient: QueryExecutor, type: "player-balance", audit: NewBalanceAudit & BaseAudit): Promise<void>;
|
|
32
|
+
export declare function insertAuditLog(pgClient: QueryExecutor, type: "house-bankroll", audit: NewBankrollAudit & BaseAudit): Promise<void>;
|
|
33
|
+
export declare function insertAuditLog(pgClient: QueryExecutor, type: "both", audit: NewBothAudit & BaseAudit): Promise<void>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { logger } from "./logger.js";
|
|
2
|
+
export async function insertAuditLog(pgClient, type, audit) {
|
|
3
|
+
await pgClient.query(`
|
|
4
|
+
INSERT INTO hub.audit_log (
|
|
5
|
+
balance_id,
|
|
6
|
+
bankroll_id,
|
|
7
|
+
|
|
8
|
+
balance_old,
|
|
9
|
+
balance_new,
|
|
10
|
+
balance_delta,
|
|
11
|
+
|
|
12
|
+
bankroll_old,
|
|
13
|
+
bankroll_new,
|
|
14
|
+
bankroll_delta,
|
|
15
|
+
|
|
16
|
+
action,
|
|
17
|
+
metadata,
|
|
18
|
+
|
|
19
|
+
ref_type,
|
|
20
|
+
ref_id
|
|
21
|
+
)
|
|
22
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
|
23
|
+
`, buildAuditParams(type, audit));
|
|
24
|
+
logger.info({ ...audit }, "audit log inserted");
|
|
25
|
+
}
|
|
26
|
+
function buildAuditParams(type, audit) {
|
|
27
|
+
const balance = type === "player-balance" || type === "both"
|
|
28
|
+
? audit
|
|
29
|
+
: null;
|
|
30
|
+
const bankroll = type === "house-bankroll" || type === "both"
|
|
31
|
+
? audit
|
|
32
|
+
: null;
|
|
33
|
+
return [
|
|
34
|
+
balance?.balanceId ?? null,
|
|
35
|
+
bankroll?.bankrollId ?? null,
|
|
36
|
+
balance?.balanceOld ?? null,
|
|
37
|
+
balance?.balanceNew ?? null,
|
|
38
|
+
balance?.balanceDelta ?? null,
|
|
39
|
+
bankroll?.bankrollOld ?? null,
|
|
40
|
+
bankroll?.bankrollNew ?? null,
|
|
41
|
+
bankroll?.bankrollDelta ?? null,
|
|
42
|
+
audit.action,
|
|
43
|
+
audit.metadata,
|
|
44
|
+
audit.refType ?? null,
|
|
45
|
+
audit.refId ?? null,
|
|
46
|
+
];
|
|
47
|
+
}
|
package/dist/src/db/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { exactlyOneRow, maybeOneRow } from "./util.js";
|
|
|
4
4
|
import { logger } from "../logger.js";
|
|
5
5
|
import { setTimeout } from "node:timers/promises";
|
|
6
6
|
import { assert } from "tsafe";
|
|
7
|
+
import { insertAuditLog } from "../audit-log.js";
|
|
7
8
|
export * from "../hash-chain/db-hash-chain.js";
|
|
8
9
|
export * from "./types.js";
|
|
9
10
|
export * from "./public.js";
|
|
@@ -172,28 +173,51 @@ export async function insertDeposit(pool, o) {
|
|
|
172
173
|
throw new UserFriendlyError("amount must be positive");
|
|
173
174
|
}
|
|
174
175
|
return withPgPoolTransaction(pool, async (client) => {
|
|
175
|
-
|
|
176
|
+
let dbDeposit;
|
|
177
|
+
try {
|
|
178
|
+
dbDeposit = await client
|
|
179
|
+
.query(`
|
|
176
180
|
INSERT INTO hub.deposit(casino_id, mp_transfer_id, user_id, experience_id, amount, currency_key)
|
|
177
181
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
178
|
-
ON CONFLICT (casino_id, mp_transfer_id) DO NOTHING
|
|
179
182
|
RETURNING id
|
|
180
183
|
`, [
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return null;
|
|
184
|
+
o.casinoId,
|
|
185
|
+
o.mpTransferId,
|
|
186
|
+
o.userId,
|
|
187
|
+
o.experienceId,
|
|
188
|
+
o.amount,
|
|
189
|
+
o.currency,
|
|
190
|
+
])
|
|
191
|
+
.then(exactlyOneRow);
|
|
190
192
|
}
|
|
191
|
-
|
|
193
|
+
catch (e) {
|
|
194
|
+
if (e instanceof pg.DatabaseError && e.code === "23505") {
|
|
195
|
+
if (e.constraint === "deposit_casino_id_mp_transfer_id_key") {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
logger.error(e, `Unexpected dupe violation constraint. Expected "deposit_casino_id_mp_transfer_id_key" but got ${e.constraint}`);
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
throw e;
|
|
202
|
+
}
|
|
203
|
+
const dbBalance = await client
|
|
204
|
+
.query(`
|
|
192
205
|
insert into hub.balance(casino_id, user_id, experience_id, currency_key, amount)
|
|
193
206
|
values ($1, $2, $3, $4, $5)
|
|
194
207
|
on conflict (casino_id, user_id, experience_id, currency_key) do update
|
|
195
208
|
set amount = balance.amount + excluded.amount
|
|
196
|
-
|
|
209
|
+
returning id, amount
|
|
210
|
+
`, [o.casinoId, o.userId, o.experienceId, o.currency, o.amount])
|
|
211
|
+
.then(exactlyOneRow);
|
|
212
|
+
await insertAuditLog(client, "player-balance", {
|
|
213
|
+
balanceId: dbBalance.id,
|
|
214
|
+
balanceOld: dbBalance.amount - o.amount,
|
|
215
|
+
balanceNew: dbBalance.amount,
|
|
216
|
+
balanceDelta: o.amount,
|
|
217
|
+
action: "hub:deposit",
|
|
218
|
+
refType: "hub.deposit",
|
|
219
|
+
refId: dbDeposit.id,
|
|
220
|
+
});
|
|
197
221
|
});
|
|
198
222
|
}
|
|
199
223
|
export async function processWithdrawal(pgClient, { casinoId, mpTransferId, userId, experienceId, amount, currency, status, }) {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
create table hub.audit_log (
|
|
2
|
+
id uuid primary key default hub_hidden.uuid_generate_v7(),
|
|
3
|
+
|
|
4
|
+
balance_id uuid null references hub.balance(id),
|
|
5
|
+
bankroll_id uuid null references hub.bankroll(id),
|
|
6
|
+
|
|
7
|
+
-- how much?
|
|
8
|
+
-- we require all three fields to force callsite to assert its assumptions and
|
|
9
|
+
-- catch potential desync between assumption and data
|
|
10
|
+
balance_old float null,
|
|
11
|
+
balance_new float null,
|
|
12
|
+
balance_delta float null,
|
|
13
|
+
|
|
14
|
+
bankroll_old float null,
|
|
15
|
+
bankroll_new float null,
|
|
16
|
+
bankroll_delta float null,
|
|
17
|
+
|
|
18
|
+
-- what happened?
|
|
19
|
+
action text not null, -- hub:init, hub:deposit, hub:take_request:pending, hub:take_request:refund, hub:outcome_bet, etc.
|
|
20
|
+
metadata jsonb null,
|
|
21
|
+
|
|
22
|
+
-- link to the item that caused the change, i.e. deposit, payout, send, take, etc.
|
|
23
|
+
ref_type text null,
|
|
24
|
+
ref_id text null, -- not a uuid since users might use it for their own non-uuid ids
|
|
25
|
+
|
|
26
|
+
-- Ensure we have at least one type of change
|
|
27
|
+
check (
|
|
28
|
+
(balance_delta is not null) or
|
|
29
|
+
(bankroll_delta is not null)
|
|
30
|
+
),
|
|
31
|
+
-- Ensure old/new/delta are all present or all null
|
|
32
|
+
check (
|
|
33
|
+
(balance_old is null) = (balance_new is null) AND
|
|
34
|
+
(balance_old is null) = (balance_delta is null)
|
|
35
|
+
),
|
|
36
|
+
check (
|
|
37
|
+
(bankroll_old is null) = (bankroll_new is null) AND
|
|
38
|
+
(bankroll_old is null) = (bankroll_delta is null)
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
create index on hub.audit_log(balance_id) where balance_id is not null;
|
|
43
|
+
create index on hub.audit_log(bankroll_id) where bankroll_id is not null;
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
-- seed audit_log with current balances
|
|
48
|
+
insert into hub.audit_log (
|
|
49
|
+
bankroll_id,
|
|
50
|
+
bankroll_old,
|
|
51
|
+
bankroll_new,
|
|
52
|
+
bankroll_delta,
|
|
53
|
+
action
|
|
54
|
+
)
|
|
55
|
+
select
|
|
56
|
+
b.id,
|
|
57
|
+
b.amount,
|
|
58
|
+
b.amount,
|
|
59
|
+
0,
|
|
60
|
+
'hub:init'
|
|
61
|
+
from hub.bankroll b;
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
-- seed audit_log with current balances
|
|
65
|
+
insert into hub.audit_log (
|
|
66
|
+
balance_id,
|
|
67
|
+
balance_old,
|
|
68
|
+
balance_new,
|
|
69
|
+
balance_delta,
|
|
70
|
+
action
|
|
71
|
+
)
|
|
72
|
+
select
|
|
73
|
+
b.id,
|
|
74
|
+
b.amount,
|
|
75
|
+
b.amount,
|
|
76
|
+
0,
|
|
77
|
+
'hub:init'
|
|
78
|
+
from hub.balance b
|
|
79
|
+
join hub.user u on u.id = b.user_id
|
|
80
|
+
;
|
|
81
|
+
|
|
82
|
+
-- This view adds convenience fields that can be derived from the row data.
|
|
83
|
+
create view hub.audit_log_view as
|
|
84
|
+
select
|
|
85
|
+
al.*,
|
|
86
|
+
coalesce(b.currency_key, br.currency_key) as currency_key,
|
|
87
|
+
b.user_id,
|
|
88
|
+
u.uname,
|
|
89
|
+
u.mp_user_id,
|
|
90
|
+
coalesce(b.casino_id, br.casino_id) as casino_id,
|
|
91
|
+
b.experience_id
|
|
92
|
+
from hub.audit_log al
|
|
93
|
+
left join hub.balance b on b.id = al.balance_id
|
|
94
|
+
left join hub.user u on u.id = b.user_id
|
|
95
|
+
left join hub.bankroll br on br.id = al.bankroll_id;
|
|
@@ -9,6 +9,7 @@ import { getIntermediateHash, getPreimageHash, } from "../hash-chain/get-hash.js
|
|
|
9
9
|
import { makeFinalHash, pickRandomOutcome } from "../hash-chain/util.js";
|
|
10
10
|
import { logger } from "../logger.js";
|
|
11
11
|
import { validateRisk } from "../risk-policy.js";
|
|
12
|
+
import { insertAuditLog } from "../audit-log.js";
|
|
12
13
|
const FLOAT_EPSILON = 1e-10;
|
|
13
14
|
function sum(ns) {
|
|
14
15
|
return ns.reduce((a, b) => a + b, 0);
|
|
@@ -272,36 +273,26 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
272
273
|
}, FLOAT_EPSILON);
|
|
273
274
|
const outcome = input.outcomes[outcomeIdx];
|
|
274
275
|
const netPlayerAmount = input.wager * outcome.profit;
|
|
276
|
+
const houseBankrollDelta = -netPlayerAmount;
|
|
275
277
|
await pgClient.query({
|
|
276
278
|
text: `
|
|
277
279
|
UPDATE hub.balance
|
|
278
280
|
SET amount = amount + $1
|
|
279
|
-
WHERE
|
|
280
|
-
AND casino_id = $3
|
|
281
|
-
AND experience_id = $4
|
|
282
|
-
AND currency_key = $5
|
|
281
|
+
WHERE id = $2
|
|
283
282
|
`,
|
|
284
|
-
values: [
|
|
285
|
-
netPlayerAmount,
|
|
286
|
-
session.user_id,
|
|
287
|
-
session.casino_id,
|
|
288
|
-
session.experience_id,
|
|
289
|
-
dbCurrency.key,
|
|
290
|
-
],
|
|
283
|
+
values: [netPlayerAmount, dbPlayerBalance.id],
|
|
291
284
|
});
|
|
292
285
|
await pgClient.query({
|
|
293
286
|
text: `
|
|
294
287
|
UPDATE hub.bankroll
|
|
295
|
-
SET amount = amount
|
|
288
|
+
SET amount = amount + $2,
|
|
296
289
|
bets = bets + 1,
|
|
297
|
-
wagered = wagered + $
|
|
298
|
-
WHERE
|
|
299
|
-
AND casino_id = $3
|
|
290
|
+
wagered = wagered + $3
|
|
291
|
+
WHERE id = $1
|
|
300
292
|
`,
|
|
301
293
|
values: [
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
session.casino_id,
|
|
294
|
+
dbHouseBankroll.id,
|
|
295
|
+
houseBankrollDelta,
|
|
305
296
|
input.wager,
|
|
306
297
|
],
|
|
307
298
|
});
|
|
@@ -371,6 +362,23 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
371
362
|
],
|
|
372
363
|
})
|
|
373
364
|
.then(exactlyOneRow);
|
|
365
|
+
await insertAuditLog(pgClient, "both", {
|
|
366
|
+
balanceId: dbPlayerBalance.id,
|
|
367
|
+
balanceOld: dbPlayerBalance.amount,
|
|
368
|
+
balanceNew: dbPlayerBalance.amount + netPlayerAmount,
|
|
369
|
+
balanceDelta: netPlayerAmount,
|
|
370
|
+
bankrollId: dbHouseBankroll.id,
|
|
371
|
+
bankrollOld: dbHouseBankroll.amount,
|
|
372
|
+
bankrollNew: dbHouseBankroll.amount + houseBankrollDelta,
|
|
373
|
+
bankrollDelta: houseBankrollDelta,
|
|
374
|
+
action: "hub:outcome_bet",
|
|
375
|
+
refType: "hub.outcome_bet",
|
|
376
|
+
refId: bet.id,
|
|
377
|
+
metadata: {
|
|
378
|
+
wager: input.wager,
|
|
379
|
+
profit: outcome.profit,
|
|
380
|
+
},
|
|
381
|
+
});
|
|
374
382
|
return {
|
|
375
383
|
__typename: "HubMakeOutcomeBetSuccess",
|
|
376
384
|
betId: bet.id,
|
|
@@ -8,9 +8,7 @@ import * as db from "../db/index.js";
|
|
|
8
8
|
import { SmartTagsPlugin } from "../smart-tags.js";
|
|
9
9
|
import { HubAuthenticatePlugin } from "../plugins/hub-authenticate.js";
|
|
10
10
|
import { IdToNodeIdPlugin } from "../plugins/id-to-node-id.js";
|
|
11
|
-
import { HubClaimFaucetPlugin } from "../plugins/hub-claim-faucet.js";
|
|
12
11
|
import { DebugPlugin } from "../plugins/debug.js";
|
|
13
|
-
import { HubWithdrawPlugin } from "../plugins/hub-withdraw.js";
|
|
14
12
|
import { HubPrefixPlugin } from "../plugins/hub-schema-prefix.js";
|
|
15
13
|
import { isUuid } from "../util.js";
|
|
16
14
|
import { HubUserBalanceByCurrencyPlugin } from "../plugins/hub-user-balance-by-currency.js";
|
|
@@ -31,7 +29,6 @@ export const requiredPlugins = [
|
|
|
31
29
|
HubPrefixPlugin,
|
|
32
30
|
HubAuthenticatePlugin,
|
|
33
31
|
HubCurrentXPlugin,
|
|
34
|
-
HubWithdrawPlugin,
|
|
35
32
|
HubBalanceAlertPlugin,
|
|
36
33
|
HubPutAlertPlugin,
|
|
37
34
|
HubUserBalanceByCurrencyPlugin,
|
|
@@ -45,7 +42,6 @@ export const defaultPlugins = [
|
|
|
45
42
|
HubBadHashChainErrorPlugin,
|
|
46
43
|
HubCreateHashChainPlugin,
|
|
47
44
|
HubUserActiveHashChainPlugin,
|
|
48
|
-
HubClaimFaucetPlugin,
|
|
49
45
|
customPgOmitArchivedPlugin("deleted"),
|
|
50
46
|
];
|
|
51
47
|
export function createPreset({ plugins, exportSchemaSDLPath, extraPgSchemas, abortSignal, context, }) {
|
|
@@ -16,7 +16,7 @@ export declare function processSingleTakeRequest({ mpTakeRequestId, mpTakeReques
|
|
|
16
16
|
casinoId: string;
|
|
17
17
|
graphqlClient: GraphQLClient;
|
|
18
18
|
pool: pg.Pool;
|
|
19
|
-
}): Promise<string | null>;
|
|
19
|
+
}): Promise<string | null | undefined>;
|
|
20
20
|
export declare function completeTransfer({ mpTakeRequestId, takeRequestId, mpTransferId, graphqlClient, casinoId, pool, }: {
|
|
21
21
|
mpTakeRequestId: string;
|
|
22
22
|
takeRequestId: string;
|
|
@@ -5,6 +5,7 @@ import { assert } from "tsafe";
|
|
|
5
5
|
import { PgAdvisoryLock } from "../pg-advisory-lock.js";
|
|
6
6
|
import { useFragment } from "../__generated__/fragment-masking.js";
|
|
7
7
|
import { logger } from "../logger.js";
|
|
8
|
+
import { insertAuditLog } from "../audit-log.js";
|
|
8
9
|
export const MP_TAKE_REQUEST_FIELDS = gql(`
|
|
9
10
|
fragment MpTakeRequestFields on TakeRequest {
|
|
10
11
|
id
|
|
@@ -305,7 +306,16 @@ async function createAndProcessNewTakeRequest({ pgClient, mpTakeRequest, casinoI
|
|
|
305
306
|
`,
|
|
306
307
|
values: [LocalTakeRequestStatus.PROCESSING, newTakeRequest.id],
|
|
307
308
|
});
|
|
308
|
-
|
|
309
|
+
await insertAuditLog(pgClient, "player-balance", {
|
|
310
|
+
balanceId: dbBalance.id,
|
|
311
|
+
balanceOld: dbBalance.amount,
|
|
312
|
+
balanceNew: dbBalance.amount - amountToTransfer,
|
|
313
|
+
balanceDelta: -amountToTransfer,
|
|
314
|
+
action: "hub:take_request:pending",
|
|
315
|
+
refType: "hub.take_request",
|
|
316
|
+
refId: newTakeRequest.id,
|
|
317
|
+
});
|
|
318
|
+
await attemptTransfer({
|
|
309
319
|
pgClient,
|
|
310
320
|
takeRequestId: newTakeRequest.id,
|
|
311
321
|
mpTakeRequestId: mpTakeRequest.id,
|
|
@@ -582,7 +592,8 @@ export async function completeTransfer({ mpTakeRequestId, takeRequestId, mpTrans
|
|
|
582
592
|
logger.warn({ mpTransferId, takeRequestId }, `[completeTransfer] Transfer was already refunded. This should never happen.`);
|
|
583
593
|
break;
|
|
584
594
|
}
|
|
585
|
-
await pgClient
|
|
595
|
+
const dbBalanceAfterUpdate = await pgClient
|
|
596
|
+
.query({
|
|
586
597
|
text: `
|
|
587
598
|
UPDATE hub.balance
|
|
588
599
|
SET amount = amount + $1
|
|
@@ -590,6 +601,8 @@ export async function completeTransfer({ mpTakeRequestId, takeRequestId, mpTrans
|
|
|
590
601
|
AND experience_id = $3
|
|
591
602
|
AND casino_id = $4
|
|
592
603
|
AND currency_key = $5
|
|
604
|
+
|
|
605
|
+
RETURNING id, amount
|
|
593
606
|
`,
|
|
594
607
|
values: [
|
|
595
608
|
takeRequestData.reserved_amount,
|
|
@@ -598,6 +611,16 @@ export async function completeTransfer({ mpTakeRequestId, takeRequestId, mpTrans
|
|
|
598
611
|
takeRequestData.casino_id,
|
|
599
612
|
takeRequestData.currency_key,
|
|
600
613
|
],
|
|
614
|
+
})
|
|
615
|
+
.then(exactlyOneRow);
|
|
616
|
+
await insertAuditLog(pgClient, "player-balance", {
|
|
617
|
+
balanceId: dbBalanceAfterUpdate.id,
|
|
618
|
+
balanceOld: dbBalanceAfterUpdate.amount - takeRequestData.reserved_amount,
|
|
619
|
+
balanceNew: dbBalanceAfterUpdate.amount,
|
|
620
|
+
balanceDelta: takeRequestData.reserved_amount,
|
|
621
|
+
action: "hub:take_request:refund",
|
|
622
|
+
refType: "hub.take_request",
|
|
623
|
+
refId: takeRequestId,
|
|
601
624
|
});
|
|
602
625
|
await pgClient.query({
|
|
603
626
|
text: `
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moneypot/hub",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0-dev.2",
|
|
4
4
|
"author": "moneypot.com",
|
|
5
5
|
"homepage": "https://moneypot.com/hub",
|
|
6
6
|
"keywords": [
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"./express": "./dist/src/express.js",
|
|
23
23
|
"./dataplan/pg": "./dist/src/dataplan/pg.js",
|
|
24
24
|
"./hash-chain": "./dist/src/hash-chain/index.js",
|
|
25
|
-
"./logger": "./dist/src/logger.js"
|
|
25
|
+
"./logger": "./dist/src/logger.js",
|
|
26
|
+
"./audit-log": "./dist/src/audit-log.js"
|
|
26
27
|
},
|
|
27
28
|
"files": [
|
|
28
29
|
"/dist"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const HubClaimFaucetPlugin: GraphileConfig.Plugin;
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { object } from "grafast";
|
|
2
|
-
import { gql, makeExtendSchemaPlugin } from "postgraphile/utils";
|
|
3
|
-
import { withPgPoolTransaction, } from "../db/index.js";
|
|
4
|
-
import { constant, context, sideEffect } from "postgraphile/grafast";
|
|
5
|
-
import { assert } from "tsafe";
|
|
6
|
-
const CLAIM_AMOUNT = 1000;
|
|
7
|
-
export const HubClaimFaucetPlugin = makeExtendSchemaPlugin(() => {
|
|
8
|
-
return {
|
|
9
|
-
typeDefs: gql `
|
|
10
|
-
type HubClaimFaucetPayload {
|
|
11
|
-
success: Boolean!
|
|
12
|
-
query: Query
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
extend type Mutation {
|
|
16
|
-
hubClaimFaucet: HubClaimFaucetPayload
|
|
17
|
-
}
|
|
18
|
-
`,
|
|
19
|
-
objects: {
|
|
20
|
-
Mutation: {
|
|
21
|
-
plans: {
|
|
22
|
-
hubClaimFaucet() {
|
|
23
|
-
const $context = context();
|
|
24
|
-
const $identity = $context.get("identity");
|
|
25
|
-
const $superuserPool = $context.get("superuserPool");
|
|
26
|
-
const $result = sideEffect([$identity, $superuserPool], ([identity, superuserPool]) => {
|
|
27
|
-
if (identity?.kind !== "user") {
|
|
28
|
-
throw new Error("Must be logged in as user");
|
|
29
|
-
}
|
|
30
|
-
const { session } = identity;
|
|
31
|
-
return withPgPoolTransaction(superuserPool, async (pgClient) => {
|
|
32
|
-
await upsertPlayCurrency(pgClient, session.casino_id);
|
|
33
|
-
await pgClient.query({
|
|
34
|
-
text: `
|
|
35
|
-
insert into hub.faucet_claim (user_id, casino_id, experience_id, currency_key, amount)
|
|
36
|
-
values ($1, $2, $3, $4, $5)
|
|
37
|
-
`,
|
|
38
|
-
values: [
|
|
39
|
-
session.user_id,
|
|
40
|
-
session.casino_id,
|
|
41
|
-
session.experience_id,
|
|
42
|
-
"PLAY",
|
|
43
|
-
CLAIM_AMOUNT,
|
|
44
|
-
],
|
|
45
|
-
});
|
|
46
|
-
await pgClient.query({
|
|
47
|
-
text: `
|
|
48
|
-
INSERT INTO hub.balance (user_id, experience_id, casino_id, currency_key, amount)
|
|
49
|
-
VALUES ($1, $2, $3, $4, $5)
|
|
50
|
-
ON CONFLICT (user_id, experience_id, casino_id, currency_key) DO UPDATE
|
|
51
|
-
SET amount = balance.amount + EXCLUDED.amount
|
|
52
|
-
`,
|
|
53
|
-
values: [
|
|
54
|
-
session.user_id,
|
|
55
|
-
session.experience_id,
|
|
56
|
-
session.casino_id,
|
|
57
|
-
"PLAY",
|
|
58
|
-
CLAIM_AMOUNT,
|
|
59
|
-
],
|
|
60
|
-
});
|
|
61
|
-
return true;
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
return object({
|
|
65
|
-
result: $result,
|
|
66
|
-
});
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
HubClaimFaucetPayload: {
|
|
71
|
-
plans: {
|
|
72
|
-
success($data) {
|
|
73
|
-
return $data.get("result");
|
|
74
|
-
},
|
|
75
|
-
query() {
|
|
76
|
-
return constant(true);
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
});
|
|
83
|
-
async function upsertPlayCurrency(pgClient, casinoId) {
|
|
84
|
-
assert(pgClient._inTransaction, "pgClient must be in transaction");
|
|
85
|
-
return pgClient.query({
|
|
86
|
-
text: `
|
|
87
|
-
insert into hub.currency (casino_id, key, display_unit_name, display_unit_scale)
|
|
88
|
-
values ($1, 'PLAY', 'tokens', 1)
|
|
89
|
-
on conflict (casino_id, key) do nothing
|
|
90
|
-
`,
|
|
91
|
-
values: [casinoId],
|
|
92
|
-
});
|
|
93
|
-
}
|