@moneypot/hub 1.3.0-dev.15 → 1.3.0-dev.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/config.d.ts +13 -8
- package/dist/src/config.js +52 -78
- package/dist/src/db/index.d.ts +0 -1
- package/dist/src/db/index.js +1 -2
- package/dist/src/db/types.d.ts +0 -28
- package/dist/src/db/types.js +1 -5
- package/dist/src/index.js +1 -1
- package/dist/src/pg-advisory-lock.d.ts +4 -9
- package/dist/src/pg-advisory-lock.js +1 -8
- package/dist/src/pg-versions/{006-outcome-bet.sql → 005-outcome-bet.sql} +1 -8
- package/dist/src/plugins/hub-make-outcome-bet.d.ts +9 -36
- package/dist/src/plugins/hub-make-outcome-bet.js +25 -186
- package/dist/src/plugins/hub-user-balance-by-currency.js +40 -15
- package/dist/src/process-transfers.js +1 -1
- package/dist/src/server/graphile.config.js +1 -9
- package/dist/src/server/handle-errors.js +1 -1
- package/dist/src/server/index.js +1 -1
- package/dist/src/take-request/process-take-request.js +3 -3
- package/package.json +1 -1
- package/dist/src/hash-chain/db-hash-chain.d.ts +0 -15
- package/dist/src/hash-chain/db-hash-chain.js +0 -35
- package/dist/src/hash-chain/get-hash.d.ts +0 -17
- package/dist/src/hash-chain/get-hash.js +0 -57
- package/dist/src/hash-chain/plugins/hub-bad-hash-chain-error.d.ts +0 -1
- package/dist/src/hash-chain/plugins/hub-bad-hash-chain-error.js +0 -20
- package/dist/src/hash-chain/plugins/hub-create-hash-chain.d.ts +0 -1
- package/dist/src/hash-chain/plugins/hub-create-hash-chain.js +0 -111
- package/dist/src/hash-chain/plugins/hub-user-active-hash-chain.d.ts +0 -1
- package/dist/src/hash-chain/plugins/hub-user-active-hash-chain.js +0 -46
- package/dist/src/pg-versions/005-hash-chain.sql +0 -84
- package/dist/src/plugins/hub-outcome-input-non-null-fields.d.ts +0 -18
- package/dist/src/plugins/hub-outcome-input-non-null-fields.js +0 -20
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { context, object, sideEffect } from "@moneypot/hub/grafast";
|
|
2
|
-
import { gql, makeExtendSchemaPlugin } from "@moneypot/hub/graphile";
|
|
3
|
-
import { GraphQLError } from "graphql";
|
|
4
|
-
import { z } from "zod";
|
|
5
|
-
import { PgAdvisoryLock } from "../../pg-advisory-lock.js";
|
|
6
|
-
import { exactlyOneRow, superuserPool, withPgPoolTransaction, } from "@moneypot/hub/db";
|
|
7
|
-
import * as HashCommon from "../get-hash.js";
|
|
8
|
-
import { DbHashKind } from "../../db/types.js";
|
|
9
|
-
import * as config from "../../config.js";
|
|
10
|
-
const InputSchema = z.object({
|
|
11
|
-
clientSeed: z.string(),
|
|
12
|
-
});
|
|
13
|
-
export const HubCreateHashChainPlugin = makeExtendSchemaPlugin((build) => {
|
|
14
|
-
const hashChainTable = build.input.pgRegistry.pgResources.hub_hash_chain;
|
|
15
|
-
return {
|
|
16
|
-
typeDefs: gql `
|
|
17
|
-
input HubCreateHashChainInput {
|
|
18
|
-
clientSeed: String!
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
type HubCreateHashChainPayload {
|
|
22
|
-
hashChain: HubHashChain!
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
extend type Mutation {
|
|
26
|
-
hubCreateHashChain(
|
|
27
|
-
input: HubCreateHashChainInput!
|
|
28
|
-
): HubCreateHashChainPayload!
|
|
29
|
-
}
|
|
30
|
-
`,
|
|
31
|
-
plans: {
|
|
32
|
-
Mutation: {
|
|
33
|
-
hubCreateHashChain: (_, { $input }) => {
|
|
34
|
-
const $identity = context().get("identity");
|
|
35
|
-
const $hashChainId = sideEffect([$input, $identity], ([rawInput, identity]) => {
|
|
36
|
-
if (identity?.kind !== "user") {
|
|
37
|
-
throw new GraphQLError("Unauthorized");
|
|
38
|
-
}
|
|
39
|
-
const result = InputSchema.safeParse(rawInput);
|
|
40
|
-
if (!result.success) {
|
|
41
|
-
const message = result.error.errors[0].message;
|
|
42
|
-
throw new GraphQLError(message);
|
|
43
|
-
}
|
|
44
|
-
const { clientSeed } = result.data;
|
|
45
|
-
return withPgPoolTransaction(superuserPool, async (pgClient) => {
|
|
46
|
-
await PgAdvisoryLock.forNewHashChain(pgClient, {
|
|
47
|
-
userId: identity.session.user_id,
|
|
48
|
-
experienceId: identity.session.experience_id,
|
|
49
|
-
casinoId: identity.session.casino_id,
|
|
50
|
-
});
|
|
51
|
-
await pgClient.query(`
|
|
52
|
-
UPDATE hub.hash_chain
|
|
53
|
-
SET active = false
|
|
54
|
-
WHERE user_id = $1
|
|
55
|
-
AND experience_id = $2
|
|
56
|
-
AND casino_id = $3
|
|
57
|
-
AND active = true
|
|
58
|
-
`, [
|
|
59
|
-
identity.session.user_id,
|
|
60
|
-
identity.session.experience_id,
|
|
61
|
-
identity.session.casino_id,
|
|
62
|
-
]);
|
|
63
|
-
const dbHashChain = await pgClient
|
|
64
|
-
.query(`
|
|
65
|
-
INSERT INTO hub.hash_chain (
|
|
66
|
-
user_id,
|
|
67
|
-
experience_id,
|
|
68
|
-
casino_id,
|
|
69
|
-
client_seed,
|
|
70
|
-
active,
|
|
71
|
-
max_iteration,
|
|
72
|
-
current_iteration
|
|
73
|
-
)
|
|
74
|
-
VALUES ($1, $2, $3, $4, true, $5, $5)
|
|
75
|
-
RETURNING *
|
|
76
|
-
`, [
|
|
77
|
-
identity.session.user_id,
|
|
78
|
-
identity.session.experience_id,
|
|
79
|
-
identity.session.casino_id,
|
|
80
|
-
clientSeed,
|
|
81
|
-
config.HASHCHAINSERVER_MAX_ITERATIONS,
|
|
82
|
-
])
|
|
83
|
-
.then(exactlyOneRow);
|
|
84
|
-
const terminalHash = await HashCommon.getTerminalHash({
|
|
85
|
-
hashChainId: dbHashChain.id,
|
|
86
|
-
});
|
|
87
|
-
await pgClient.query(`
|
|
88
|
-
INSERT INTO hub.hash (
|
|
89
|
-
hash_chain_id,
|
|
90
|
-
kind,
|
|
91
|
-
digest,
|
|
92
|
-
iteration
|
|
93
|
-
)
|
|
94
|
-
VALUES ($1, $2, $3, $4)
|
|
95
|
-
`, [
|
|
96
|
-
dbHashChain.id,
|
|
97
|
-
DbHashKind.TERMINAL,
|
|
98
|
-
terminalHash,
|
|
99
|
-
config.HASHCHAINSERVER_MAX_ITERATIONS,
|
|
100
|
-
]);
|
|
101
|
-
return dbHashChain.id;
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
return object({
|
|
105
|
-
hashChain: hashChainTable.get({ id: $hashChainId }),
|
|
106
|
-
});
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
}, "CreateHashChainPlugin");
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const HubUserActiveHashChainPlugin: GraphileConfig.Plugin;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { maybeOneRow } from "@moneypot/hub/db";
|
|
2
|
-
import { inhibitOnNull } from "@moneypot/hub/grafast";
|
|
3
|
-
import { context } from "@moneypot/hub/grafast";
|
|
4
|
-
import { gql, makeExtendSchemaPlugin } from "@moneypot/hub/graphile";
|
|
5
|
-
import { withPgClient } from "postgraphile/@dataplan/pg";
|
|
6
|
-
import { object } from "postgraphile/grafast";
|
|
7
|
-
export const HubUserActiveHashChainPlugin = makeExtendSchemaPlugin((build) => {
|
|
8
|
-
const hashChainTable = build.input.pgRegistry.pgResources.hub_hash_chain;
|
|
9
|
-
return {
|
|
10
|
-
typeDefs: gql `
|
|
11
|
-
extend type HubUser {
|
|
12
|
-
activeHashChain: HubHashChain
|
|
13
|
-
}
|
|
14
|
-
`,
|
|
15
|
-
plans: {
|
|
16
|
-
HubUser: {
|
|
17
|
-
activeHashChain: ($record) => {
|
|
18
|
-
const $identity = context().get("identity");
|
|
19
|
-
const $hashChainId = withPgClient(hashChainTable.executor, object({ userId: $record.get("id"), identity: $identity }), async (pgClient, { userId, identity }) => {
|
|
20
|
-
if (identity?.kind !== "user") {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
const { session } = identity;
|
|
24
|
-
const activeHashChain = await pgClient
|
|
25
|
-
.query({
|
|
26
|
-
text: `
|
|
27
|
-
select id
|
|
28
|
-
from hub.hash_chain
|
|
29
|
-
where user_id = $1
|
|
30
|
-
and experience_id = $2
|
|
31
|
-
and casino_id = $3
|
|
32
|
-
and active = TRUE
|
|
33
|
-
order by id desc
|
|
34
|
-
limit 1
|
|
35
|
-
`,
|
|
36
|
-
values: [userId, session.experience_id, session.casino_id],
|
|
37
|
-
})
|
|
38
|
-
.then(maybeOneRow);
|
|
39
|
-
return activeHashChain?.id ?? null;
|
|
40
|
-
});
|
|
41
|
-
return hashChainTable.get({ id: inhibitOnNull($hashChainId) });
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
}, "HubActiveHashChainPlugin");
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
CREATE TABLE hub.hash_chain (
|
|
2
|
-
id uuid PRIMARY KEY DEFAULT hub_hidden.uuid_generate_v7(),
|
|
3
|
-
user_id uuid NOT NULL REFERENCES hub.user(id),
|
|
4
|
-
experience_id uuid NOT NULL REFERENCES hub.experience(id),
|
|
5
|
-
casino_id uuid NOT NULL REFERENCES hub.casino(id),
|
|
6
|
-
client_seed text NOT NULL,
|
|
7
|
-
active boolean NOT NULL,
|
|
8
|
-
|
|
9
|
-
max_iteration int NOT NULL check (max_iteration > 0),
|
|
10
|
-
current_iteration int NOT NULL check (current_iteration between 0 and max_iteration)
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
-- TODO: Should probably index current_iteration
|
|
14
|
-
-- CREATE INDEX hash_chain_current_iteration_idx ON hub.hash_chain(current_iteration);
|
|
15
|
-
|
|
16
|
-
CREATE INDEX hash_chain_user_id_idx ON hub.hash_chain(user_id);
|
|
17
|
-
CREATE INDEX hash_chain_experience_id_idx ON hub.hash_chain(experience_id);
|
|
18
|
-
CREATE INDEX hash_chain_casino_id_idx ON hub.hash_chain(casino_id);
|
|
19
|
-
|
|
20
|
-
-- Ensure only one active hash_chain per user per experience per casino
|
|
21
|
-
CREATE UNIQUE INDEX active_hash_chain_idx
|
|
22
|
-
ON hub.hash_chain (user_id, experience_id, casino_id)
|
|
23
|
-
WHERE active = true;
|
|
24
|
-
|
|
25
|
-
CREATE TYPE hub.hash_kind AS ENUM (
|
|
26
|
-
'TERMINAL', -- max iteration hash (e.g. iteration 1000)
|
|
27
|
-
'INTERMEDIATE', -- intermediate hash (e.g. iteration 1-999)
|
|
28
|
-
'PREIMAGE' -- preimage hash (always iteration 0)
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
-- this is the base table for all bets events
|
|
32
|
-
CREATE TABLE hub.hash (
|
|
33
|
-
id uuid PRIMARY KEY DEFAULT hub_hidden.uuid_generate_v7(),
|
|
34
|
-
kind hub.hash_kind NOT NULL,
|
|
35
|
-
hash_chain_id uuid NOT NULL REFERENCES hub.hash_chain(id),
|
|
36
|
-
iteration int NOT NULL check (iteration >= 0), -- which Nth value from the hash chain it is
|
|
37
|
-
digest bytea NOT NULL, -- the actual hash we got from hash chain server
|
|
38
|
-
metadata jsonb NOT NULL DEFAULT '{}' -- operator can store game-specific tags
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
CREATE INDEX hash_hash_chain_id_idx ON hub.hash(hash_chain_id);
|
|
42
|
-
|
|
43
|
-
-- Ensure iterations are unique per hash_chain to avoid dupe mistakes
|
|
44
|
-
CREATE UNIQUE INDEX hash_hash_chain_id_iteration_idx ON hub.hash(hash_chain_id, iteration);
|
|
45
|
-
|
|
46
|
-
-- Ensure a hash_chain only has of each end-type hash
|
|
47
|
-
CREATE UNIQUE INDEX hash_chain_terminal_hash_idx ON hub.hash (hash_chain_id)
|
|
48
|
-
WHERE kind = 'TERMINAL';
|
|
49
|
-
CREATE UNIQUE INDEX hash_chain_preimage_hash_idx ON hub.hash (hash_chain_id)
|
|
50
|
-
WHERE kind = 'PREIMAGE';
|
|
51
|
-
|
|
52
|
-
-- GRANTS
|
|
53
|
-
|
|
54
|
-
GRANT SELECT ON TABLE hub.hash_chain TO app_postgraphile;
|
|
55
|
-
GRANT SELECT ON TABLE hub.hash TO app_postgraphile;
|
|
56
|
-
|
|
57
|
-
-- RLS
|
|
58
|
-
ALTER TABLE hub.hash_chain ENABLE ROW LEVEL SECURITY;
|
|
59
|
-
ALTER TABLE hub.hash ENABLE ROW LEVEL SECURITY;
|
|
60
|
-
|
|
61
|
-
CREATE POLICY select_hash_chain ON hub.hash_chain FOR SELECT USING (
|
|
62
|
-
-- Operator can see all rows
|
|
63
|
-
hub_hidden.is_operator() OR
|
|
64
|
-
-- User can see their own rows
|
|
65
|
-
(
|
|
66
|
-
user_id = hub_hidden.current_user_id() AND
|
|
67
|
-
experience_id = hub_hidden.current_experience_id() AND
|
|
68
|
-
casino_id = hub_hidden.current_casino_id()
|
|
69
|
-
)
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
CREATE POLICY select_hash ON hub.hash FOR SELECT USING (
|
|
73
|
-
-- Operator can see all rows
|
|
74
|
-
hub_hidden.is_operator() OR
|
|
75
|
-
-- User can see their own rows by checking the associated hash_chain
|
|
76
|
-
EXISTS (
|
|
77
|
-
SELECT 1
|
|
78
|
-
FROM hub.hash_chain
|
|
79
|
-
WHERE hub.hash_chain.id = hub.hash.hash_chain_id
|
|
80
|
-
AND hub.hash_chain.user_id = hub_hidden.current_user_id()
|
|
81
|
-
AND hub.hash_chain.experience_id = hub_hidden.current_experience_id()
|
|
82
|
-
AND hub.hash_chain.casino_id = hub_hidden.current_casino_id()
|
|
83
|
-
)
|
|
84
|
-
);
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { GraphQLInputFieldConfig } from "graphql";
|
|
2
|
-
export declare const HubOutcomeInputNonNullFieldsPlugin: {
|
|
3
|
-
name: string;
|
|
4
|
-
version: string;
|
|
5
|
-
description: string;
|
|
6
|
-
schema: {
|
|
7
|
-
hooks: {
|
|
8
|
-
GraphQLInputObjectType_fields_field: (field: GraphQLInputFieldConfig, build: any, context: any) => {
|
|
9
|
-
type: any;
|
|
10
|
-
description?: import("graphql/jsutils/Maybe.js").Maybe<string>;
|
|
11
|
-
defaultValue?: unknown;
|
|
12
|
-
deprecationReason?: import("graphql/jsutils/Maybe.js").Maybe<string>;
|
|
13
|
-
extensions?: import("graphql/jsutils/Maybe.js").Maybe<Readonly<import("graphql").GraphQLInputFieldExtensions>>;
|
|
14
|
-
astNode?: import("graphql/jsutils/Maybe.js").Maybe<import("graphql").InputValueDefinitionNode>;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export const HubOutcomeInputNonNullFieldsPlugin = {
|
|
2
|
-
name: "HubOutcomeInputNonNullFieldsPlugin",
|
|
3
|
-
version: "0.0.0",
|
|
4
|
-
description: "Specifies that HubOutcomeInput fields are non-null",
|
|
5
|
-
schema: {
|
|
6
|
-
hooks: {
|
|
7
|
-
GraphQLInputObjectType_fields_field: (field, build, context) => {
|
|
8
|
-
const { scope: { fieldName }, } = context;
|
|
9
|
-
if (context.scope.pgCodec?.name === "hubOutcome" &&
|
|
10
|
-
["profit", "weight"].includes(fieldName)) {
|
|
11
|
-
return {
|
|
12
|
-
...field,
|
|
13
|
-
type: new build.graphql.GraphQLNonNull(field.type),
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
return field;
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
};
|