@moneypot/hub 0.0.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 (106) hide show
  1. package/README.md +108 -0
  2. package/dist/cli/add-casino.d.ts +2 -0
  3. package/dist/cli/add-casino.js +116 -0
  4. package/dist/dashboard/assets/index-BtrbrisP.js +360 -0
  5. package/dist/dashboard/assets/index-tK7EUtyc.css +5 -0
  6. package/dist/dashboard/index.html +13 -0
  7. package/dist/src/GraphQLError.d.ts +8 -0
  8. package/dist/src/GraphQLError.js +79 -0
  9. package/dist/src/__generated__/fragment-masking.d.ts +19 -0
  10. package/dist/src/__generated__/fragment-masking.js +16 -0
  11. package/dist/src/__generated__/gql.d.ts +26 -0
  12. package/dist/src/__generated__/gql.js +15 -0
  13. package/dist/src/__generated__/graphql.d.ts +3129 -0
  14. package/dist/src/__generated__/graphql.js +454 -0
  15. package/dist/src/__generated__/index.d.ts +2 -0
  16. package/dist/src/__generated__/index.js +2 -0
  17. package/dist/src/config.d.ts +14 -0
  18. package/dist/src/config.js +57 -0
  19. package/dist/src/db/index.d.ts +89 -0
  20. package/dist/src/db/index.js +339 -0
  21. package/dist/src/db/internal.d.ts +7 -0
  22. package/dist/src/db/internal.js +33 -0
  23. package/dist/src/db/public.d.ts +7 -0
  24. package/dist/src/db/public.js +20 -0
  25. package/dist/src/db/types.d.ts +80 -0
  26. package/dist/src/db/types.js +1 -0
  27. package/dist/src/db/util.d.ts +6 -0
  28. package/dist/src/db/util.js +9 -0
  29. package/dist/src/express.d.ts +13 -0
  30. package/dist/src/express.js +1 -0
  31. package/dist/src/grafast.d.ts +1 -0
  32. package/dist/src/grafast.js +1 -0
  33. package/dist/src/graphile.d.ts +1 -0
  34. package/dist/src/graphile.js +1 -0
  35. package/dist/src/graphql-client.d.ts +6 -0
  36. package/dist/src/graphql-client.js +8 -0
  37. package/dist/src/graphql-queries.d.ts +18 -0
  38. package/dist/src/graphql-queries.js +123 -0
  39. package/dist/src/graphql.d.ts +1 -0
  40. package/dist/src/graphql.js +1 -0
  41. package/dist/src/index.d.ts +15 -0
  42. package/dist/src/index.js +65 -0
  43. package/dist/src/logger.d.ts +9 -0
  44. package/dist/src/logger.js +21 -0
  45. package/dist/src/pg-versions/001-schema.sql +456 -0
  46. package/dist/src/plugins/caas-add-casino.d.ts +1 -0
  47. package/dist/src/plugins/caas-add-casino.js +150 -0
  48. package/dist/src/plugins/caas-authenticate.d.ts +1 -0
  49. package/dist/src/plugins/caas-authenticate.js +175 -0
  50. package/dist/src/plugins/caas-balance-alert.d.ts +1 -0
  51. package/dist/src/plugins/caas-balance-alert.js +43 -0
  52. package/dist/src/plugins/caas-claim-faucet.d.ts +1 -0
  53. package/dist/src/plugins/caas-claim-faucet.js +85 -0
  54. package/dist/src/plugins/caas-current-x.d.ts +1 -0
  55. package/dist/src/plugins/caas-current-x.js +62 -0
  56. package/dist/src/plugins/caas-schema-prefix.d.ts +1 -0
  57. package/dist/src/plugins/caas-schema-prefix.js +25 -0
  58. package/dist/src/plugins/caas-user-balance-by-currency.d.ts +1 -0
  59. package/dist/src/plugins/caas-user-balance-by-currency.js +55 -0
  60. package/dist/src/plugins/caas-withdraw.d.ts +1 -0
  61. package/dist/src/plugins/caas-withdraw.js +133 -0
  62. package/dist/src/plugins/debug.d.ts +1 -0
  63. package/dist/src/plugins/debug.js +14 -0
  64. package/dist/src/plugins/hub-add-casino.d.ts +1 -0
  65. package/dist/src/plugins/hub-add-casino.js +150 -0
  66. package/dist/src/plugins/hub-authenticate.d.ts +1 -0
  67. package/dist/src/plugins/hub-authenticate.js +175 -0
  68. package/dist/src/plugins/hub-balance-alert.d.ts +1 -0
  69. package/dist/src/plugins/hub-balance-alert.js +43 -0
  70. package/dist/src/plugins/hub-claim-faucet.d.ts +1 -0
  71. package/dist/src/plugins/hub-claim-faucet.js +85 -0
  72. package/dist/src/plugins/hub-current-x.d.ts +1 -0
  73. package/dist/src/plugins/hub-current-x.js +62 -0
  74. package/dist/src/plugins/hub-schema-prefix.d.ts +1 -0
  75. package/dist/src/plugins/hub-schema-prefix.js +25 -0
  76. package/dist/src/plugins/hub-user-balance-by-currency.d.ts +1 -0
  77. package/dist/src/plugins/hub-user-balance-by-currency.js +55 -0
  78. package/dist/src/plugins/hub-withdraw.d.ts +1 -0
  79. package/dist/src/plugins/hub-withdraw.js +133 -0
  80. package/dist/src/plugins/id-to-node-id.d.ts +1 -0
  81. package/dist/src/plugins/id-to-node-id.js +31 -0
  82. package/dist/src/plugins/validate-fields.d.ts +1 -0
  83. package/dist/src/plugins/validate-fields.js +61 -0
  84. package/dist/src/process-transfers.d.ts +7 -0
  85. package/dist/src/process-transfers.js +413 -0
  86. package/dist/src/process-withdrawal-request.d.ts +5 -0
  87. package/dist/src/process-withdrawal-request.js +129 -0
  88. package/dist/src/server/graphile.config.d.ts +33 -0
  89. package/dist/src/server/graphile.config.js +166 -0
  90. package/dist/src/server/handle-errors.d.ts +10 -0
  91. package/dist/src/server/handle-errors.js +88 -0
  92. package/dist/src/server/index.d.ts +2 -0
  93. package/dist/src/server/index.js +69 -0
  94. package/dist/src/server/middleware/authentication.d.ts +4 -0
  95. package/dist/src/server/middleware/authentication.js +55 -0
  96. package/dist/src/server/middleware/cors.d.ts +3 -0
  97. package/dist/src/server/middleware/cors.js +14 -0
  98. package/dist/src/services/jwt-service.d.ts +13 -0
  99. package/dist/src/services/jwt-service.js +131 -0
  100. package/dist/src/smart-tags.d.ts +1 -0
  101. package/dist/src/smart-tags.js +55 -0
  102. package/dist/src/util.d.ts +12 -0
  103. package/dist/src/util.js +4 -0
  104. package/dist/src/validate.d.ts +9 -0
  105. package/dist/src/validate.js +91 -0
  106. package/package.json +69 -0
@@ -0,0 +1,133 @@
1
+ import { constant, context, object, sideEffect } from "postgraphile/grafast";
2
+ import { gql, makeExtendSchemaPlugin } from "postgraphile/utils";
3
+ import { superuserPool, withPgPoolTransaction, } from "../db/index.js";
4
+ import { exactlyOneRow, maybeOneRow } from "../db/util.js";
5
+ import { GraphQLError } from "graphql";
6
+ export const CaasWithdrawPlugin = makeExtendSchemaPlugin((build) => {
7
+ const caasWithdrawalRequests = build.input.pgRegistry.pgResources.caas_withdrawal_request;
8
+ return {
9
+ typeDefs: gql `
10
+ input CaasWithdrawInput {
11
+ amount: Int!
12
+ currency: String!
13
+ }
14
+
15
+ type CaasWithdrawPayload {
16
+ withdrawalRequest: CaasWithdrawalRequest!
17
+ query: Query
18
+ }
19
+
20
+ extend type Mutation {
21
+ caasWithdraw(input: CaasWithdrawInput!): CaasWithdrawPayload
22
+ }
23
+ `,
24
+ plans: {
25
+ Mutation: {
26
+ caasWithdraw(_, { $input }) {
27
+ const $identity = context().get("identity");
28
+ const $withdrawalRequestId = sideEffect([$input, $identity], ([input, identity]) => {
29
+ if (identity?.kind !== "user") {
30
+ throw new GraphQLError("You must be logged in");
31
+ }
32
+ const { session } = identity;
33
+ return withPgPoolTransaction(superuserPool, async (pgClient) => {
34
+ const { amount, currency } = input;
35
+ if (amount <= 0) {
36
+ throw new GraphQLError("Withdraw amount must be greater than zero");
37
+ }
38
+ if (!Number.isInteger(amount)) {
39
+ throw new GraphQLError("Withdraw amount must be an integer");
40
+ }
41
+ const dbCurrency = await pgClient
42
+ .query({
43
+ text: `
44
+ SELECT key
45
+ FROM caas.currency
46
+ WHERE key = $1 AND casino_id = $2
47
+ `,
48
+ values: [currency, session.casino_id],
49
+ })
50
+ .then(maybeOneRow);
51
+ if (!dbCurrency) {
52
+ throw new GraphQLError("Currency not supported");
53
+ }
54
+ const balance = await pgClient
55
+ .query({
56
+ text: `
57
+ select *
58
+ from caas.balance
59
+ where currency_key = $1
60
+ and user_id = $2
61
+ and casino_id = $3
62
+ and experience_id = $4
63
+
64
+ FOR UPDATE
65
+ `,
66
+ values: [
67
+ currency,
68
+ session.user_id,
69
+ session.casino_id,
70
+ session.experience_id,
71
+ ],
72
+ })
73
+ .then(maybeOneRow);
74
+ if (!balance || balance.amount < amount) {
75
+ throw new GraphQLError("Insufficient funds for withdrawal");
76
+ }
77
+ const dbWithdrawalRequest = await pgClient
78
+ .query({
79
+ text: `
80
+ insert into caas.withdrawal_request(
81
+ user_id,
82
+ experience_id,
83
+ casino_id,
84
+ amount,
85
+ currency_key
86
+ )
87
+ values ($1, $2, $3, $4, $5)
88
+ returning id
89
+ `,
90
+ values: [
91
+ session.user_id,
92
+ session.experience_id,
93
+ session.casino_id,
94
+ amount,
95
+ currency,
96
+ ],
97
+ })
98
+ .then(exactlyOneRow);
99
+ await pgClient.query({
100
+ text: `
101
+ update caas.balance
102
+ set amount = amount - $1
103
+ where user_id = $2
104
+ and experience_id = $3
105
+ and currency_key = $4
106
+ and casino_id = $5
107
+ `,
108
+ values: [
109
+ amount,
110
+ session.user_id,
111
+ session.experience_id,
112
+ currency,
113
+ session.casino_id,
114
+ ],
115
+ });
116
+ return dbWithdrawalRequest.id;
117
+ });
118
+ });
119
+ return object({
120
+ withdrawalRequestId: $withdrawalRequestId,
121
+ query: constant(true),
122
+ });
123
+ },
124
+ },
125
+ CaasWithdrawPayload: {
126
+ withdrawalRequest($data) {
127
+ const $id = $data.get("withdrawalRequestId");
128
+ return caasWithdrawalRequests.get({ id: $id });
129
+ },
130
+ },
131
+ },
132
+ };
133
+ });
@@ -0,0 +1 @@
1
+ export declare const DebugPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,14 @@
1
+ import { logger } from "../logger.js";
2
+ export const DebugPlugin = {
3
+ name: "DebugPlugin",
4
+ description: "A place to artificially slow down the server to test client",
5
+ version: "0.0.1",
6
+ grafserv: {
7
+ hooks: {
8
+ processGraphQLRequestBody(info, event) {
9
+ const { body } = event;
10
+ logger.debug("GraphQL request:", body.operationName, body.variableValues);
11
+ },
12
+ },
13
+ },
14
+ };
@@ -0,0 +1 @@
1
+ export declare const HubAddCasinoPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,150 @@
1
+ import { constant, context, object, sideEffect } from "postgraphile/grafast";
2
+ import { gql, makeExtendSchemaPlugin } from "postgraphile/utils";
3
+ import { exactlyOneRow } from "../db/util.js";
4
+ import { gql as generatedGql } from "../__generated__/gql.js";
5
+ import { GraphQLClient } from "graphql-request";
6
+ import { GraphQLError } from "graphql";
7
+ import { superuserPool, upsertCurrencies, withPgPoolTransaction, } from "../db/index.js";
8
+ import { logger } from "../logger.js";
9
+ import { assert, is } from "tsafe";
10
+ import * as jwtService from "../services/jwt-service.js";
11
+ import { startTransferProcessor } from "../process-transfers.js";
12
+ const GET_CURRENT_CONTROLLER = generatedGql(`
13
+ query GetCurrentController {
14
+ currentController {
15
+ id
16
+ }
17
+ allCurrencies {
18
+ nodes {
19
+ id
20
+ displayUnitName
21
+ displayUnitScale
22
+ }
23
+ }
24
+ }
25
+ `);
26
+ export const HubAddCasinoPlugin = makeExtendSchemaPlugin((build) => {
27
+ const casinoTable = build.input.pgRegistry.pgResources.hub_casino;
28
+ return {
29
+ typeDefs: gql `
30
+ input HubAddCasinoInput {
31
+ name: String!
32
+ baseUrl: String!
33
+ graphqlUrl: String!
34
+ apiKey: String!
35
+ }
36
+
37
+ type HubAddCasinoPayload {
38
+ casino: HubCasino
39
+ query: Query
40
+ }
41
+
42
+ extend type Mutation {
43
+ hubAddCasino(input: HubAddCasinoInput!): HubAddCasinoPayload
44
+ }
45
+ `,
46
+ plans: {
47
+ Mutation: {
48
+ hubAddCasino(_, { $input }) {
49
+ const $identity = context().get("identity");
50
+ const $casinoId = sideEffect([$input, $identity], ([input, identity]) => {
51
+ return withPgPoolTransaction(superuserPool, async (pgClient) => {
52
+ if (identity?.kind !== "operator") {
53
+ throw new GraphQLError("Unauthorized");
54
+ }
55
+ assert(is(input));
56
+ const { name, baseUrl, graphqlUrl, apiKey } = input;
57
+ const graphqlClient = new GraphQLClient(graphqlUrl, {
58
+ headers: {
59
+ Authorization: `apikey:${apiKey}`,
60
+ },
61
+ });
62
+ console.log(`[hubAddCasino] Making request to ${graphqlUrl}`);
63
+ const result = await graphqlClient
64
+ .request(GET_CURRENT_CONTROLLER)
65
+ .catch((e) => {
66
+ if (e.cause?.code === "ECONNREFUSED" ||
67
+ e.cause?.code === "ENOTFOUND") {
68
+ throw new GraphQLError(`Cannot connect to graphqlUrl`);
69
+ }
70
+ throw e;
71
+ });
72
+ if (!result) {
73
+ throw new GraphQLError("Invalid API key");
74
+ }
75
+ if (!result.currentController) {
76
+ throw new GraphQLError("Invalid API key");
77
+ }
78
+ let casino;
79
+ try {
80
+ casino = await pgClient
81
+ .query({
82
+ text: `
83
+ INSERT INTO hub.casino(name, base_url, graphql_url)
84
+ VALUES($1, $2, $3)
85
+ returning id
86
+ `,
87
+ values: [name, baseUrl, graphqlUrl],
88
+ })
89
+ .then((res) => {
90
+ console.log("res", res.rows);
91
+ return res;
92
+ })
93
+ .then(exactlyOneRow);
94
+ }
95
+ catch (e) {
96
+ if (e instanceof Error &&
97
+ "code" in e &&
98
+ e.code === "23505" &&
99
+ "constraint" in e) {
100
+ switch (e.constraint) {
101
+ case "casino_graphql_url_idx":
102
+ throw new GraphQLError("Casino with that graphqlUrl already exists");
103
+ case "casino_base_url_idx":
104
+ throw new GraphQLError("Casino with that baseUrl already exists");
105
+ default:
106
+ throw new GraphQLError(`Duplicate constraint violation: ${e.constraint}`);
107
+ }
108
+ }
109
+ logger.error("Error adding casino", e);
110
+ throw e;
111
+ }
112
+ await pgClient.query({
113
+ text: `
114
+ INSERT INTO hub.casino_secret(id, controller_id, api_key)
115
+ VALUES($1, $2, $3)
116
+ `,
117
+ values: [casino.id, result.currentController.id, apiKey],
118
+ });
119
+ const currencies = result.allCurrencies?.nodes.flatMap((x) => x || []) || [];
120
+ await upsertCurrencies(pgClient, {
121
+ casinoId: casino.id,
122
+ currencies,
123
+ });
124
+ await pgClient.query({
125
+ text: `
126
+ INSERT INTO hub.bankroll (casino_id, currency_key)
127
+ SELECT casino_id, key
128
+ FROM hub.currency
129
+ WHERE casino_id = $1
130
+ `,
131
+ values: [casino.id],
132
+ });
133
+ logger.info(`Fetching JWKS for new casino from ${graphqlUrl}...`);
134
+ await jwtService.refreshCasinoJwksTask(pgClient, {
135
+ graphqlClient,
136
+ casinoId: casino.id,
137
+ });
138
+ startTransferProcessor({ casinoId: casino.id });
139
+ return casino.id;
140
+ });
141
+ });
142
+ return object({
143
+ casino: casinoTable.get({ id: $casinoId }),
144
+ query: constant(true),
145
+ });
146
+ },
147
+ },
148
+ },
149
+ };
150
+ });
@@ -0,0 +1 @@
1
+ export declare const HubAuthenticatePlugin: GraphileConfig.Plugin;
@@ -0,0 +1,175 @@
1
+ import { GraphQLError } from "graphql";
2
+ import { gql, makeExtendSchemaPlugin } from "postgraphile/utils";
3
+ import { assert, is } from "tsafe";
4
+ import { GET_USER_FROM_USER_TOKEN } from "../graphql-queries.js";
5
+ import { exactlyOneRow, maybeOneRow } from "../db/util.js";
6
+ import { createGraphqlClient } from "../graphql-client.js";
7
+ import { constant, context, error, object, sideEffect, } from "postgraphile/grafast";
8
+ import { superuserPool, withPgPoolTransaction, } from "../db/index.js";
9
+ import { logger } from "../logger.js";
10
+ import * as jwtService from "../services/jwt-service.js";
11
+ import { extractGraphQLErrorInfo, isGraphQLError } from "../GraphQLError.js";
12
+ export const HubAuthenticatePlugin = makeExtendSchemaPlugin(() => {
13
+ return {
14
+ typeDefs: gql `
15
+ input HubAuthenticateInput {
16
+ casinoBaseUrl: String!
17
+ userToken: String!
18
+ }
19
+
20
+ type HubAuthenticateSuccess {
21
+ experienceId: UUID!
22
+ sessionKey: UUID!
23
+ userId: UUID!
24
+ uname: String!
25
+ }
26
+
27
+ type HubAuthenticatePayload {
28
+ query: Query
29
+ success: HubAuthenticateSuccess
30
+ }
31
+
32
+ extend type Mutation {
33
+ hubAuthenticate(input: HubAuthenticateInput!): HubAuthenticatePayload
34
+ }
35
+ `,
36
+ plans: {
37
+ Mutation: {
38
+ hubAuthenticate(_, { $input }) {
39
+ try {
40
+ const $context = context();
41
+ const $success = sideEffect([$input, $context], ([input, context]) => {
42
+ return withPgPoolTransaction(superuserPool, async (pgClient) => {
43
+ assert(is(input));
44
+ const { userToken: jwt, casinoBaseUrl } = input;
45
+ const casino = await pgClient
46
+ .query({
47
+ text: `
48
+ SELECT c.*, s.api_key
49
+ FROM hub.casino c
50
+ LEFT JOIN hub.casino_secret s ON c.id = s.id
51
+ WHERE c.base_url = $1`,
52
+ values: [casinoBaseUrl],
53
+ })
54
+ .then(maybeOneRow);
55
+ if (!casino) {
56
+ throw new GraphQLError(`CAAS is unaware of casino with a base url of provided casinoBaseUrl`);
57
+ }
58
+ if (!casino.api_key) {
59
+ throw new GraphQLError("Casino secret not configured");
60
+ }
61
+ const graphqlClient = createGraphqlClient({
62
+ graphqlUrl: casino.graphql_url,
63
+ apiKey: casino.api_key,
64
+ });
65
+ const verifyResult = await jwtService.verifyJwtFromDbCacheAndEnsureNotAlreadyUsed(pgClient, {
66
+ casinoId: casino.id,
67
+ jwt,
68
+ });
69
+ if (!verifyResult.ok) {
70
+ throw new GraphQLError(`Error verifying userToken: ${verifyResult.error}`);
71
+ }
72
+ const { userToken } = verifyResult.value;
73
+ let res;
74
+ try {
75
+ res = await graphqlClient.request(GET_USER_FROM_USER_TOKEN, {
76
+ token: userToken,
77
+ });
78
+ }
79
+ catch (e) {
80
+ logger.error(`[hubAuthenticate] Error when making GET_USER_FROM_USER_TOKEN to casino:`, e);
81
+ if (isGraphQLError(e)) {
82
+ const errorInfo = extractGraphQLErrorInfo(e);
83
+ if (errorInfo.code === "UNAUTHENTICATED") {
84
+ throw new GraphQLError("Invalid api key");
85
+ }
86
+ else {
87
+ throw new GraphQLError(errorInfo.message);
88
+ }
89
+ }
90
+ throw error;
91
+ }
92
+ const result = res.userFromUserToken;
93
+ if (!result || !result.user || !result.experience) {
94
+ return null;
95
+ }
96
+ const mpUserId = result.user.id;
97
+ assert(mpUserId);
98
+ const uname = result.user.uname;
99
+ assert(uname);
100
+ const dbUser = await pgClient
101
+ .query({
102
+ text: `
103
+ INSERT INTO hub.user(casino_id, mp_user_id, uname)
104
+ VALUES($1, $2, $3)
105
+ ON CONFLICT (casino_id, mp_user_id) DO UPDATE
106
+ SET uname = EXCLUDED.uname
107
+ RETURNING id, uname
108
+ `,
109
+ values: [casino.id, mpUserId, uname],
110
+ })
111
+ .then(exactlyOneRow);
112
+ const userId = dbUser.id;
113
+ const mpExperience = result.experience;
114
+ assert(mpExperience);
115
+ const dbExperience = await pgClient
116
+ .query({
117
+ text: `
118
+ INSERT INTO hub.experience(casino_id, mp_experience_id, name)
119
+ VALUES($1, $2, $3)
120
+ ON CONFLICT (casino_id, mp_experience_id) DO UPDATE
121
+ SET name = EXCLUDED.name
122
+ RETURNING id
123
+ `,
124
+ values: [casino.id, mpExperience.id, mpExperience.name],
125
+ })
126
+ .then(exactlyOneRow);
127
+ const dbSession = await pgClient
128
+ .query({
129
+ text: `
130
+ INSERT INTO hub.session(casino_id, user_id, experience_id, user_token)
131
+ VALUES($1, $2, $3, $4)
132
+ RETURNING id, key
133
+ `,
134
+ values: [casino.id, userId, dbExperience.id, userToken],
135
+ })
136
+ .then(exactlyOneRow);
137
+ const ret = {
138
+ userId,
139
+ uname: dbUser.uname,
140
+ experienceId: dbExperience.id,
141
+ sessionKey: dbSession.key,
142
+ };
143
+ context.identity = {
144
+ kind: "user",
145
+ session: {
146
+ user_id: userId,
147
+ mp_user_id: mpUserId,
148
+ casino_id: casino.id,
149
+ experience_id: dbExperience.id,
150
+ session_id: dbSession.id,
151
+ },
152
+ };
153
+ context.pgSettings = {
154
+ "session.user_id": userId,
155
+ "session.casino_id": casino.id,
156
+ "session.experience_id": dbExperience.id,
157
+ "session.session_id": dbSession.id,
158
+ };
159
+ return ret;
160
+ });
161
+ });
162
+ return object({
163
+ query: constant(true),
164
+ success: $success,
165
+ });
166
+ }
167
+ catch (error) {
168
+ logger.error(error);
169
+ throw error;
170
+ }
171
+ },
172
+ },
173
+ },
174
+ };
175
+ });
@@ -0,0 +1 @@
1
+ export declare const HubBalanceAlertPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,43 @@
1
+ import { makeExtendSchemaPlugin, gql } from "postgraphile/utils";
2
+ import { context, lambda, listen } from "postgraphile/grafast";
3
+ import { jsonParse } from "postgraphile/@dataplan/json";
4
+ export const HubBalanceAlertPlugin = makeExtendSchemaPlugin(() => {
5
+ return {
6
+ typeDefs: gql `
7
+ extend type Subscription {
8
+ hubBalanceAlert: HubBalanceAlertPayload
9
+ }
10
+
11
+ type HubBalanceAlertPayload {
12
+ currencyKey: String
13
+ }
14
+ `,
15
+ plans: {
16
+ Subscription: {
17
+ hubBalanceAlert: {
18
+ subscribePlan(_$root) {
19
+ const $pgSubscriber = context().get("pgSubscriber");
20
+ const $identity = context().get("identity");
21
+ const $channelKey = lambda($identity, (identity) => {
22
+ if (identity?.kind === "user") {
23
+ return `hub:user:${identity.session.user_id}:balance_alert`;
24
+ }
25
+ else {
26
+ return "";
27
+ }
28
+ });
29
+ return listen($pgSubscriber, $channelKey, jsonParse);
30
+ },
31
+ plan($event) {
32
+ return $event;
33
+ },
34
+ },
35
+ },
36
+ HubBalanceAlertPayload: {
37
+ currencyKey($event) {
38
+ return $event.get("currency_key");
39
+ },
40
+ },
41
+ },
42
+ };
43
+ });
@@ -0,0 +1 @@
1
+ export declare const HubClaimFaucetPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,85 @@
1
+ import { object } from "grafast";
2
+ import { gql, makeExtendSchemaPlugin } from "postgraphile/utils";
3
+ import { superuserPool, withPgPoolTransaction } from "../db/index.js";
4
+ import { constant, context, sideEffect } from "postgraphile/grafast";
5
+ const CLAIM_AMOUNT = 1000;
6
+ export const HubClaimFaucetPlugin = makeExtendSchemaPlugin(() => {
7
+ return {
8
+ typeDefs: gql `
9
+ type HubClaimFaucetPayload {
10
+ success: Boolean!
11
+ query: Query
12
+ }
13
+
14
+ extend type Mutation {
15
+ hubClaimFaucet: HubClaimFaucetPayload
16
+ }
17
+ `,
18
+ plans: {
19
+ Mutation: {
20
+ hubClaimFaucet() {
21
+ const $identity = context().get("identity");
22
+ const $result = sideEffect([$identity], ([identity]) => {
23
+ if (identity?.kind !== "user") {
24
+ throw new Error("Must be logged in as user");
25
+ }
26
+ const { session } = identity;
27
+ return withPgPoolTransaction(superuserPool, async (pgClient) => {
28
+ await upsertPlayCurrency(pgClient, session.casino_id);
29
+ await pgClient.query({
30
+ text: `
31
+ insert into hub.faucet_claim (user_id, casino_id, experience_id, currency_key, amount)
32
+ values ($1, $2, $3, $4, $5)
33
+ `,
34
+ values: [
35
+ session.user_id,
36
+ session.casino_id,
37
+ session.experience_id,
38
+ "PLAY",
39
+ CLAIM_AMOUNT,
40
+ ],
41
+ });
42
+ await pgClient.query({
43
+ text: `
44
+ INSERT INTO hub.balance (user_id, experience_id, casino_id, currency_key, amount)
45
+ VALUES ($1, $2, $3, $4, $5)
46
+ ON CONFLICT (user_id, experience_id, casino_id, currency_key) DO UPDATE
47
+ SET amount = balance.amount + EXCLUDED.amount
48
+ `,
49
+ values: [
50
+ session.user_id,
51
+ session.experience_id,
52
+ session.casino_id,
53
+ "PLAY",
54
+ CLAIM_AMOUNT,
55
+ ],
56
+ });
57
+ return true;
58
+ });
59
+ });
60
+ return object({
61
+ result: $result,
62
+ });
63
+ },
64
+ },
65
+ HubClaimFaucetPayload: {
66
+ success($data) {
67
+ return $data.get("result");
68
+ },
69
+ query() {
70
+ return constant(true);
71
+ },
72
+ },
73
+ },
74
+ };
75
+ });
76
+ async function upsertPlayCurrency(pgClient, casinoId) {
77
+ return pgClient.query({
78
+ text: `
79
+ insert into hub.currency (casino_id, key, display_unit_name, display_unit_scale)
80
+ values ($1, 'PLAY', 'tokens', 1)
81
+ on conflict (casino_id, key) do nothing
82
+ `,
83
+ values: [casinoId],
84
+ });
85
+ }
@@ -0,0 +1 @@
1
+ export declare const HubCurrentXPlugin: GraphileConfig.Plugin;