trucoshi 7.0.0 → 7.2.0
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/events.d.ts +5 -1
- package/dist/events.js +1 -0
- package/dist/lib/classes/Random.d.ts +15 -6
- package/dist/lib/classes/Random.js +62 -17
- package/dist/types.d.ts +11 -1
- package/package.json +2 -2
- package/prisma/client/index.d.ts +309 -241
- package/prisma/client/index.js +4 -2
- package/prisma/client/schema.prisma +7 -8
package/dist/events.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EMatchState } from "@trucoshi/prisma";
|
|
2
2
|
import { SocketError } from "./server";
|
|
3
|
-
import { IAccountDetails, IChatMessage, ILobbyOptions, IMatchDetails, IMatchPreviousHand, IPublicChatRoom, IPublicMatch, IPublicMatchInfo, IUserData, IWaitingPlayData, IWaitingSayData } from "./types";
|
|
3
|
+
import { IAccountDetails, IChatMessage, ILobbyOptions, IMatchDetails, IMatchPreviousHand, IPlayerRanking, IPublicChatRoom, IPublicMatch, IPublicMatchInfo, IUserData, IWaitingPlayData, IWaitingSayData } from "./types";
|
|
4
4
|
import { User } from "lightning-accounts";
|
|
5
5
|
export type IEventCallback<T = {}> = (args: {
|
|
6
6
|
success: boolean;
|
|
@@ -43,6 +43,7 @@ export declare enum EClientEvent {
|
|
|
43
43
|
FETCH_MATCH_DETAILS = "FETCH_MATCH_DETAILS",
|
|
44
44
|
SET_MATCH_OPTIONS = "SET_MATCH_OPTIONS",
|
|
45
45
|
LIST_MATCHES = "LIST_MATCHES",
|
|
46
|
+
LIST_RANKING = "LIST_RANKING",
|
|
46
47
|
JOIN_MATCH = "JOIN_MATCH",
|
|
47
48
|
START_MATCH = "START_MATCH",
|
|
48
49
|
SET_PLAYER_READY = "SET_PLAYER_READY",
|
|
@@ -90,6 +91,9 @@ export interface ClientToServerEvents {
|
|
|
90
91
|
}, callback: IEventCallback<{
|
|
91
92
|
matches: Array<IPublicMatchInfo>;
|
|
92
93
|
}>) => void;
|
|
94
|
+
[EClientEvent.LIST_RANKING]: (filters: {}, callback: IEventCallback<{
|
|
95
|
+
ranking: Array<IPlayerRanking>;
|
|
96
|
+
}>) => void;
|
|
93
97
|
[EClientEvent.LOGIN]: (user: User, identityToken: string, callback: IEventCallback<{
|
|
94
98
|
activeMatches?: IPublicMatchInfo[];
|
|
95
99
|
}>) => void;
|
package/dist/events.js
CHANGED
|
@@ -23,6 +23,7 @@ export var EClientEvent;
|
|
|
23
23
|
EClientEvent["FETCH_MATCH_DETAILS"] = "FETCH_MATCH_DETAILS";
|
|
24
24
|
EClientEvent["SET_MATCH_OPTIONS"] = "SET_MATCH_OPTIONS";
|
|
25
25
|
EClientEvent["LIST_MATCHES"] = "LIST_MATCHES";
|
|
26
|
+
EClientEvent["LIST_RANKING"] = "LIST_RANKING";
|
|
26
27
|
EClientEvent["JOIN_MATCH"] = "JOIN_MATCH";
|
|
27
28
|
EClientEvent["START_MATCH"] = "START_MATCH";
|
|
28
29
|
EClientEvent["SET_PLAYER_READY"] = "SET_PLAYER_READY";
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
+
import { RequestParams } from "lightning-accounts";
|
|
1
2
|
import { IRandom } from "../../types";
|
|
3
|
+
import { AxiosResponse } from "axios";
|
|
2
4
|
export declare const Random: () => IRandom;
|
|
3
5
|
export interface IRng {
|
|
4
|
-
combine(client: string, server: string, nonce: number): string;
|
|
6
|
+
combine(client: string, server: string, bitcoinHash: string, nonce: number): string;
|
|
5
7
|
sha512(string: string): string;
|
|
6
8
|
generateServerSeed(): string;
|
|
9
|
+
getBitcoinLatestBlockHash(fn: (params?: RequestParams) => Promise<AxiosResponse<{
|
|
10
|
+
hash: string;
|
|
11
|
+
height: number;
|
|
12
|
+
}, any>>): Promise<{
|
|
13
|
+
hash: string;
|
|
14
|
+
height: number;
|
|
15
|
+
}>;
|
|
7
16
|
hexToBytes(hex: string): Uint8Array;
|
|
8
|
-
byteGenerator(clientseed: string, serverseed: string, nonce: number): Uint8Array;
|
|
9
|
-
generateInteger(clientSeed: string, serverSeed: string, nonce: number, min: number, max: number): number;
|
|
10
|
-
generateFloat(clientSeed: string, serverSeed: string, nonce: number, precision?: number): number;
|
|
11
|
-
generateBool(clientSeed: string, serverSeed: string, nonce: number): boolean;
|
|
17
|
+
byteGenerator(clientseed: string, serverseed: string, bitcoinHash: string, nonce: number): Uint8Array;
|
|
18
|
+
generateInteger(clientSeed: string, serverSeed: string, bitcoinHash: string, nonce: number, min: number, max: number): number;
|
|
19
|
+
generateFloat(clientSeed: string, serverSeed: string, bitcoinHash: string, nonce: number, precision?: number): number;
|
|
20
|
+
generateBool(clientSeed: string, serverSeed: string, bitcoinHash: string, nonce: number): boolean;
|
|
12
21
|
selectRandomObject<T extends {
|
|
13
22
|
probability: number;
|
|
14
23
|
} = {
|
|
15
24
|
probability: number;
|
|
16
25
|
[x: string]: any;
|
|
17
|
-
}>(clientSeed: string, serverSeed: string, nonce: number, objects: Array<T>): T | null;
|
|
26
|
+
}>(clientSeed: string, serverSeed: string, bitcoinHash: string, nonce: number, objects: Array<T>): T | null;
|
|
18
27
|
}
|
|
@@ -1,18 +1,41 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
import forge from "node-forge";
|
|
2
11
|
const rnd = Rng();
|
|
3
12
|
export const Random = () => {
|
|
4
13
|
const random = {
|
|
5
14
|
secret: rnd.generateServerSeed(),
|
|
6
15
|
clients: [],
|
|
16
|
+
bitcoinHash: "",
|
|
17
|
+
bitcoinHeight: 0,
|
|
7
18
|
nonce: 0,
|
|
19
|
+
getLatestBitcoinBlock(fn) {
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
const { hash, height } = yield rnd.getBitcoinLatestBlockHash(fn);
|
|
22
|
+
random.bitcoinHash = hash;
|
|
23
|
+
random.bitcoinHeight = height;
|
|
24
|
+
});
|
|
25
|
+
},
|
|
8
26
|
pick(key, max) {
|
|
9
|
-
return rnd.generateInteger(random.clients[key], random.secret, random.nonce, 0, max);
|
|
27
|
+
return rnd.generateInteger(random.clients[key], random.secret, random.bitcoinHash, random.nonce, 0, max);
|
|
10
28
|
},
|
|
11
29
|
next() {
|
|
12
30
|
random.nonce++;
|
|
13
31
|
},
|
|
14
32
|
reveal() {
|
|
15
|
-
return {
|
|
33
|
+
return {
|
|
34
|
+
secret: random.secret,
|
|
35
|
+
clients: [...random.clients],
|
|
36
|
+
bitcoinHash: random.bitcoinHash,
|
|
37
|
+
bitcoinHeight: random.bitcoinHeight,
|
|
38
|
+
};
|
|
16
39
|
},
|
|
17
40
|
};
|
|
18
41
|
return random;
|
|
@@ -22,12 +45,13 @@ function Rng() {
|
|
|
22
45
|
/**
|
|
23
46
|
* Generates a random 256 long hex hash
|
|
24
47
|
*
|
|
25
|
-
* @param {string} clientSeed
|
|
26
|
-
* @param {string} serverSeed
|
|
27
|
-
* @param {
|
|
48
|
+
* @param {string} clientSeed - the clientSeed
|
|
49
|
+
* @param {string} serverSeed - the serverSeed
|
|
50
|
+
* @param {string} bitcoinHash - The latest bitcoin block hash.
|
|
51
|
+
* @param {number} nonce - the nonce
|
|
28
52
|
* @returns {string} combined string
|
|
29
53
|
*/
|
|
30
|
-
combine: (clientSeed, serverSeed, nonce) => clientSeed + serverSeed + nonce,
|
|
54
|
+
combine: (clientSeed, serverSeed, bitcoinHash, nonce) => clientSeed + serverSeed + bitcoinHash + nonce,
|
|
31
55
|
/**
|
|
32
56
|
* Generates a sha512 hash from a string
|
|
33
57
|
*
|
|
@@ -62,11 +86,12 @@ function Rng() {
|
|
|
62
86
|
*
|
|
63
87
|
* @param {string} clientseed - The clientseed to use.
|
|
64
88
|
* @param {string} serverseed - The serverseed to use.
|
|
89
|
+
* @param {string} bitcoinHash - The latest bitcoin block hash.
|
|
65
90
|
* @param {number} nonce - The nonce to use.
|
|
66
91
|
* @returns {Uint8Array} - The generated bytes as a Uint8Array.
|
|
67
92
|
*/
|
|
68
|
-
byteGenerator: function (clientseed, serverseed, nonce) {
|
|
69
|
-
const preHash = this.combine(clientseed, serverseed, nonce);
|
|
93
|
+
byteGenerator: function (clientseed, serverseed, bitcoinHash, nonce) {
|
|
94
|
+
const preHash = this.combine(clientseed, serverseed, bitcoinHash, nonce);
|
|
70
95
|
const hash = this.sha512(preHash);
|
|
71
96
|
return this.hexToBytes(hash.slice(0, 64));
|
|
72
97
|
},
|
|
@@ -75,27 +100,29 @@ function Rng() {
|
|
|
75
100
|
*
|
|
76
101
|
* @param {string} clientSeed - The client seed.
|
|
77
102
|
* @param {string} serverSeed - The server seed.
|
|
103
|
+
* @param {string} bitcoinHash - The latest bitcoin block hash.
|
|
78
104
|
* @param {number} nonce - The nonce.
|
|
79
105
|
* @param {number} min - The minimum value of the range.
|
|
80
106
|
* @param {number} max - The maximum value of the range.
|
|
81
107
|
* @returns {number} A random integer between min and max (inclusive).
|
|
82
108
|
*/
|
|
83
|
-
generateInteger: function (clientSeed, serverSeed, nonce, min, max) {
|
|
84
|
-
const preHash = this.combine(clientSeed, serverSeed, nonce);
|
|
109
|
+
generateInteger: function (clientSeed, serverSeed, bitcoinHash, nonce, min, max) {
|
|
110
|
+
const preHash = this.combine(clientSeed, serverSeed, bitcoinHash, nonce);
|
|
85
111
|
const hash = this.sha512(preHash);
|
|
86
112
|
const range = max - min + 1;
|
|
87
|
-
return (parseInt(hash.slice(0,
|
|
113
|
+
return (parseInt(hash.slice(0, 16), 16) % range) + min;
|
|
88
114
|
},
|
|
89
115
|
/**
|
|
90
116
|
* Generates a random float between 0 and 1 using the fairjs library.
|
|
91
117
|
* @param {string} clientSeed - The client seed to use for the random number generation.
|
|
92
118
|
* @param {string} serverSeed - The server seed to use for the random number generation.
|
|
119
|
+
* @param {string} bitcoinHash - The latest bitcoin block hash.
|
|
93
120
|
* @param {number} nonce - The nonce to use for the random number generation.
|
|
94
121
|
* @param {number} [precision=2] - The number of decimal places to include in the result.
|
|
95
122
|
* @returns {number} - The random float between 0 and 1.
|
|
96
123
|
*/
|
|
97
|
-
generateFloat: function (clientSeed, serverSeed, nonce, precision = 2) {
|
|
98
|
-
const bytes = this.byteGenerator(clientSeed, serverSeed, nonce);
|
|
124
|
+
generateFloat: function (clientSeed, serverSeed, bitcoinHash, nonce, precision = 2) {
|
|
125
|
+
const bytes = this.byteGenerator(clientSeed, serverSeed, bitcoinHash, nonce);
|
|
99
126
|
const float = parseFloat("0." + bytes.join(""));
|
|
100
127
|
return parseFloat(float.toFixed(precision));
|
|
101
128
|
},
|
|
@@ -107,25 +134,28 @@ function Rng() {
|
|
|
107
134
|
* @param {number} nonce - The nonce.
|
|
108
135
|
* @returns {float, boolean} random boolean true/false
|
|
109
136
|
*/
|
|
110
|
-
generateBool: function (clientSeed, serverSeed, nonce) {
|
|
111
|
-
return this.generateFloat(clientSeed, serverSeed, nonce, 10) <= 0.5
|
|
137
|
+
generateBool: function (clientSeed, serverSeed, bitcoinHash, nonce) {
|
|
138
|
+
return this.generateFloat(clientSeed, serverSeed, bitcoinHash, nonce, 10) <= 0.5
|
|
139
|
+
? true
|
|
140
|
+
: false;
|
|
112
141
|
},
|
|
113
142
|
/**
|
|
114
143
|
* Selects a random object from an array of objects based on their probabilities.
|
|
115
144
|
*
|
|
116
145
|
* @param {string} clientSeed - The client seed.
|
|
117
146
|
* @param {string} serverSeed - The server seed.
|
|
147
|
+
* @param {string} bitcoinHash - The latest bitcoin block hash.
|
|
118
148
|
* @param {number} nonce - The nonce.
|
|
119
149
|
* @param {Array} objects - An array of objects with an ID and a probability property.
|
|
120
150
|
* @returns {String} The ID of the randomly selected object.
|
|
121
151
|
*/
|
|
122
|
-
selectRandomObject: function (clientSeed, serverSeed, nonce, objects) {
|
|
152
|
+
selectRandomObject: function (clientSeed, serverSeed, bitcoinHash, nonce, objects) {
|
|
123
153
|
let totalProbability = 0;
|
|
124
154
|
for (const obj of objects) {
|
|
125
155
|
totalProbability += obj.probability;
|
|
126
156
|
}
|
|
127
157
|
const normalizedProbabilities = objects.map((obj) => obj.probability / totalProbability);
|
|
128
|
-
const randomFloat = this.generateFloat(clientSeed, serverSeed, nonce, 10);
|
|
158
|
+
const randomFloat = this.generateFloat(clientSeed, serverSeed, bitcoinHash, nonce, 10);
|
|
129
159
|
let index = 0;
|
|
130
160
|
for (let i = 0; i < normalizedProbabilities.length; i++) {
|
|
131
161
|
index += normalizedProbabilities[i];
|
|
@@ -136,5 +166,20 @@ function Rng() {
|
|
|
136
166
|
// If no object is selected, return null
|
|
137
167
|
return null;
|
|
138
168
|
},
|
|
169
|
+
/**
|
|
170
|
+
* Gets the latest Bitcoin block hash from the LND node
|
|
171
|
+
*
|
|
172
|
+
* @returns {Promise<string>} The latest Bitcoin block hash
|
|
173
|
+
*/
|
|
174
|
+
getBitcoinLatestBlockHash: function (fn) {
|
|
175
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
176
|
+
try {
|
|
177
|
+
return (yield fn()).data || { hash: "", height: 0 };
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
return { hash: "", height: 0 };
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
},
|
|
139
184
|
};
|
|
140
185
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
export * from "./events";
|
|
2
2
|
export { CARDS, CARDS_HUMAN_READABLE, BURNT_CARD } from "./lib/constants";
|
|
3
|
-
import { User } from "lightning-accounts";
|
|
3
|
+
import { RequestParams, User } from "lightning-accounts";
|
|
4
4
|
import { Match, MatchPlayer, MatchHand, UserStats } from "@trucoshi/prisma";
|
|
5
5
|
import { IHand } from "./truco";
|
|
6
6
|
import { CARDS } from "./lib";
|
|
7
|
+
import { AxiosResponse } from "axios";
|
|
7
8
|
export declare enum EMatchState {
|
|
8
9
|
UNREADY = "UNREADY",
|
|
9
10
|
READY = "READY",
|
|
10
11
|
STARTED = "STARTED",
|
|
11
12
|
FINISHED = "FINISHED"
|
|
12
13
|
}
|
|
14
|
+
export type IPlayerRanking = Omit<UserStats, "id" | "satsBet" | "satsWon" | "satsLost"> & Pick<User, "name" | "avatarUrl">;
|
|
13
15
|
export interface IMatchDetails extends Match {
|
|
14
16
|
players: Array<Pick<MatchPlayer, "id" | "accountId" | "teamIdx" | "name" | "idx">>;
|
|
15
17
|
hands: Array<MatchHand>;
|
|
@@ -237,12 +239,20 @@ export interface IHandPoints {
|
|
|
237
239
|
export interface IRandom {
|
|
238
240
|
secret: string;
|
|
239
241
|
clients: string[];
|
|
242
|
+
bitcoinHash: string;
|
|
243
|
+
bitcoinHeight: number;
|
|
240
244
|
nonce: number;
|
|
245
|
+
getLatestBitcoinBlock(fn: (params?: RequestParams) => Promise<AxiosResponse<{
|
|
246
|
+
hash: string;
|
|
247
|
+
height: number;
|
|
248
|
+
}, any>>): Promise<void>;
|
|
241
249
|
next(): void;
|
|
242
250
|
pick(idx: number, max: number): number;
|
|
243
251
|
reveal(): {
|
|
244
252
|
secret: string;
|
|
245
253
|
clients: string[];
|
|
254
|
+
bitcoinHash: string;
|
|
255
|
+
bitcoinHeight: number;
|
|
246
256
|
};
|
|
247
257
|
}
|
|
248
258
|
export type IPublicPlayer = Pick<IPlayer, "idx" | "key" | "name" | "abandonedTime" | "accountId" | "avatarUrl" | "disabled" | "abandoned" | "ready" | "hand" | "usedHand" | "prevHand" | "teamIdx" | "isTurn" | "turnExpiresAt" | "turnExtensionExpiresAt" | "isEnvidoTurn" | "isOwner"> & ({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trucoshi",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.0",
|
|
4
4
|
"description": "Lightning Truco Server",
|
|
5
5
|
"main": "dist/types.js",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"dotenv-cli": "^7.3.0",
|
|
77
77
|
"form-data": "^4.0.0",
|
|
78
78
|
"jsonwebtoken": "^9.0.2",
|
|
79
|
-
"lightning-accounts": "
|
|
79
|
+
"lightning-accounts": "4.3.0",
|
|
80
80
|
"node-forge": "^1.3.1",
|
|
81
81
|
"path-scurry": "^1.9.2",
|
|
82
82
|
"pino": "^9.3.2",
|