@moneypot/hub 1.9.0-dev.9 → 1.10.0-dev.1

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.
Files changed (42) hide show
  1. package/dist/cli/add-casino.js +24 -17
  2. package/dist/src/__generated__/gql.d.ts +2 -2
  3. package/dist/src/__generated__/gql.js +1 -1
  4. package/dist/src/__generated__/graphql.d.ts +23 -5
  5. package/dist/src/__generated__/graphql.js +3 -1
  6. package/dist/src/context.d.ts +12 -0
  7. package/dist/src/context.js +31 -0
  8. package/dist/src/db/index.d.ts +3 -6
  9. package/dist/src/db/index.js +5 -13
  10. package/dist/src/db/types.d.ts +1 -0
  11. package/dist/src/db/util.d.ts +4 -0
  12. package/dist/src/hash-chain/plugins/hub-create-hash-chain.js +3 -2
  13. package/dist/src/index.d.ts +7 -4
  14. package/dist/src/index.js +23 -12
  15. package/dist/src/pg-versions/010-take-request-refunded-at.sql +1 -0
  16. package/dist/src/plugins/hub-add-casino.js +4 -2
  17. package/dist/src/plugins/hub-authenticate.js +3 -2
  18. package/dist/src/plugins/hub-claim-faucet.js +5 -3
  19. package/dist/src/plugins/hub-make-outcome-bet.d.ts +1 -10
  20. package/dist/src/plugins/hub-make-outcome-bet.js +20 -55
  21. package/dist/src/plugins/hub-withdraw.js +3 -2
  22. package/dist/src/process-transfers/index.d.ts +5 -2
  23. package/dist/src/process-transfers/index.js +15 -11
  24. package/dist/src/process-transfers/polling-processor.d.ts +3 -1
  25. package/dist/src/process-transfers/polling-processor.js +17 -13
  26. package/dist/src/process-transfers/process-transfer.d.ts +3 -1
  27. package/dist/src/process-transfers/process-transfer.js +7 -8
  28. package/dist/src/process-transfers/websocket-processor.d.ts +3 -1
  29. package/dist/src/process-transfers/websocket-processor.js +3 -1
  30. package/dist/src/process-withdrawal-request.d.ts +3 -1
  31. package/dist/src/process-withdrawal-request.js +6 -5
  32. package/dist/src/risk-policy.d.ts +20 -0
  33. package/dist/src/risk-policy.js +61 -0
  34. package/dist/src/server/graphile.config.d.ts +3 -1
  35. package/dist/src/server/graphile.config.js +6 -5
  36. package/dist/src/server/index.d.ts +3 -1
  37. package/dist/src/server/index.js +5 -4
  38. package/dist/src/server/middleware/authentication.d.ts +2 -1
  39. package/dist/src/server/middleware/authentication.js +5 -5
  40. package/dist/src/take-request/process-take-request.d.ts +13 -2
  41. package/dist/src/take-request/process-take-request.js +70 -23
  42. package/package.json +1 -1
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { z } from "zod";
3
3
  import { dbInsertCasino } from "../src/db/internal.js";
4
- import { superuserPool, upsertCurrencies } from "../src/db/index.js";
4
+ import { upsertCurrencies } from "../src/db/index.js";
5
5
  import { createGraphqlClient } from "../src/graphql-client.js";
6
6
  import { GET_CURRENCIES } from "../src/graphql-queries.js";
7
7
  import { gql } from "../src/__generated__/gql.js";
8
+ import { createServerContext, closeServerContext } from "../src/context.js";
8
9
  const GET_CURRENT_CONTROLLER = gql(`
9
10
  query AddCasino_GetCurrentController {
10
11
  currentController {
@@ -66,24 +67,30 @@ function parseArgs(args) {
66
67
  return parsedArgs;
67
68
  }
68
69
  async function addCasino(input) {
69
- const graphqlClient = createGraphqlClient({
70
- graphqlUrl: input.graphql_url,
71
- apiKey: input.api_key,
72
- });
73
- console.log(`Verifying controller creds with ${input.graphql_url}...`);
74
- const result1 = await graphqlClient.request(GET_CURRENT_CONTROLLER);
75
- if (!result1.currentController) {
76
- throw new Error("Bad controller ID or API key");
70
+ const context = createServerContext();
71
+ try {
72
+ const graphqlClient = createGraphqlClient({
73
+ graphqlUrl: input.graphql_url,
74
+ apiKey: input.api_key,
75
+ });
76
+ console.log(`Verifying controller creds with ${input.graphql_url}...`);
77
+ const result1 = await graphqlClient.request(GET_CURRENT_CONTROLLER);
78
+ if (!result1.currentController) {
79
+ throw new Error("Bad controller ID or API key");
80
+ }
81
+ const result2 = await graphqlClient.request(GET_CURRENCIES);
82
+ const currencies = result2.allCurrencies?.nodes.flatMap((x) => (x ? [x] : [])) || [];
83
+ console.log(`Found ${currencies.length} currencies:`, currencies.map((x) => x.id).join(", "));
84
+ const fields = { ...input, controller_id: result1.currentController.id };
85
+ const casino = await dbInsertCasino(context.superuserPool, fields);
86
+ if (currencies.length > 0) {
87
+ await upsertCurrencies(context.superuserPool, { casinoId: casino.id, currencies });
88
+ }
89
+ return casino;
77
90
  }
78
- const result2 = await graphqlClient.request(GET_CURRENCIES);
79
- const currencies = result2.allCurrencies?.nodes.flatMap((x) => (x ? [x] : [])) || [];
80
- console.log(`Found ${currencies.length} currencies:`, currencies.map((x) => x.id).join(", "));
81
- const fields = { ...input, controller_id: result1.currentController.id };
82
- const casino = await dbInsertCasino(superuserPool, fields);
83
- if (currencies.length > 0) {
84
- await upsertCurrencies(superuserPool, { casinoId: casino.id, currencies });
91
+ finally {
92
+ await closeServerContext(context);
85
93
  }
86
- return casino;
87
94
  }
88
95
  function printUsageExample() {
89
96
  console.error("\nUsage example:");
@@ -19,7 +19,7 @@ type Documents = {
19
19
  "\n query MpPaginatedPendingTakeRequests($controllerId: UUID!, $after: Cursor) {\n allTakeRequests(\n condition: { controllerId: $controllerId, status: PENDING }\n after: $after\n orderBy: ID_ASC\n ) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n ...MpTakeRequestFields\n }\n }\n }\n }\n": typeof types.MpPaginatedPendingTakeRequestsDocument;
20
20
  "\n mutation MpRejectTakeRequest($mpTakeRequestId: UUID!) {\n rejectTakeRequest(input: { id: $mpTakeRequestId }) {\n result {\n ... on RejectTakeRequestSuccess {\n __typename\n takeRequest {\n id\n }\n }\n ... on TakeRequestAlreadyTerminal {\n __typename\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n": typeof types.MpRejectTakeRequestDocument;
21
21
  "\n mutation MpTransferTakeRequest(\n $mpTakeRequestId: UUID!\n $mpExperienceId: UUID!\n $mpUserId: UUID!\n $amount: Int!\n $currencyKey: String!\n ) {\n transferCurrencyExperienceToUser(\n input: {\n takeRequestId: $mpTakeRequestId\n experienceId: $mpExperienceId\n userId: $mpUserId\n amount: $amount\n currency: $currencyKey\n }\n ) {\n result {\n ... on TransferSuccess {\n __typename\n transfer {\n id\n status\n }\n }\n ... on TransferMetadataIdExists {\n __typename\n transfer {\n id\n status\n }\n }\n ... on TakeRequestAlreadyTerminal {\n __typename\n takeRequest {\n id\n status\n experienceTransfer {\n id\n status\n }\n }\n }\n }\n }\n }\n": typeof types.MpTransferTakeRequestDocument;
22
- "\n mutation CompleteTransfer2($mpTransferId: UUID!) {\n completeTransfer(input: { id: $mpTransferId }) {\n result {\n ... on CompleteTransferSuccess {\n __typename\n transfer {\n __typename\n id\n status\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n ... on InvalidTransferStatus {\n __typename\n currentStatus\n message\n transfer {\n __typename\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n }\n }\n": typeof types.CompleteTransfer2Document;
22
+ "\n mutation CompleteTransfer2($mpTransferId: UUID!) {\n completeTransfer(input: { id: $mpTransferId }) {\n result {\n __typename\n ... on CompleteTransferSuccess {\n __typename\n transfer {\n id\n status\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n ... on InsufficientBalance {\n message\n }\n ... on InvalidTransferStatus {\n currentStatus\n message\n transfer {\n __typename\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n }\n }\n": typeof types.CompleteTransfer2Document;
23
23
  };
24
24
  declare const documents: Documents;
25
25
  export declare function gql(source: string): unknown;
@@ -41,6 +41,6 @@ export declare function gql(source: "\n query MpGetTakeRequest($id: UUID!) {\n
41
41
  export declare function gql(source: "\n query MpPaginatedPendingTakeRequests($controllerId: UUID!, $after: Cursor) {\n allTakeRequests(\n condition: { controllerId: $controllerId, status: PENDING }\n after: $after\n orderBy: ID_ASC\n ) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n ...MpTakeRequestFields\n }\n }\n }\n }\n"): (typeof documents)["\n query MpPaginatedPendingTakeRequests($controllerId: UUID!, $after: Cursor) {\n allTakeRequests(\n condition: { controllerId: $controllerId, status: PENDING }\n after: $after\n orderBy: ID_ASC\n ) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n ...MpTakeRequestFields\n }\n }\n }\n }\n"];
42
42
  export declare function gql(source: "\n mutation MpRejectTakeRequest($mpTakeRequestId: UUID!) {\n rejectTakeRequest(input: { id: $mpTakeRequestId }) {\n result {\n ... on RejectTakeRequestSuccess {\n __typename\n takeRequest {\n id\n }\n }\n ... on TakeRequestAlreadyTerminal {\n __typename\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n"): (typeof documents)["\n mutation MpRejectTakeRequest($mpTakeRequestId: UUID!) {\n rejectTakeRequest(input: { id: $mpTakeRequestId }) {\n result {\n ... on RejectTakeRequestSuccess {\n __typename\n takeRequest {\n id\n }\n }\n ... on TakeRequestAlreadyTerminal {\n __typename\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n"];
43
43
  export declare function gql(source: "\n mutation MpTransferTakeRequest(\n $mpTakeRequestId: UUID!\n $mpExperienceId: UUID!\n $mpUserId: UUID!\n $amount: Int!\n $currencyKey: String!\n ) {\n transferCurrencyExperienceToUser(\n input: {\n takeRequestId: $mpTakeRequestId\n experienceId: $mpExperienceId\n userId: $mpUserId\n amount: $amount\n currency: $currencyKey\n }\n ) {\n result {\n ... on TransferSuccess {\n __typename\n transfer {\n id\n status\n }\n }\n ... on TransferMetadataIdExists {\n __typename\n transfer {\n id\n status\n }\n }\n ... on TakeRequestAlreadyTerminal {\n __typename\n takeRequest {\n id\n status\n experienceTransfer {\n id\n status\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n mutation MpTransferTakeRequest(\n $mpTakeRequestId: UUID!\n $mpExperienceId: UUID!\n $mpUserId: UUID!\n $amount: Int!\n $currencyKey: String!\n ) {\n transferCurrencyExperienceToUser(\n input: {\n takeRequestId: $mpTakeRequestId\n experienceId: $mpExperienceId\n userId: $mpUserId\n amount: $amount\n currency: $currencyKey\n }\n ) {\n result {\n ... on TransferSuccess {\n __typename\n transfer {\n id\n status\n }\n }\n ... on TransferMetadataIdExists {\n __typename\n transfer {\n id\n status\n }\n }\n ... on TakeRequestAlreadyTerminal {\n __typename\n takeRequest {\n id\n status\n experienceTransfer {\n id\n status\n }\n }\n }\n }\n }\n }\n"];
44
- export declare function gql(source: "\n mutation CompleteTransfer2($mpTransferId: UUID!) {\n completeTransfer(input: { id: $mpTransferId }) {\n result {\n ... on CompleteTransferSuccess {\n __typename\n transfer {\n __typename\n id\n status\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n ... on InvalidTransferStatus {\n __typename\n currentStatus\n message\n transfer {\n __typename\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n mutation CompleteTransfer2($mpTransferId: UUID!) {\n completeTransfer(input: { id: $mpTransferId }) {\n result {\n ... on CompleteTransferSuccess {\n __typename\n transfer {\n __typename\n id\n status\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n ... on InvalidTransferStatus {\n __typename\n currentStatus\n message\n transfer {\n __typename\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n }\n }\n"];
44
+ export declare function gql(source: "\n mutation CompleteTransfer2($mpTransferId: UUID!) {\n completeTransfer(input: { id: $mpTransferId }) {\n result {\n __typename\n ... on CompleteTransferSuccess {\n __typename\n transfer {\n id\n status\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n ... on InsufficientBalance {\n message\n }\n ... on InvalidTransferStatus {\n currentStatus\n message\n transfer {\n __typename\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n mutation CompleteTransfer2($mpTransferId: UUID!) {\n completeTransfer(input: { id: $mpTransferId }) {\n result {\n __typename\n ... on CompleteTransferSuccess {\n __typename\n transfer {\n id\n status\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n ... on InsufficientBalance {\n message\n }\n ... on InvalidTransferStatus {\n currentStatus\n message\n transfer {\n __typename\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n }\n }\n"];
45
45
  export type DocumentType<TDocumentNode extends DocumentNode<any, any>> = TDocumentNode extends DocumentNode<infer TType, any> ? TType : never;
46
46
  export {};
@@ -18,7 +18,7 @@ const documents = {
18
18
  "\n query MpPaginatedPendingTakeRequests($controllerId: UUID!, $after: Cursor) {\n allTakeRequests(\n condition: { controllerId: $controllerId, status: PENDING }\n after: $after\n orderBy: ID_ASC\n ) {\n pageInfo {\n endCursor\n hasNextPage\n }\n edges {\n cursor\n node {\n ...MpTakeRequestFields\n }\n }\n }\n }\n": types.MpPaginatedPendingTakeRequestsDocument,
19
19
  "\n mutation MpRejectTakeRequest($mpTakeRequestId: UUID!) {\n rejectTakeRequest(input: { id: $mpTakeRequestId }) {\n result {\n ... on RejectTakeRequestSuccess {\n __typename\n takeRequest {\n id\n }\n }\n ... on TakeRequestAlreadyTerminal {\n __typename\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n": types.MpRejectTakeRequestDocument,
20
20
  "\n mutation MpTransferTakeRequest(\n $mpTakeRequestId: UUID!\n $mpExperienceId: UUID!\n $mpUserId: UUID!\n $amount: Int!\n $currencyKey: String!\n ) {\n transferCurrencyExperienceToUser(\n input: {\n takeRequestId: $mpTakeRequestId\n experienceId: $mpExperienceId\n userId: $mpUserId\n amount: $amount\n currency: $currencyKey\n }\n ) {\n result {\n ... on TransferSuccess {\n __typename\n transfer {\n id\n status\n }\n }\n ... on TransferMetadataIdExists {\n __typename\n transfer {\n id\n status\n }\n }\n ... on TakeRequestAlreadyTerminal {\n __typename\n takeRequest {\n id\n status\n experienceTransfer {\n id\n status\n }\n }\n }\n }\n }\n }\n": types.MpTransferTakeRequestDocument,
21
- "\n mutation CompleteTransfer2($mpTransferId: UUID!) {\n completeTransfer(input: { id: $mpTransferId }) {\n result {\n ... on CompleteTransferSuccess {\n __typename\n transfer {\n __typename\n id\n status\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n ... on InvalidTransferStatus {\n __typename\n currentStatus\n message\n transfer {\n __typename\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n }\n }\n": types.CompleteTransfer2Document,
21
+ "\n mutation CompleteTransfer2($mpTransferId: UUID!) {\n completeTransfer(input: { id: $mpTransferId }) {\n result {\n __typename\n ... on CompleteTransferSuccess {\n __typename\n transfer {\n id\n status\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n ... on InsufficientBalance {\n message\n }\n ... on InvalidTransferStatus {\n currentStatus\n message\n transfer {\n __typename\n ... on ExperienceTransfer {\n id\n takeRequest {\n id\n status\n }\n }\n }\n }\n }\n }\n }\n": types.CompleteTransfer2Document,
22
22
  };
23
23
  export function gql(source) {
24
24
  return documents[source] ?? {};
@@ -336,6 +336,17 @@ export type ChallengeFailed = {
336
336
  __typename?: 'ChallengeFailed';
337
337
  message: Scalars['String']['output'];
338
338
  };
339
+ export type ChangeUserRoleInput = {
340
+ clientMutationId?: InputMaybe<Scalars['String']['input']>;
341
+ role: UserRole;
342
+ userId: Scalars['UUID']['input'];
343
+ };
344
+ export type ChangeUserRolePayload = {
345
+ __typename?: 'ChangeUserRolePayload';
346
+ clientMutationId?: Maybe<Scalars['String']['output']>;
347
+ query?: Maybe<Query>;
348
+ user: User;
349
+ };
339
350
  export type ClaimFaucetInput = {
340
351
  clientMutationId?: InputMaybe<Scalars['String']['input']>;
341
352
  currencyKey: Scalars['String']['input'];
@@ -1281,6 +1292,7 @@ export type Mutation = {
1281
1292
  cancelPendingPayout: CancelPendingPayoutPayload;
1282
1293
  cancelTakeRequest: CancelTakeRequestPayload;
1283
1294
  cancelTransfer?: Maybe<CancelTransferPayload>;
1295
+ changeUserRole?: Maybe<ChangeUserRolePayload>;
1284
1296
  claimFaucet?: Maybe<ClaimFaucetPayload>;
1285
1297
  claimTransfer?: Maybe<ClaimTransferPayload>;
1286
1298
  completeTransfer?: Maybe<CompleteTransferPayload>;
@@ -1337,6 +1349,9 @@ export type MutationCancelTakeRequestArgs = {
1337
1349
  export type MutationCancelTransferArgs = {
1338
1350
  input: CancelTransferInput;
1339
1351
  };
1352
+ export type MutationChangeUserRoleArgs = {
1353
+ input: ChangeUserRoleInput;
1354
+ };
1340
1355
  export type MutationClaimFaucetArgs = {
1341
1356
  input: ClaimFaucetInput;
1342
1357
  };
@@ -1550,6 +1565,7 @@ export declare enum PayoutStatus {
1550
1565
  New = "new",
1551
1566
  Pending = "pending",
1552
1567
  Rejected = "rejected",
1568
+ Scheduled = "scheduled",
1553
1569
  Unconfirmed = "unconfirmed"
1554
1570
  }
1555
1571
  export type PayoutStatusChange = {
@@ -3237,7 +3253,8 @@ export declare enum UserOrderBy {
3237
3253
  export declare enum UserRole {
3238
3254
  Admin = "ADMIN",
3239
3255
  Demo = "DEMO",
3240
- Member = "MEMBER"
3256
+ Member = "MEMBER",
3257
+ Restricted = "RESTRICTED"
3241
3258
  }
3242
3259
  export type UserTransfer = Transfer & {
3243
3260
  __typename?: 'UserTransfer';
@@ -3861,11 +3878,11 @@ export type CompleteTransfer2Mutation = {
3861
3878
  result: {
3862
3879
  __typename: 'CompleteTransferSuccess';
3863
3880
  transfer: {
3864
- __typename: 'ControllerTransfer';
3881
+ __typename?: 'ControllerTransfer';
3865
3882
  id: string;
3866
3883
  status: TransferStatusKind;
3867
3884
  } | {
3868
- __typename: 'ExperienceTransfer';
3885
+ __typename?: 'ExperienceTransfer';
3869
3886
  id: string;
3870
3887
  status: TransferStatusKind;
3871
3888
  takeRequest?: {
@@ -3874,12 +3891,13 @@ export type CompleteTransfer2Mutation = {
3874
3891
  status: TakeRequestStatus;
3875
3892
  } | null;
3876
3893
  } | {
3877
- __typename: 'UserTransfer';
3894
+ __typename?: 'UserTransfer';
3878
3895
  id: string;
3879
3896
  status: TransferStatusKind;
3880
3897
  };
3881
3898
  } | {
3882
- __typename?: 'InsufficientBalance';
3899
+ __typename: 'InsufficientBalance';
3900
+ message: string;
3883
3901
  } | {
3884
3902
  __typename: 'InvalidTransferStatus';
3885
3903
  currentStatus: TransferStatusKind;
@@ -252,6 +252,7 @@ export var PayoutStatus;
252
252
  PayoutStatus["New"] = "new";
253
253
  PayoutStatus["Pending"] = "pending";
254
254
  PayoutStatus["Rejected"] = "rejected";
255
+ PayoutStatus["Scheduled"] = "scheduled";
255
256
  PayoutStatus["Unconfirmed"] = "unconfirmed";
256
257
  })(PayoutStatus || (PayoutStatus = {}));
257
258
  export var PayoutStatusChangeOrderBy;
@@ -471,6 +472,7 @@ export var UserRole;
471
472
  UserRole["Admin"] = "ADMIN";
472
473
  UserRole["Demo"] = "DEMO";
473
474
  UserRole["Member"] = "MEMBER";
475
+ UserRole["Restricted"] = "RESTRICTED";
474
476
  })(UserRole || (UserRole = {}));
475
477
  export var UserTransferOrderBy;
476
478
  (function (UserTransferOrderBy) {
@@ -522,4 +524,4 @@ export const MpGetTakeRequestDocument = { "kind": "Document", "definitions": [{
522
524
  export const MpPaginatedPendingTakeRequestsDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "MpPaginatedPendingTakeRequests" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "controllerId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "UUID" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "after" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Cursor" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "allTakeRequests" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "condition" }, "value": { "kind": "ObjectValue", "fields": [{ "kind": "ObjectField", "name": { "kind": "Name", "value": "controllerId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "controllerId" } } }, { "kind": "ObjectField", "name": { "kind": "Name", "value": "status" }, "value": { "kind": "EnumValue", "value": "PENDING" } }] } }, { "kind": "Argument", "name": { "kind": "Name", "value": "after" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "after" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "orderBy" }, "value": { "kind": "EnumValue", "value": "ID_ASC" } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "pageInfo" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "endCursor" } }, { "kind": "Field", "name": { "kind": "Name", "value": "hasNextPage" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "edges" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "cursor" } }, { "kind": "Field", "name": { "kind": "Name", "value": "node" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "FragmentSpread", "name": { "kind": "Name", "value": "MpTakeRequestFields" } }] } }] } }] } }] } }, { "kind": "FragmentDefinition", "name": { "kind": "Name", "value": "MpTakeRequestFields" }, "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "TakeRequest" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "amount" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currencyKey" } }, { "kind": "Field", "name": { "kind": "Name", "value": "userId" } }, { "kind": "Field", "name": { "kind": "Name", "value": "experienceId" } }, { "kind": "Field", "name": { "kind": "Name", "value": "experienceTransfer" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "amount" } }] } }] } }] };
523
525
  export const MpRejectTakeRequestDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "mutation", "name": { "kind": "Name", "value": "MpRejectTakeRequest" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "mpTakeRequestId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "UUID" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "rejectTakeRequest" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "input" }, "value": { "kind": "ObjectValue", "fields": [{ "kind": "ObjectField", "name": { "kind": "Name", "value": "id" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "mpTakeRequestId" } } }] } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "result" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "RejectTakeRequestSuccess" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "takeRequest" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }] } }] } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "TakeRequestAlreadyTerminal" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "takeRequest" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }] } }] } }] } }] } }] } }] };
524
526
  export const MpTransferTakeRequestDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "mutation", "name": { "kind": "Name", "value": "MpTransferTakeRequest" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "mpTakeRequestId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "UUID" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "mpExperienceId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "UUID" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "mpUserId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "UUID" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "amount" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "currencyKey" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "transferCurrencyExperienceToUser" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "input" }, "value": { "kind": "ObjectValue", "fields": [{ "kind": "ObjectField", "name": { "kind": "Name", "value": "takeRequestId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "mpTakeRequestId" } } }, { "kind": "ObjectField", "name": { "kind": "Name", "value": "experienceId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "mpExperienceId" } } }, { "kind": "ObjectField", "name": { "kind": "Name", "value": "userId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "mpUserId" } } }, { "kind": "ObjectField", "name": { "kind": "Name", "value": "amount" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "amount" } } }, { "kind": "ObjectField", "name": { "kind": "Name", "value": "currency" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "currencyKey" } } }] } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "result" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "TransferSuccess" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "transfer" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }] } }] } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "TransferMetadataIdExists" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "transfer" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }] } }] } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "TakeRequestAlreadyTerminal" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "takeRequest" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "experienceTransfer" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }] } }] } }] } }] } }] } }] } }] };
525
- export const CompleteTransfer2Document = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "mutation", "name": { "kind": "Name", "value": "CompleteTransfer2" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "mpTransferId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "UUID" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "completeTransfer" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "input" }, "value": { "kind": "ObjectValue", "fields": [{ "kind": "ObjectField", "name": { "kind": "Name", "value": "id" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "mpTransferId" } } }] } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "result" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "CompleteTransferSuccess" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "transfer" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "ExperienceTransfer" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "takeRequest" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }] } }] } }] } }] } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "InvalidTransferStatus" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "currentStatus" } }, { "kind": "Field", "name": { "kind": "Name", "value": "message" } }, { "kind": "Field", "name": { "kind": "Name", "value": "transfer" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "ExperienceTransfer" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "takeRequest" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }] } }] } }] } }] } }] } }] } }] } }] };
527
+ export const CompleteTransfer2Document = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "mutation", "name": { "kind": "Name", "value": "CompleteTransfer2" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "mpTransferId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "UUID" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "completeTransfer" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "input" }, "value": { "kind": "ObjectValue", "fields": [{ "kind": "ObjectField", "name": { "kind": "Name", "value": "id" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "mpTransferId" } } }] } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "result" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "CompleteTransferSuccess" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "transfer" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "ExperienceTransfer" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "takeRequest" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }] } }] } }] } }] } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "InsufficientBalance" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "message" } }] } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "InvalidTransferStatus" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "currentStatus" } }, { "kind": "Field", "name": { "kind": "Name", "value": "message" } }, { "kind": "Field", "name": { "kind": "Name", "value": "transfer" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "ExperienceTransfer" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "takeRequest" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "status" } }] } }] } }] } }] } }] } }] } }] } }] };
@@ -0,0 +1,12 @@
1
+ import * as pg from "pg";
2
+ import { DatabaseNotifier } from "./db/index.js";
3
+ export interface ServerContext {
4
+ postgraphilePool: pg.Pool;
5
+ superuserPool: pg.Pool;
6
+ notifier: DatabaseNotifier;
7
+ }
8
+ export declare function createServerContext(overrides?: {
9
+ superuserDatabaseUrl?: string;
10
+ postgraphileDatabaseUrl?: string;
11
+ }): ServerContext;
12
+ export declare function closeServerContext(context: ServerContext): Promise<void>;
@@ -0,0 +1,31 @@
1
+ import * as pg from "pg";
2
+ import * as config from "./config.js";
3
+ import { logger } from "./logger.js";
4
+ import { DatabaseNotifier } from "./db/index.js";
5
+ export function createServerContext(overrides) {
6
+ const postgraphileDatabaseUrl = overrides?.postgraphileDatabaseUrl ?? config.DATABASE_URL;
7
+ const superuserDatabaseUrl = overrides?.superuserDatabaseUrl ?? config.SUPERUSER_DATABASE_URL;
8
+ const context = {
9
+ postgraphilePool: new pg.Pool({
10
+ connectionString: postgraphileDatabaseUrl,
11
+ }),
12
+ superuserPool: new pg.Pool({
13
+ connectionString: superuserDatabaseUrl,
14
+ }),
15
+ notifier: new DatabaseNotifier(postgraphileDatabaseUrl),
16
+ };
17
+ return context;
18
+ }
19
+ export async function closeServerContext(context) {
20
+ try {
21
+ await Promise.all([
22
+ context.notifier.close(),
23
+ context.postgraphilePool.end(),
24
+ context.superuserPool.end(),
25
+ ]);
26
+ }
27
+ catch (err) {
28
+ logger.warn(err, "Error closing server context resources");
29
+ throw err;
30
+ }
31
+ }
@@ -7,8 +7,6 @@ export * from "./types.js";
7
7
  export * from "./public.js";
8
8
  export * from "./util.js";
9
9
  export declare function getPgClient(connectionString: string): InstanceType<typeof pg.Client>;
10
- export declare const postgraphilePool: pg.Pool;
11
- export declare const superuserPool: pg.Pool;
12
10
  export interface QueryExecutor {
13
11
  query<T extends pg.QueryResultRow = any>(queryText: string, values?: any[]): Promise<pg.QueryResult<T>>;
14
12
  }
@@ -23,13 +21,12 @@ export declare function userFromActiveSessionKey(pgClient: QueryExecutor, sessio
23
21
  user: DbUser;
24
22
  sessionId: DbSession["id"];
25
23
  } | null>;
26
- declare class DatabaseNotifier extends stream.EventEmitter {
24
+ export declare class DatabaseNotifier extends stream.EventEmitter {
27
25
  private pgClient;
28
26
  constructor(connectionString: string);
29
27
  close(): Promise<void>;
30
28
  listen(): Promise<void>;
31
29
  }
32
- export declare const notifier: DatabaseNotifier;
33
30
  export declare function getTransferCursor(pgClient: QueryExecutor, { casinoId, }: {
34
31
  casinoId: string;
35
32
  }): Promise<string | undefined>;
@@ -47,7 +44,7 @@ export declare function upsertExperience(pgClient: QueryExecutor, { casinoId, mp
47
44
  mpExperienceId: string;
48
45
  name: string;
49
46
  }): Promise<DbExperience>;
50
- export declare function insertDeposit(o: {
47
+ export declare function insertDeposit(pool: pg.Pool, o: {
51
48
  casinoId: string;
52
49
  mpTransferId: string;
53
50
  userId: string;
@@ -78,7 +75,7 @@ export declare function getPendingWithdrawals(pgClient: QueryExecutor, { casinoI
78
75
  mp_experience_id: string;
79
76
  mp_user_id: string;
80
77
  })[]>;
81
- export declare function settleWithdrawal({ withdrawalId, newStatus, }: {
78
+ export declare function settleWithdrawal(pool: pg.Pool, { withdrawalId, newStatus, }: {
82
79
  withdrawalId: string;
83
80
  newStatus: Extract<DbTransferStatusKind, "COMPLETED" | "CANCELED">;
84
81
  }): Promise<void>;
@@ -1,5 +1,4 @@
1
1
  import * as pg from "pg";
2
- import * as config from "../config.js";
3
2
  import stream from "node:stream";
4
3
  import { exactlyOneRow, maybeOneRow } from "./util.js";
5
4
  import { logger } from "../logger.js";
@@ -13,12 +12,6 @@ export function getPgClient(connectionString) {
13
12
  const client = new pg.Client({ connectionString });
14
13
  return client;
15
14
  }
16
- export const postgraphilePool = new pg.Pool({
17
- connectionString: config.DATABASE_URL,
18
- });
19
- export const superuserPool = new pg.Pool({
20
- connectionString: config.SUPERUSER_DATABASE_URL,
21
- });
22
15
  export class UserFriendlyError extends Error {
23
16
  constructor(userFriendlyMessage) {
24
17
  super(userFriendlyMessage);
@@ -93,7 +86,7 @@ export async function userFromActiveSessionKey(pgClient, sessionKey) {
93
86
  sessionId: session_id,
94
87
  };
95
88
  }
96
- class DatabaseNotifier extends stream.EventEmitter {
89
+ export class DatabaseNotifier extends stream.EventEmitter {
97
90
  pgClient;
98
91
  constructor(connectionString) {
99
92
  super();
@@ -124,7 +117,6 @@ class DatabaseNotifier extends stream.EventEmitter {
124
117
  });
125
118
  }
126
119
  }
127
- export const notifier = new DatabaseNotifier(config.DATABASE_URL);
128
120
  export async function getTransferCursor(pgClient, { casinoId, }) {
129
121
  const row = await pgClient
130
122
  .query("select cursor from hub_hidden.transfer_cursor where casino_id = $1", [casinoId])
@@ -175,11 +167,11 @@ export async function upsertExperience(pgClient, { casinoId, mpExperienceId, nam
175
167
  `, [casinoId, mpExperienceId, name])
176
168
  .then(exactlyOneRow);
177
169
  }
178
- export async function insertDeposit(o) {
170
+ export async function insertDeposit(pool, o) {
179
171
  if (o.amount <= 0) {
180
172
  throw new UserFriendlyError("amount must be positive");
181
173
  }
182
- return withPgPoolTransaction(superuserPool, async (client) => {
174
+ return withPgPoolTransaction(pool, async (client) => {
183
175
  const result = await client.query(`
184
176
  INSERT INTO hub.deposit(casino_id, mp_transfer_id, user_id, experience_id, amount, currency_key)
185
177
  VALUES ($1, $2, $3, $4, $5, $6)
@@ -268,8 +260,8 @@ export async function getPendingWithdrawals(pgClient, { casinoId, limit, }) {
268
260
  `, [casinoId, limit]);
269
261
  return result.rows;
270
262
  }
271
- export async function settleWithdrawal({ withdrawalId, newStatus, }) {
272
- return withPgPoolTransaction(superuserPool, async (pgClient) => {
263
+ export async function settleWithdrawal(pool, { withdrawalId, newStatus, }) {
264
+ return withPgPoolTransaction(pool, async (pgClient) => {
273
265
  const dbWithdrawal = await pgClient
274
266
  .query(`
275
267
  select *
@@ -112,6 +112,7 @@ export type DbTakeRequest = {
112
112
  mp_transfer_status: DbTransferStatusKind | null;
113
113
  transfer_needs_completion: boolean;
114
114
  transfer_completion_attempted_at: Date | null;
115
+ refunded_at: Date | null;
115
116
  updated_at: Date;
116
117
  };
117
118
  export type DbHashChain = {
@@ -1,5 +1,9 @@
1
1
  import { QueryResult, QueryResultRow } from "pg";
2
2
  import { PgClientResult } from "postgraphile/@dataplan/pg";
3
+ import * as pg from "pg";
4
+ export interface QueryExecutor {
5
+ query<T extends pg.QueryResultRow = any>(queryText: string, values?: any[]): Promise<pg.QueryResult<T>>;
6
+ }
3
7
  type ResultType<T> = PgClientResult<T> | QueryResult<T extends QueryResultRow ? T : never>;
4
8
  export declare function maybeOneRow<T>(result: ResultType<T>): T | undefined;
5
9
  export declare function exactlyOneRow<T>(result: ResultType<T>): T;
@@ -2,7 +2,7 @@ import { context, object, sideEffect } from "@moneypot/hub/grafast";
2
2
  import { gql, makeExtendSchemaPlugin } from "@moneypot/hub/graphile";
3
3
  import { GraphQLError } from "graphql";
4
4
  import { PgAdvisoryLock } from "../../pg-advisory-lock.js";
5
- import { exactlyOneRow, superuserPool, withPgPoolTransaction, } from "@moneypot/hub/db";
5
+ import { exactlyOneRow, withPgPoolTransaction } from "@moneypot/hub/db";
6
6
  import * as HashCommon from "../get-hash.js";
7
7
  import { DbHashKind } from "../../db/types.js";
8
8
  import * as config from "../../config.js";
@@ -23,7 +23,8 @@ export const HubCreateHashChainPlugin = makeExtendSchemaPlugin((build) => {
23
23
  plans: {
24
24
  hubCreateHashChain: () => {
25
25
  const $identity = context().get("identity");
26
- const $hashChainId = sideEffect([$identity], ([identity]) => {
26
+ const $superuserPool = context().get("superuserPool");
27
+ const $hashChainId = sideEffect([$identity, $superuserPool], ([identity, superuserPool]) => {
27
28
  if (identity?.kind !== "user") {
28
29
  throw new GraphQLError("Unauthorized");
29
30
  }
@@ -1,10 +1,12 @@
1
1
  import { Express } from "express";
2
2
  import { type PluginIdentity } from "./server/graphile.config.js";
3
+ import { ServerContext } from "./context.js";
3
4
  declare global {
4
5
  namespace Grafast {
5
6
  interface Context {
6
7
  identity?: PluginIdentity;
7
8
  abortSignal: AbortSignal;
9
+ superuserPool: ServerContext["superuserPool"];
8
10
  }
9
11
  }
10
12
  }
@@ -15,7 +17,8 @@ declare global {
15
17
  }
16
18
  }
17
19
  }
18
- export { MakeOutcomeBetPlugin, type OutcomeBetConfigMap, type OutcomeBetConfig, type RiskPolicy, type RiskLimits, } from "./plugins/hub-make-outcome-bet.js";
20
+ export { MakeOutcomeBetPlugin, type OutcomeBetConfigMap, type OutcomeBetConfig, } from "./plugins/hub-make-outcome-bet.js";
21
+ export { validateRisk, type RiskPolicy, type RiskPolicyArgs, type RiskLimits, } from "./risk-policy.js";
19
22
  export type PluginContext = Grafast.Context;
20
23
  export { defaultPlugins, type PluginIdentity, type UserSessionContext, } from "./server/graphile.config.js";
21
24
  export type ServerOptions = {
@@ -25,7 +28,7 @@ export type ServerOptions = {
25
28
  exportSchemaSDLPath?: string;
26
29
  userDatabaseMigrationsPath?: string;
27
30
  };
28
- type ListenInfo = {
31
+ export declare function startAndListen(options: ServerOptions): Promise<{
29
32
  port: number;
30
- };
31
- export declare function startAndListen(options: ServerOptions): Promise<ListenInfo>;
33
+ stop: () => Promise<void>;
34
+ }>;
package/dist/src/index.js CHANGED
@@ -5,7 +5,9 @@ import { createHubServer } from "./server/index.js";
5
5
  import { initializeTransferProcessors } from "./process-transfers/index.js";
6
6
  import { join } from "path";
7
7
  import { logger } from "./logger.js";
8
+ import { createServerContext, closeServerContext, } from "./context.js";
8
9
  export { MakeOutcomeBetPlugin, } from "./plugins/hub-make-outcome-bet.js";
10
+ export { validateRisk, } from "./risk-policy.js";
9
11
  export { defaultPlugins, } from "./server/graphile.config.js";
10
12
  async function initialize(options) {
11
13
  if (options.signal.aborted) {
@@ -45,9 +47,12 @@ async function initialize(options) {
45
47
  logger.info("Initialization aborted by graceful shutdown");
46
48
  return;
47
49
  }
48
- initializeTransferProcessors({
49
- signal: options.signal,
50
- });
50
+ if (process.env.NODE_ENV !== "test") {
51
+ initializeTransferProcessors({
52
+ signal: options.signal,
53
+ pool: options.context.superuserPool,
54
+ });
55
+ }
51
56
  }
52
57
  export async function startAndListen(options) {
53
58
  if (options.plugins && options.plugins.some((p) => typeof p === "function")) {
@@ -63,9 +68,11 @@ export async function startAndListen(options) {
63
68
  }
64
69
  const abortController = new AbortController();
65
70
  let isShuttingDown = false;
71
+ const context = createServerContext();
66
72
  await initialize({
67
73
  userDatabaseMigrationsPath: options.userDatabaseMigrationsPath,
68
74
  signal: abortController.signal,
75
+ context,
69
76
  });
70
77
  const hubServer = createHubServer({
71
78
  configureApp: options.configureApp,
@@ -73,8 +80,9 @@ export async function startAndListen(options) {
73
80
  exportSchemaSDLPath: options.exportSchemaSDLPath,
74
81
  extraPgSchemas: options.extraPgSchemas,
75
82
  abortSignal: abortController.signal,
83
+ context,
76
84
  });
77
- const gracefulShutdown = async () => {
85
+ const gracefulShutdown = async ({ exit = true } = {}) => {
78
86
  if (isShuttingDown) {
79
87
  logger.warn("Already shutting down.");
80
88
  return;
@@ -87,11 +95,7 @@ export async function startAndListen(options) {
87
95
  hubServer.shutdown();
88
96
  try {
89
97
  await Promise.race([
90
- Promise.all([
91
- db.notifier.close(),
92
- db.postgraphilePool.end(),
93
- db.superuserPool.end(),
94
- ]),
98
+ closeServerContext(context),
95
99
  new Promise((_, reject) => setTimeout(() => reject(new Error("Database cleanup timeout")), 3000)),
96
100
  ]);
97
101
  logger.info("Cleanup complete.");
@@ -99,13 +103,20 @@ export async function startAndListen(options) {
99
103
  catch (err) {
100
104
  logger.warn(err, "Cleanup error (proceeding anyway)");
101
105
  }
102
- process.exit(0);
106
+ if (exit) {
107
+ process.exit(0);
108
+ }
103
109
  };
104
- process.on("SIGINT", gracefulShutdown);
105
- process.on("SIGTERM", gracefulShutdown);
110
+ if (process.env.NODE_ENV !== "test") {
111
+ process.on("SIGINT", gracefulShutdown);
112
+ process.on("SIGTERM", gracefulShutdown);
113
+ }
106
114
  return hubServer.listen().then(() => {
107
115
  return {
108
116
  port: config.PORT,
117
+ stop: async () => {
118
+ await gracefulShutdown({ exit: false });
119
+ },
109
120
  };
110
121
  });
111
122
  }
@@ -0,0 +1 @@
1
+ alter table hub.take_request add column refunded_at timestamptz
@@ -4,7 +4,7 @@ import { exactlyOneRow } from "../db/util.js";
4
4
  import { gql as generatedGql } from "../__generated__/gql.js";
5
5
  import { GraphQLClient } from "graphql-request";
6
6
  import { GraphQLError } from "graphql";
7
- import { superuserPool, upsertCurrencies, withPgPoolTransaction, } from "../db/index.js";
7
+ import { upsertCurrencies, withPgPoolTransaction, } from "../db/index.js";
8
8
  import { logger } from "../logger.js";
9
9
  import { assert, is } from "tsafe";
10
10
  import * as jwtService from "../services/jwt-service.js";
@@ -48,8 +48,9 @@ export const HubAddCasinoPlugin = makeExtendSchemaPlugin((build) => {
48
48
  plans: {
49
49
  hubAddCasino(_, { $input }) {
50
50
  const $identity = context().get("identity");
51
+ const $superuserPool = context().get("superuserPool");
51
52
  const $abortSignal = context().get("abortSignal");
52
- const $casinoId = sideEffect([$input, $identity, $abortSignal], ([input, identity, abortSignal]) => {
53
+ const $casinoId = sideEffect([$input, $identity, $superuserPool, $abortSignal], ([input, identity, superuserPool, abortSignal]) => {
53
54
  return withPgPoolTransaction(superuserPool, async (pgClient) => {
54
55
  if (identity?.kind !== "operator") {
55
56
  throw new GraphQLError("Unauthorized");
@@ -141,6 +142,7 @@ export const HubAddCasinoPlugin = makeExtendSchemaPlugin((build) => {
141
142
  startCasinoTransferProcessor({
142
143
  casinoId: casino.id,
143
144
  signal: abortSignal,
145
+ pool: superuserPool,
144
146
  });
145
147
  return casino.id;
146
148
  });