@moneypot/hub 1.4.10 → 1.5.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.
- package/README.md +10 -3
- package/dist/src/hash-chain/plugins/hub-bad-hash-chain-error.js +7 -5
- package/dist/src/hash-chain/plugins/hub-create-hash-chain.js +42 -40
- package/dist/src/hash-chain/plugins/hub-user-active-hash-chain.js +19 -17
- package/dist/src/index.d.ts +17 -1
- package/dist/src/plugins/hub-add-casino.js +89 -87
- package/dist/src/plugins/hub-authenticate.js +120 -118
- package/dist/src/plugins/hub-balance-alert.js +23 -19
- package/dist/src/plugins/hub-claim-faucet.js +43 -39
- package/dist/src/plugins/hub-current-x.js +43 -41
- package/dist/src/plugins/hub-make-outcome-bet.js +230 -227
- package/dist/src/plugins/hub-put-alert.js +38 -34
- package/dist/src/plugins/hub-user-balance-by-currency.js +9 -7
- package/dist/src/plugins/hub-withdraw.js +72 -68
- package/dist/src/server/graphile.config.d.ts +0 -11
- package/dist/src/server/graphile.config.js +5 -5
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @moneypot/hub
|
|
2
2
|
|
|
3
|
-
@moneypot/hub is our official game server
|
|
3
|
+
@moneypot/hub is our official GraphQL game server for building games for [MoneyPot.com](https://moneypot.com).
|
|
4
4
|
|
|
5
5
|
- Extend it with custom tables and game logic.
|
|
6
6
|
- Give it an api key for each controller you've registered on each casino.
|
|
@@ -13,7 +13,7 @@ Example implementations:
|
|
|
13
13
|
|
|
14
14
|
## Manual
|
|
15
15
|
|
|
16
|
-
View our docs: https://moneypot.com
|
|
16
|
+
View our docs: <https://docs.moneypot.com>
|
|
17
17
|
|
|
18
18
|
## Install
|
|
19
19
|
|
|
@@ -76,4 +76,11 @@ insert into hub.api_key default values returning key;
|
|
|
76
76
|
|
|
77
77
|
## Changelog
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
### 1.5.x
|
|
80
|
+
|
|
81
|
+
Migrated to Postgraphile beta.52 which has new plugin and polymorphism systems:
|
|
82
|
+
|
|
83
|
+
Read more:
|
|
84
|
+
|
|
85
|
+
- https://www.graphile.org/news/20250607-last-epic-solved/
|
|
86
|
+
- https://grafast.org/grafast/polymorphism
|
|
@@ -7,12 +7,14 @@ export const HubBadHashChainErrorPlugin = makeExtendSchemaPlugin(() => {
|
|
|
7
7
|
message: String
|
|
8
8
|
}
|
|
9
9
|
`,
|
|
10
|
-
|
|
10
|
+
objects: {
|
|
11
11
|
HubBadHashChainError: {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
assertStep: ObjectStep,
|
|
13
|
+
plans: {
|
|
14
|
+
message($data) {
|
|
15
|
+
const $message = access($data, "message");
|
|
16
|
+
return $message;
|
|
17
|
+
},
|
|
16
18
|
},
|
|
17
19
|
},
|
|
18
20
|
},
|
|
@@ -18,21 +18,22 @@ export const HubCreateHashChainPlugin = makeExtendSchemaPlugin((build) => {
|
|
|
18
18
|
hubCreateHashChain: HubCreateHashChainPayload!
|
|
19
19
|
}
|
|
20
20
|
`,
|
|
21
|
-
|
|
21
|
+
objects: {
|
|
22
22
|
Mutation: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
plans: {
|
|
24
|
+
hubCreateHashChain: () => {
|
|
25
|
+
const $identity = context().get("identity");
|
|
26
|
+
const $hashChainId = sideEffect([$identity], ([identity]) => {
|
|
27
|
+
if (identity?.kind !== "user") {
|
|
28
|
+
throw new GraphQLError("Unauthorized");
|
|
29
|
+
}
|
|
30
|
+
return withPgPoolTransaction(superuserPool, async (pgClient) => {
|
|
31
|
+
await PgAdvisoryLock.forNewHashChain(pgClient, {
|
|
32
|
+
userId: identity.session.user_id,
|
|
33
|
+
experienceId: identity.session.experience_id,
|
|
34
|
+
casinoId: identity.session.casino_id,
|
|
35
|
+
});
|
|
36
|
+
await pgClient.query(`
|
|
36
37
|
UPDATE hub.hash_chain
|
|
37
38
|
SET active = false
|
|
38
39
|
WHERE user_id = $1
|
|
@@ -40,12 +41,12 @@ export const HubCreateHashChainPlugin = makeExtendSchemaPlugin((build) => {
|
|
|
40
41
|
AND casino_id = $3
|
|
41
42
|
AND active = true
|
|
42
43
|
`, [
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
identity.session.user_id,
|
|
45
|
+
identity.session.experience_id,
|
|
46
|
+
identity.session.casino_id,
|
|
47
|
+
]);
|
|
48
|
+
const dbHashChain = await pgClient
|
|
49
|
+
.query(`
|
|
49
50
|
INSERT INTO hub.hash_chain (
|
|
50
51
|
user_id,
|
|
51
52
|
experience_id,
|
|
@@ -57,16 +58,16 @@ export const HubCreateHashChainPlugin = makeExtendSchemaPlugin((build) => {
|
|
|
57
58
|
VALUES ($1, $2, $3, true, $4, $4)
|
|
58
59
|
RETURNING *
|
|
59
60
|
`, [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
identity.session.user_id,
|
|
62
|
+
identity.session.experience_id,
|
|
63
|
+
identity.session.casino_id,
|
|
64
|
+
config.HASHCHAINSERVER_MAX_ITERATIONS,
|
|
65
|
+
])
|
|
66
|
+
.then(exactlyOneRow);
|
|
67
|
+
const terminalHash = await HashCommon.getTerminalHash({
|
|
68
|
+
hashChainId: dbHashChain.id,
|
|
69
|
+
});
|
|
70
|
+
await pgClient.query(`
|
|
70
71
|
INSERT INTO hub.hash (
|
|
71
72
|
hash_chain_id,
|
|
72
73
|
kind,
|
|
@@ -75,17 +76,18 @@ export const HubCreateHashChainPlugin = makeExtendSchemaPlugin((build) => {
|
|
|
75
76
|
)
|
|
76
77
|
VALUES ($1, $2, $3, $4)
|
|
77
78
|
`, [
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
dbHashChain.id,
|
|
80
|
+
DbHashKind.TERMINAL,
|
|
81
|
+
terminalHash,
|
|
82
|
+
config.HASHCHAINSERVER_MAX_ITERATIONS,
|
|
83
|
+
]);
|
|
84
|
+
return dbHashChain.id;
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
return object({
|
|
88
|
+
hashChain: hashChainTable.get({ id: $hashChainId }),
|
|
84
89
|
});
|
|
85
|
-
}
|
|
86
|
-
return object({
|
|
87
|
-
hashChain: hashChainTable.get({ id: $hashChainId }),
|
|
88
|
-
});
|
|
90
|
+
},
|
|
89
91
|
},
|
|
90
92
|
},
|
|
91
93
|
},
|
|
@@ -12,18 +12,19 @@ export const HubUserActiveHashChainPlugin = makeExtendSchemaPlugin((build) => {
|
|
|
12
12
|
activeHashChain: HubHashChain
|
|
13
13
|
}
|
|
14
14
|
`,
|
|
15
|
-
|
|
15
|
+
objects: {
|
|
16
16
|
HubUser: {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
plans: {
|
|
18
|
+
activeHashChain: ($record) => {
|
|
19
|
+
const $identity = context().get("identity");
|
|
20
|
+
const $hashChainId = withPgClient(hashChainTable.executor, object({ userId: $record.get("id"), identity: $identity }), async (pgClient, { userId, identity }) => {
|
|
21
|
+
if (identity?.kind !== "user") {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const { session } = identity;
|
|
25
|
+
const activeHashChain = await pgClient
|
|
26
|
+
.query({
|
|
27
|
+
text: `
|
|
27
28
|
select id
|
|
28
29
|
from hub.hash_chain
|
|
29
30
|
where user_id = $1
|
|
@@ -33,12 +34,13 @@ export const HubUserActiveHashChainPlugin = makeExtendSchemaPlugin((build) => {
|
|
|
33
34
|
order by id desc
|
|
34
35
|
limit 1
|
|
35
36
|
`,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
values: [userId, session.experience_id, session.casino_id],
|
|
38
|
+
})
|
|
39
|
+
.then(maybeOneRow);
|
|
40
|
+
return activeHashChain?.id ?? null;
|
|
41
|
+
});
|
|
42
|
+
return hashChainTable.get({ id: inhibitOnNull($hashChainId) });
|
|
43
|
+
},
|
|
42
44
|
},
|
|
43
45
|
},
|
|
44
46
|
},
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import { Express } from "express";
|
|
2
2
|
import { Logger } from "./logger.js";
|
|
3
|
+
import { PluginIdentity } from "./server/graphile.config.js";
|
|
4
|
+
declare global {
|
|
5
|
+
namespace Grafast {
|
|
6
|
+
interface Context {
|
|
7
|
+
identity?: PluginIdentity;
|
|
8
|
+
abortSignal: AbortSignal;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
declare global {
|
|
13
|
+
namespace GraphileBuild {
|
|
14
|
+
interface SchemaOptions {
|
|
15
|
+
pgDeletedColumnName?: string;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
3
19
|
export { MakeOutcomeBetPlugin, type OutcomeBetConfigMap, type OutcomeBetConfig, } from "./plugins/hub-make-outcome-bet.js";
|
|
4
|
-
export { defaultPlugins, type
|
|
20
|
+
export { defaultPlugins, type PluginIdentity, type UserSessionContext, } from "./server/graphile.config.js";
|
|
5
21
|
export type ServerOptions = {
|
|
6
22
|
configureApp?: (app: Express) => void;
|
|
7
23
|
plugins?: readonly GraphileConfig.Plugin[];
|
|
@@ -43,115 +43,117 @@ export const HubAddCasinoPlugin = makeExtendSchemaPlugin((build) => {
|
|
|
43
43
|
hubAddCasino(input: HubAddCasinoInput!): HubAddCasinoPayload
|
|
44
44
|
}
|
|
45
45
|
`,
|
|
46
|
-
|
|
46
|
+
objects: {
|
|
47
47
|
Mutation: {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
assert(is(input));
|
|
57
|
-
const { name, baseUrl, graphqlUrl, apiKey } = input;
|
|
58
|
-
const graphqlClient = new GraphQLClient(graphqlUrl, {
|
|
59
|
-
headers: {
|
|
60
|
-
Authorization: `apikey:${apiKey}`,
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
console.log(`[hubAddCasino] Making request to ${graphqlUrl}`);
|
|
64
|
-
const result = await graphqlClient
|
|
65
|
-
.request(GET_CURRENT_CONTROLLER)
|
|
66
|
-
.catch((e) => {
|
|
67
|
-
if (e.cause?.code === "ECONNREFUSED" ||
|
|
68
|
-
e.cause?.code === "ENOTFOUND") {
|
|
69
|
-
throw new GraphQLError(`Cannot connect to graphqlUrl`);
|
|
48
|
+
plans: {
|
|
49
|
+
hubAddCasino(_, { $input }) {
|
|
50
|
+
const $identity = context().get("identity");
|
|
51
|
+
const $abortSignal = context().get("abortSignal");
|
|
52
|
+
const $casinoId = sideEffect([$input, $identity, $abortSignal], ([input, identity, abortSignal]) => {
|
|
53
|
+
return withPgPoolTransaction(superuserPool, async (pgClient) => {
|
|
54
|
+
if (identity?.kind !== "operator") {
|
|
55
|
+
throw new GraphQLError("Unauthorized");
|
|
70
56
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
57
|
+
assert(is(input));
|
|
58
|
+
const { name, baseUrl, graphqlUrl, apiKey } = input;
|
|
59
|
+
const graphqlClient = new GraphQLClient(graphqlUrl, {
|
|
60
|
+
headers: {
|
|
61
|
+
Authorization: `apikey:${apiKey}`,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
console.log(`[hubAddCasino] Making request to ${graphqlUrl}`);
|
|
65
|
+
const result = await graphqlClient
|
|
66
|
+
.request(GET_CURRENT_CONTROLLER)
|
|
67
|
+
.catch((e) => {
|
|
68
|
+
if (e.cause?.code === "ECONNREFUSED" ||
|
|
69
|
+
e.cause?.code === "ENOTFOUND") {
|
|
70
|
+
throw new GraphQLError(`Cannot connect to graphqlUrl`);
|
|
71
|
+
}
|
|
72
|
+
throw e;
|
|
73
|
+
});
|
|
74
|
+
if (!result || !result.currentController) {
|
|
75
|
+
throw new GraphQLError("Invalid API key for your casino controller. Go to your controller on the casino website and double check.");
|
|
76
|
+
}
|
|
77
|
+
let casino;
|
|
78
|
+
try {
|
|
79
|
+
casino = await pgClient
|
|
80
|
+
.query({
|
|
81
|
+
text: `
|
|
81
82
|
INSERT INTO hub.casino(name, base_url, graphql_url)
|
|
82
83
|
VALUES($1, $2, $3)
|
|
83
84
|
returning id
|
|
84
85
|
`,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
86
|
+
values: [name, baseUrl, graphqlUrl],
|
|
87
|
+
})
|
|
88
|
+
.then((res) => {
|
|
89
|
+
console.log("res", res.rows);
|
|
90
|
+
return res;
|
|
91
|
+
})
|
|
92
|
+
.then(exactlyOneRow);
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
if (e instanceof Error &&
|
|
96
|
+
"code" in e &&
|
|
97
|
+
e.code === "23505" &&
|
|
98
|
+
"constraint" in e) {
|
|
99
|
+
switch (e.constraint) {
|
|
100
|
+
case "casino_graphql_url_idx":
|
|
101
|
+
throw new GraphQLError("Casino with that graphqlUrl already exists");
|
|
102
|
+
case "casino_base_url_idx":
|
|
103
|
+
throw new GraphQLError("Casino with that baseUrl already exists");
|
|
104
|
+
default:
|
|
105
|
+
throw new GraphQLError(`Duplicate constraint violation: ${e.constraint}`);
|
|
106
|
+
}
|
|
105
107
|
}
|
|
108
|
+
logger.error("Error adding casino", e);
|
|
109
|
+
throw e;
|
|
106
110
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
await pgClient.query({
|
|
111
|
-
text: `
|
|
111
|
+
await pgClient.query({
|
|
112
|
+
text: `
|
|
112
113
|
INSERT INTO hub.casino_secret(id, controller_id, api_key)
|
|
113
114
|
VALUES($1, $2, $3)
|
|
114
115
|
`,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
116
|
+
values: [casino.id, result.currentController.id, apiKey],
|
|
117
|
+
});
|
|
118
|
+
const currencies = result.allCurrencies?.nodes.flatMap((x) => x || []) || [];
|
|
119
|
+
await upsertCurrencies(pgClient, {
|
|
120
|
+
casinoId: casino.id,
|
|
121
|
+
currencies,
|
|
122
|
+
});
|
|
123
|
+
await pgClient.query({
|
|
124
|
+
text: `
|
|
124
125
|
INSERT INTO hub.bankroll (casino_id, currency_key)
|
|
125
126
|
SELECT casino_id, key
|
|
126
127
|
FROM hub.currency
|
|
127
128
|
WHERE casino_id = $1
|
|
128
129
|
`,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
130
|
+
values: [casino.id],
|
|
131
|
+
});
|
|
132
|
+
await pgClient.query({
|
|
133
|
+
text: `
|
|
133
134
|
UPDATE hub.bankroll
|
|
134
135
|
SET amount = 1000000
|
|
135
136
|
WHERE casino_id = $1 AND currency_key = 'HOUSE'
|
|
136
137
|
`,
|
|
137
|
-
|
|
138
|
+
values: [casino.id],
|
|
139
|
+
});
|
|
140
|
+
logger.info(`Fetching JWKS for new casino from ${graphqlUrl}...`);
|
|
141
|
+
await jwtService.refreshCasinoJwksTask(pgClient, {
|
|
142
|
+
graphqlClient,
|
|
143
|
+
casinoId: casino.id,
|
|
144
|
+
});
|
|
145
|
+
startTransferProcessor({
|
|
146
|
+
casinoId: casino.id,
|
|
147
|
+
signal: abortSignal,
|
|
148
|
+
});
|
|
149
|
+
return casino.id;
|
|
138
150
|
});
|
|
139
|
-
logger.info(`Fetching JWKS for new casino from ${graphqlUrl}...`);
|
|
140
|
-
await jwtService.refreshCasinoJwksTask(pgClient, {
|
|
141
|
-
graphqlClient,
|
|
142
|
-
casinoId: casino.id,
|
|
143
|
-
});
|
|
144
|
-
startTransferProcessor({
|
|
145
|
-
casinoId: casino.id,
|
|
146
|
-
signal: abortSignal,
|
|
147
|
-
});
|
|
148
|
-
return casino.id;
|
|
149
151
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
152
|
+
return object({
|
|
153
|
+
casino: casinoTable.get({ id: $casinoId }),
|
|
154
|
+
query: constant(true),
|
|
155
|
+
});
|
|
156
|
+
},
|
|
155
157
|
},
|
|
156
158
|
},
|
|
157
159
|
},
|