trucoshi 7.0.0-rc.9 → 7.1.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.
@@ -1,4 +1,4 @@
1
- import { BURNT_CARD, CARDS } from "../../types";
1
+ import { BURNT_CARD, CARDS } from "../constants";
2
2
  import { Random } from "./Random";
3
3
  export function Deck() {
4
4
  const deck = {
@@ -1,18 +1,22 @@
1
1
  import { IRandom } from "../../types";
2
2
  export declare const Random: () => IRandom;
3
3
  export interface IRng {
4
- combine(client: string, server: string, nonce: number): string;
4
+ combine(client: string, server: string, bitcoinHash: string, nonce: number): string;
5
5
  sha512(string: string): string;
6
6
  generateServerSeed(): string;
7
+ getBitcoinLatestBlockHash(): Promise<{
8
+ hash: string;
9
+ height: number;
10
+ }>;
7
11
  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;
12
+ byteGenerator(clientseed: string, serverseed: string, bitcoinHash: string, nonce: number): Uint8Array;
13
+ generateInteger(clientSeed: string, serverSeed: string, bitcoinHash: string, nonce: number, min: number, max: number): number;
14
+ generateFloat(clientSeed: string, serverSeed: string, bitcoinHash: string, nonce: number, precision?: number): number;
15
+ generateBool(clientSeed: string, serverSeed: string, bitcoinHash: string, nonce: number): boolean;
12
16
  selectRandomObject<T extends {
13
17
  probability: number;
14
18
  } = {
15
19
  probability: number;
16
20
  [x: string]: any;
17
- }>(clientSeed: string, serverSeed: string, nonce: number, objects: Array<T>): T | null;
21
+ }>(clientSeed: string, serverSeed: string, bitcoinHash: string, nonce: number, objects: Array<T>): T | null;
18
22
  }
@@ -1,18 +1,42 @@
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
+ };
10
+ import { accountsApi } from "../../accounts/client";
1
11
  import forge from "node-forge";
2
12
  const rnd = Rng();
3
13
  export const Random = () => {
4
14
  const random = {
5
15
  secret: rnd.generateServerSeed(),
6
16
  clients: [],
17
+ bitcoinHash: "",
18
+ bitcoinHeight: 0,
7
19
  nonce: 0,
20
+ getLatestBitcoinBlock() {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const { hash, height } = yield rnd.getBitcoinLatestBlockHash();
23
+ random.bitcoinHash = hash;
24
+ random.bitcoinHeight = height;
25
+ });
26
+ },
8
27
  pick(key, max) {
9
- return rnd.generateInteger(random.clients[key], random.secret, random.nonce, 0, max);
28
+ return rnd.generateInteger(random.clients[key], random.secret, random.bitcoinHash, random.nonce, 0, max);
10
29
  },
11
30
  next() {
12
31
  random.nonce++;
13
32
  },
14
33
  reveal() {
15
- return { secret: random.secret, clients: [...random.clients] };
34
+ return {
35
+ secret: random.secret,
36
+ clients: [...random.clients],
37
+ bitcoinHash: random.bitcoinHash,
38
+ bitcoinHeight: random.bitcoinHeight,
39
+ };
16
40
  },
17
41
  };
18
42
  return random;
@@ -22,12 +46,13 @@ function Rng() {
22
46
  /**
23
47
  * Generates a random 256 long hex hash
24
48
  *
25
- * @param {string} clientSeed - the clientSeed
26
- * @param {string} serverSeed - the serverSeed
27
- * @param {number} nonce - the nonce
49
+ * @param {string} clientSeed - the clientSeed
50
+ * @param {string} serverSeed - the serverSeed
51
+ * @param {string} bitcoinHash - The latest bitcoin block hash.
52
+ * @param {number} nonce - the nonce
28
53
  * @returns {string} combined string
29
54
  */
30
- combine: (clientSeed, serverSeed, nonce) => clientSeed + serverSeed + nonce,
55
+ combine: (clientSeed, serverSeed, bitcoinHash, nonce) => clientSeed + serverSeed + bitcoinHash + nonce,
31
56
  /**
32
57
  * Generates a sha512 hash from a string
33
58
  *
@@ -62,11 +87,12 @@ function Rng() {
62
87
  *
63
88
  * @param {string} clientseed - The clientseed to use.
64
89
  * @param {string} serverseed - The serverseed to use.
90
+ * @param {string} bitcoinHash - The latest bitcoin block hash.
65
91
  * @param {number} nonce - The nonce to use.
66
92
  * @returns {Uint8Array} - The generated bytes as a Uint8Array.
67
93
  */
68
- byteGenerator: function (clientseed, serverseed, nonce) {
69
- const preHash = this.combine(clientseed, serverseed, nonce);
94
+ byteGenerator: function (clientseed, serverseed, bitcoinHash, nonce) {
95
+ const preHash = this.combine(clientseed, serverseed, bitcoinHash, nonce);
70
96
  const hash = this.sha512(preHash);
71
97
  return this.hexToBytes(hash.slice(0, 64));
72
98
  },
@@ -75,27 +101,29 @@ function Rng() {
75
101
  *
76
102
  * @param {string} clientSeed - The client seed.
77
103
  * @param {string} serverSeed - The server seed.
104
+ * @param {string} bitcoinHash - The latest bitcoin block hash.
78
105
  * @param {number} nonce - The nonce.
79
106
  * @param {number} min - The minimum value of the range.
80
107
  * @param {number} max - The maximum value of the range.
81
108
  * @returns {number} A random integer between min and max (inclusive).
82
109
  */
83
- generateInteger: function (clientSeed, serverSeed, nonce, min, max) {
84
- const preHash = this.combine(clientSeed, serverSeed, nonce);
110
+ generateInteger: function (clientSeed, serverSeed, bitcoinHash, nonce, min, max) {
111
+ const preHash = this.combine(clientSeed, serverSeed, bitcoinHash, nonce);
85
112
  const hash = this.sha512(preHash);
86
113
  const range = max - min + 1;
87
- return (parseInt(hash.slice(0, 8), 16) % range) + min;
114
+ return (parseInt(hash.slice(0, 16), 16) % range) + min;
88
115
  },
89
116
  /**
90
117
  * Generates a random float between 0 and 1 using the fairjs library.
91
118
  * @param {string} clientSeed - The client seed to use for the random number generation.
92
119
  * @param {string} serverSeed - The server seed to use for the random number generation.
120
+ * @param {string} bitcoinHash - The latest bitcoin block hash.
93
121
  * @param {number} nonce - The nonce to use for the random number generation.
94
122
  * @param {number} [precision=2] - The number of decimal places to include in the result.
95
123
  * @returns {number} - The random float between 0 and 1.
96
124
  */
97
- generateFloat: function (clientSeed, serverSeed, nonce, precision = 2) {
98
- const bytes = this.byteGenerator(clientSeed, serverSeed, nonce);
125
+ generateFloat: function (clientSeed, serverSeed, bitcoinHash, nonce, precision = 2) {
126
+ const bytes = this.byteGenerator(clientSeed, serverSeed, bitcoinHash, nonce);
99
127
  const float = parseFloat("0." + bytes.join(""));
100
128
  return parseFloat(float.toFixed(precision));
101
129
  },
@@ -107,25 +135,28 @@ function Rng() {
107
135
  * @param {number} nonce - The nonce.
108
136
  * @returns {float, boolean} random boolean true/false
109
137
  */
110
- generateBool: function (clientSeed, serverSeed, nonce) {
111
- return this.generateFloat(clientSeed, serverSeed, nonce, 10) <= 0.5 ? true : false;
138
+ generateBool: function (clientSeed, serverSeed, bitcoinHash, nonce) {
139
+ return this.generateFloat(clientSeed, serverSeed, bitcoinHash, nonce, 10) <= 0.5
140
+ ? true
141
+ : false;
112
142
  },
113
143
  /**
114
144
  * Selects a random object from an array of objects based on their probabilities.
115
145
  *
116
146
  * @param {string} clientSeed - The client seed.
117
147
  * @param {string} serverSeed - The server seed.
148
+ * @param {string} bitcoinHash - The latest bitcoin block hash.
118
149
  * @param {number} nonce - The nonce.
119
150
  * @param {Array} objects - An array of objects with an ID and a probability property.
120
151
  * @returns {String} The ID of the randomly selected object.
121
152
  */
122
- selectRandomObject: function (clientSeed, serverSeed, nonce, objects) {
153
+ selectRandomObject: function (clientSeed, serverSeed, bitcoinHash, nonce, objects) {
123
154
  let totalProbability = 0;
124
155
  for (const obj of objects) {
125
156
  totalProbability += obj.probability;
126
157
  }
127
158
  const normalizedProbabilities = objects.map((obj) => obj.probability / totalProbability);
128
- const randomFloat = this.generateFloat(clientSeed, serverSeed, nonce, 10);
159
+ const randomFloat = this.generateFloat(clientSeed, serverSeed, bitcoinHash, nonce, 10);
129
160
  let index = 0;
130
161
  for (let i = 0; i < normalizedProbabilities.length; i++) {
131
162
  index += normalizedProbabilities[i];
@@ -136,5 +167,23 @@ function Rng() {
136
167
  // If no object is selected, return null
137
168
  return null;
138
169
  },
170
+ /**
171
+ * Gets the latest Bitcoin block hash from the LND node
172
+ *
173
+ * @returns {Promise<string>} The latest Bitcoin block hash
174
+ */
175
+ getBitcoinLatestBlockHash: function () {
176
+ return __awaiter(this, void 0, void 0, function* () {
177
+ try {
178
+ if (!accountsApi.instance.defaults.baseURL) {
179
+ return { hash: "", height: 0 };
180
+ }
181
+ return (yield accountsApi.wallet.getLatestBitcoinBlock()).data || { hash: "", height: 0 };
182
+ }
183
+ catch (error) {
184
+ return { hash: "", height: 0 };
185
+ }
186
+ });
187
+ },
139
188
  };
140
189
  }
@@ -1,48 +1,35 @@
1
- import logger from "../../utils/logger";
2
- const log = logger.child({ class: "Table" });
3
1
  export function Table(players) {
4
- log.trace({ playerKeys: players.map((p) => p.key) }, "Creating new table");
5
2
  const table = {
6
3
  players,
7
4
  cards: [],
8
5
  forehandIdx: 0,
9
6
  nextHand() {
10
- log.trace({ currentForehandIdx: table.forehandIdx }, "nextHand called");
11
7
  if (table.forehandIdx < table.players.length - 1) {
12
8
  table.forehandIdx++;
13
9
  }
14
10
  else {
15
11
  table.forehandIdx = 0;
16
12
  }
17
- log.trace({ newForehandIdx: table.forehandIdx }, "nextHand updated");
18
13
  const nextPlayer = table.getPlayerByPosition();
19
- log.trace({ playerKey: nextPlayer.key }, "nextHand returning player");
20
14
  return nextPlayer;
21
15
  },
22
16
  getPlayerPosition(key, forehandFirst = false) {
23
- log.trace({ key, forehandFirst }, "getPlayerPosition called");
24
17
  const array = forehandFirst ? table.getPlayersForehandFirst() : table.players;
25
18
  const position = array.findIndex((p) => p.key === key);
26
- log.trace({ key, position }, "getPlayerPosition result");
27
19
  return position;
28
20
  },
29
21
  getPlayersForehandFirst(forehand) {
30
22
  const idx = forehand !== undefined ? forehand : table.forehandIdx;
31
- log.trace({ forehandIdx: idx }, "getPlayersForehandFirst called");
32
23
  const cut = players.slice(idx, table.players.length);
33
24
  const end = players.slice(0, idx);
34
25
  const result = cut.concat(end);
35
- log.trace({ playerKeys: result.map((p) => p.key) }, "getPlayersForehandFirst result");
36
26
  return result;
37
27
  },
38
28
  getPlayerByPosition(idx, forehandFirst = false) {
39
- log.trace({ idx, forehandFirst }, "getPlayerByPosition called");
40
29
  const array = forehandFirst ? table.getPlayersForehandFirst() : table.players;
41
30
  const player = idx !== undefined ? array[idx] : array[0];
42
- log.trace({ playerKey: player.key }, "getPlayerByPosition result");
43
31
  return player;
44
32
  },
45
33
  };
46
- log.trace({ forehandIdx: table.forehandIdx }, "Table initialization complete");
47
34
  return table;
48
35
  }
@@ -0,0 +1,89 @@
1
+ export declare const PLAYER_ABANDON_TIMEOUT: number;
2
+ export declare const PLAYER_TURN_TIMEOUT: number;
3
+ export declare const PREVIOUS_HAND_ACK_TIMEOUT: number;
4
+ export declare const CARDS: {
5
+ "1e": number;
6
+ "1b": number;
7
+ "7e": number;
8
+ "7o": number;
9
+ "3e": number;
10
+ "3o": number;
11
+ "3b": number;
12
+ "3c": number;
13
+ "2e": number;
14
+ "2o": number;
15
+ "2b": number;
16
+ "2c": number;
17
+ "1o": number;
18
+ "1c": number;
19
+ re: number;
20
+ ro: number;
21
+ rb: number;
22
+ rc: number;
23
+ ce: number;
24
+ co: number;
25
+ cb: number;
26
+ cc: number;
27
+ pe: number;
28
+ po: number;
29
+ pb: number;
30
+ pc: number;
31
+ "7b": number;
32
+ "7c": number;
33
+ "6e": number;
34
+ "6o": number;
35
+ "6b": number;
36
+ "6c": number;
37
+ "5e": number;
38
+ "5o": number;
39
+ "5b": number;
40
+ "5c": number;
41
+ "4e": number;
42
+ "4o": number;
43
+ "4b": number;
44
+ "4c": number;
45
+ };
46
+ export declare const BURNT_CARD: "rb" | "1e" | "1b" | "7e" | "7o" | "3e" | "3o" | "3b" | "3c" | "2e" | "2o" | "2b" | "2c" | "1o" | "1c" | "re" | "ro" | "rc" | "ce" | "co" | "cb" | "cc" | "pe" | "po" | "pb" | "pc" | "7b" | "7c" | "6e" | "6o" | "6b" | "6c" | "5e" | "5o" | "5b" | "5c" | "4e" | "4o" | "4b" | "4c";
47
+ export declare const CARDS_HUMAN_READABLE: {
48
+ "1e": string;
49
+ "1b": string;
50
+ "7e": string;
51
+ "7o": string;
52
+ "3e": string;
53
+ "3o": string;
54
+ "3b": string;
55
+ "3c": string;
56
+ "2e": string;
57
+ "2o": string;
58
+ "2b": string;
59
+ "2c": string;
60
+ "1o": string;
61
+ "1c": string;
62
+ re: string;
63
+ ro: string;
64
+ rb: string;
65
+ rc: string;
66
+ ce: string;
67
+ co: string;
68
+ cb: string;
69
+ cc: string;
70
+ pe: string;
71
+ po: string;
72
+ pb: string;
73
+ pc: string;
74
+ "7b": string;
75
+ "7c": string;
76
+ "6e": string;
77
+ "6o": string;
78
+ "6b": string;
79
+ "6c": string;
80
+ "5e": string;
81
+ "5o": string;
82
+ "5b": string;
83
+ "5c": string;
84
+ "4e": string;
85
+ "4o": string;
86
+ "4b": string;
87
+ "4c": string;
88
+ };
89
+ export declare const TEAM_SIZE_VALUES: number[];
@@ -0,0 +1,89 @@
1
+ export const PLAYER_ABANDON_TIMEOUT = 1000 * 60;
2
+ export const PLAYER_TURN_TIMEOUT = 1000 * 30;
3
+ export const PREVIOUS_HAND_ACK_TIMEOUT = 1000 * 5;
4
+ export const CARDS = {
5
+ "1e": 13,
6
+ "1b": 12,
7
+ "7e": 11,
8
+ "7o": 10,
9
+ "3e": 9,
10
+ "3o": 9,
11
+ "3b": 9,
12
+ "3c": 9,
13
+ "2e": 8,
14
+ "2o": 8,
15
+ "2b": 8,
16
+ "2c": 8,
17
+ "1o": 7,
18
+ "1c": 7,
19
+ re: 6,
20
+ ro: 6,
21
+ rb: 6,
22
+ rc: 6,
23
+ ce: 5,
24
+ co: 5,
25
+ cb: 5,
26
+ cc: 5,
27
+ pe: 4,
28
+ po: 4,
29
+ pb: 4,
30
+ pc: 4,
31
+ "7b": 3,
32
+ "7c": 3,
33
+ "6e": 2,
34
+ "6o": 2,
35
+ "6b": 2,
36
+ "6c": 2,
37
+ "5e": 1,
38
+ "5o": 1,
39
+ "5b": 1,
40
+ "5c": 1,
41
+ "4e": 0,
42
+ "4o": 0,
43
+ "4b": 0,
44
+ "4c": 0,
45
+ };
46
+ export const BURNT_CARD = "xx";
47
+ export const CARDS_HUMAN_READABLE = {
48
+ "1e": "1🗡️",
49
+ "1b": "1🌵",
50
+ "7e": "7🗡️",
51
+ "7o": "7💰",
52
+ "3e": "3🗡️",
53
+ "3o": "3💰",
54
+ "3b": "3🌵",
55
+ "3c": "3🍷",
56
+ "2e": "2🗡️",
57
+ "2o": "2💰",
58
+ "2b": "2🌵",
59
+ "2c": "2🍷",
60
+ "1o": "1💰",
61
+ "1c": "1🍷",
62
+ re: "12🗡️",
63
+ ro: "12💰",
64
+ rb: "12🌵",
65
+ rc: "12🍷",
66
+ ce: "11🗡️",
67
+ co: "11💰",
68
+ cb: "11🌵",
69
+ cc: "11🍷",
70
+ pe: "10🗡️",
71
+ po: "10💰",
72
+ pb: "10🌵",
73
+ pc: "10🍷",
74
+ "7b": "7🌵",
75
+ "7c": "7🍷",
76
+ "6e": "6🗡️",
77
+ "6o": "6💰",
78
+ "6b": "6🌵",
79
+ "6c": "6🍷",
80
+ "5e": "5🗡️",
81
+ "5o": "5💰",
82
+ "5b": "5🌵",
83
+ "5c": "5🍷",
84
+ "4e": "4🗡️",
85
+ "4o": "4💰",
86
+ "4b": "4🌵",
87
+ "4c": "4🍷",
88
+ };
89
+ export const TEAM_SIZE_VALUES = [1, 2, 3];
@@ -1,2 +1,2 @@
1
1
  export * from "./classes";
2
- export * from "../constants";
2
+ export * from "./constants";
package/dist/lib/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export * from "./classes";
2
- export * from "../constants";
2
+ export * from "./constants";
package/dist/lib/utils.js CHANGED
@@ -1,4 +1,4 @@
1
- import { CARDS } from "../constants";
1
+ import { CARDS } from "./constants";
2
2
  export function getMaxNumberIndex(array) {
3
3
  return array.reduce((accumulator, current, index) => {
4
4
  return current > array[accumulator] ? index : accumulator;
package/dist/types.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export * from "./events";
2
- export { CARDS, CARDS_HUMAN_READABLE, BURNT_CARD } from "./constants";
2
+ export { CARDS, CARDS_HUMAN_READABLE, BURNT_CARD } from "./lib/constants";
3
3
  import { User } from "lightning-accounts";
4
- import { CARDS } from "./lib";
5
4
  import { Match, MatchPlayer, MatchHand, UserStats } from "@trucoshi/prisma";
6
5
  import { IHand } from "./truco";
6
+ import { CARDS } from "./lib";
7
7
  export declare enum EMatchState {
8
8
  UNREADY = "UNREADY",
9
9
  READY = "READY",
@@ -237,12 +237,17 @@ export interface IHandPoints {
237
237
  export interface IRandom {
238
238
  secret: string;
239
239
  clients: string[];
240
+ bitcoinHash: string;
241
+ bitcoinHeight: number;
240
242
  nonce: number;
243
+ getLatestBitcoinBlock(): Promise<void>;
241
244
  next(): void;
242
245
  pick(idx: number, max: number): number;
243
246
  reveal(): {
244
247
  secret: string;
245
248
  clients: string[];
249
+ bitcoinHash: string;
250
+ bitcoinHeight: number;
246
251
  };
247
252
  }
248
253
  export type IPublicPlayer = Pick<IPlayer, "idx" | "key" | "name" | "abandonedTime" | "accountId" | "avatarUrl" | "disabled" | "abandoned" | "ready" | "hand" | "usedHand" | "prevHand" | "teamIdx" | "isTurn" | "turnExpiresAt" | "turnExtensionExpiresAt" | "isEnvidoTurn" | "isOwner"> & ({
package/dist/types.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from "./events";
2
- export { CARDS, CARDS_HUMAN_READABLE, BURNT_CARD } from "./constants";
2
+ export { CARDS, CARDS_HUMAN_READABLE, BURNT_CARD } from "./lib/constants";
3
3
  export var EMatchState;
4
4
  (function (EMatchState) {
5
5
  EMatchState["UNREADY"] = "UNREADY";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trucoshi",
3
- "version": "7.0.0-rc.9",
3
+ "version": "7.1.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": "^4.1.0",
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",