@actuallyfair/verifier 0.0.1 → 0.0.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/.github/workflows/publish.yml +28 -0
- package/dist/cli/context-codec.d.ts +1 -0
- package/dist/cli/context-codec.js +90 -0
- package/dist/compute-wager.d.ts +15 -1
- package/dist/compute-wager.js +63 -3
- package/dist/generated/context/index.d.ts +29 -170
- package/dist/generated/context/index.js +15 -287
- package/package.json +4 -2
- package/protobuf/context/index.proto +2 -22
- package/src/cli/context-codec.ts +103 -0
- package/src/compute-wager.ts +92 -2
- package/src/generated/context/index.ts +15 -332
- package/actuallyfair-verifier-0.0.7.tgz +0 -0
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.PosthashInit = exports.Context = void 0;
|
|
7
7
|
/* eslint-disable */
|
|
8
8
|
const minimal_1 = __importDefault(require("protobufjs/minimal"));
|
|
9
9
|
const crash_1 = require("./crash");
|
|
@@ -24,6 +24,7 @@ function createBaseContext() {
|
|
|
24
24
|
mines: undefined,
|
|
25
25
|
tower: undefined,
|
|
26
26
|
plinko: undefined,
|
|
27
|
+
init: undefined,
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
30
|
exports.Context = {
|
|
@@ -52,6 +53,9 @@ exports.Context = {
|
|
|
52
53
|
if (message.plinko !== undefined) {
|
|
53
54
|
plinko_1.Plinko.encode(message.plinko, writer.uint32(66).fork()).ldelim();
|
|
54
55
|
}
|
|
56
|
+
if (message.init !== undefined) {
|
|
57
|
+
exports.PosthashInit.encode(message.init, writer.uint32(74).fork()).ldelim();
|
|
58
|
+
}
|
|
55
59
|
return writer;
|
|
56
60
|
},
|
|
57
61
|
decode(input, length) {
|
|
@@ -109,6 +113,12 @@ exports.Context = {
|
|
|
109
113
|
}
|
|
110
114
|
message.plinko = plinko_1.Plinko.decode(reader, reader.uint32());
|
|
111
115
|
continue;
|
|
116
|
+
case 9:
|
|
117
|
+
if (tag !== 74) {
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
message.init = exports.PosthashInit.decode(reader, reader.uint32());
|
|
121
|
+
continue;
|
|
112
122
|
}
|
|
113
123
|
if ((tag & 7) === 4 || tag === 0) {
|
|
114
124
|
break;
|
|
@@ -127,6 +137,7 @@ exports.Context = {
|
|
|
127
137
|
mines: isSet(object.mines) ? mines_1.Mines.fromJSON(object.mines) : undefined,
|
|
128
138
|
tower: isSet(object.tower) ? tower_1.Tower.fromJSON(object.tower) : undefined,
|
|
129
139
|
plinko: isSet(object.plinko) ? plinko_1.Plinko.fromJSON(object.plinko) : undefined,
|
|
140
|
+
init: isSet(object.init) ? exports.PosthashInit.fromJSON(object.init) : undefined,
|
|
130
141
|
};
|
|
131
142
|
},
|
|
132
143
|
toJSON(message) {
|
|
@@ -155,6 +166,9 @@ exports.Context = {
|
|
|
155
166
|
if (message.plinko !== undefined) {
|
|
156
167
|
obj.plinko = plinko_1.Plinko.toJSON(message.plinko);
|
|
157
168
|
}
|
|
169
|
+
if (message.init !== undefined) {
|
|
170
|
+
obj.init = exports.PosthashInit.toJSON(message.init);
|
|
171
|
+
}
|
|
158
172
|
return obj;
|
|
159
173
|
},
|
|
160
174
|
create(base) {
|
|
@@ -178,92 +192,9 @@ exports.Context = {
|
|
|
178
192
|
message.plinko = (object.plinko !== undefined && object.plinko !== null)
|
|
179
193
|
? plinko_1.Plinko.fromPartial(object.plinko)
|
|
180
194
|
: undefined;
|
|
181
|
-
return message;
|
|
182
|
-
},
|
|
183
|
-
};
|
|
184
|
-
function createBasePosthashContext() {
|
|
185
|
-
return { init: undefined, dice: undefined, plinko: undefined };
|
|
186
|
-
}
|
|
187
|
-
exports.PosthashContext = {
|
|
188
|
-
encode(message, writer = minimal_1.default.Writer.create()) {
|
|
189
|
-
if (message.init !== undefined) {
|
|
190
|
-
exports.PosthashInit.encode(message.init, writer.uint32(10).fork()).ldelim();
|
|
191
|
-
}
|
|
192
|
-
if (message.dice !== undefined) {
|
|
193
|
-
exports.PosthashDice.encode(message.dice, writer.uint32(18).fork()).ldelim();
|
|
194
|
-
}
|
|
195
|
-
if (message.plinko !== undefined) {
|
|
196
|
-
exports.PosthashPlinko.encode(message.plinko, writer.uint32(26).fork()).ldelim();
|
|
197
|
-
}
|
|
198
|
-
return writer;
|
|
199
|
-
},
|
|
200
|
-
decode(input, length) {
|
|
201
|
-
const reader = input instanceof minimal_1.default.Reader ? input : minimal_1.default.Reader.create(input);
|
|
202
|
-
let end = length === undefined ? reader.len : reader.pos + length;
|
|
203
|
-
const message = createBasePosthashContext();
|
|
204
|
-
while (reader.pos < end) {
|
|
205
|
-
const tag = reader.uint32();
|
|
206
|
-
switch (tag >>> 3) {
|
|
207
|
-
case 1:
|
|
208
|
-
if (tag !== 10) {
|
|
209
|
-
break;
|
|
210
|
-
}
|
|
211
|
-
message.init = exports.PosthashInit.decode(reader, reader.uint32());
|
|
212
|
-
continue;
|
|
213
|
-
case 2:
|
|
214
|
-
if (tag !== 18) {
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
message.dice = exports.PosthashDice.decode(reader, reader.uint32());
|
|
218
|
-
continue;
|
|
219
|
-
case 3:
|
|
220
|
-
if (tag !== 26) {
|
|
221
|
-
break;
|
|
222
|
-
}
|
|
223
|
-
message.plinko = exports.PosthashPlinko.decode(reader, reader.uint32());
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
if ((tag & 7) === 4 || tag === 0) {
|
|
227
|
-
break;
|
|
228
|
-
}
|
|
229
|
-
reader.skipType(tag & 7);
|
|
230
|
-
}
|
|
231
|
-
return message;
|
|
232
|
-
},
|
|
233
|
-
fromJSON(object) {
|
|
234
|
-
return {
|
|
235
|
-
init: isSet(object.init) ? exports.PosthashInit.fromJSON(object.init) : undefined,
|
|
236
|
-
dice: isSet(object.dice) ? exports.PosthashDice.fromJSON(object.dice) : undefined,
|
|
237
|
-
plinko: isSet(object.plinko) ? exports.PosthashPlinko.fromJSON(object.plinko) : undefined,
|
|
238
|
-
};
|
|
239
|
-
},
|
|
240
|
-
toJSON(message) {
|
|
241
|
-
const obj = {};
|
|
242
|
-
if (message.init !== undefined) {
|
|
243
|
-
obj.init = exports.PosthashInit.toJSON(message.init);
|
|
244
|
-
}
|
|
245
|
-
if (message.dice !== undefined) {
|
|
246
|
-
obj.dice = exports.PosthashDice.toJSON(message.dice);
|
|
247
|
-
}
|
|
248
|
-
if (message.plinko !== undefined) {
|
|
249
|
-
obj.plinko = exports.PosthashPlinko.toJSON(message.plinko);
|
|
250
|
-
}
|
|
251
|
-
return obj;
|
|
252
|
-
},
|
|
253
|
-
create(base) {
|
|
254
|
-
return exports.PosthashContext.fromPartial(base ?? {});
|
|
255
|
-
},
|
|
256
|
-
fromPartial(object) {
|
|
257
|
-
const message = createBasePosthashContext();
|
|
258
195
|
message.init = (object.init !== undefined && object.init !== null)
|
|
259
196
|
? exports.PosthashInit.fromPartial(object.init)
|
|
260
197
|
: undefined;
|
|
261
|
-
message.dice = (object.dice !== undefined && object.dice !== null)
|
|
262
|
-
? exports.PosthashDice.fromPartial(object.dice)
|
|
263
|
-
: undefined;
|
|
264
|
-
message.plinko = (object.plinko !== undefined && object.plinko !== null)
|
|
265
|
-
? exports.PosthashPlinko.fromPartial(object.plinko)
|
|
266
|
-
: undefined;
|
|
267
198
|
return message;
|
|
268
199
|
},
|
|
269
200
|
};
|
|
@@ -304,209 +235,6 @@ exports.PosthashInit = {
|
|
|
304
235
|
return message;
|
|
305
236
|
},
|
|
306
237
|
};
|
|
307
|
-
function createBasePosthashDice() {
|
|
308
|
-
return { target: 0, clientSeed: "", hashchainServerHash: new Uint8Array(0) };
|
|
309
|
-
}
|
|
310
|
-
exports.PosthashDice = {
|
|
311
|
-
encode(message, writer = minimal_1.default.Writer.create()) {
|
|
312
|
-
if (message.target !== 0) {
|
|
313
|
-
writer.uint32(9).double(message.target);
|
|
314
|
-
}
|
|
315
|
-
if (message.clientSeed !== "") {
|
|
316
|
-
writer.uint32(18).string(message.clientSeed);
|
|
317
|
-
}
|
|
318
|
-
if (message.hashchainServerHash.length !== 0) {
|
|
319
|
-
writer.uint32(26).bytes(message.hashchainServerHash);
|
|
320
|
-
}
|
|
321
|
-
return writer;
|
|
322
|
-
},
|
|
323
|
-
decode(input, length) {
|
|
324
|
-
const reader = input instanceof minimal_1.default.Reader ? input : minimal_1.default.Reader.create(input);
|
|
325
|
-
let end = length === undefined ? reader.len : reader.pos + length;
|
|
326
|
-
const message = createBasePosthashDice();
|
|
327
|
-
while (reader.pos < end) {
|
|
328
|
-
const tag = reader.uint32();
|
|
329
|
-
switch (tag >>> 3) {
|
|
330
|
-
case 1:
|
|
331
|
-
if (tag !== 9) {
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
message.target = reader.double();
|
|
335
|
-
continue;
|
|
336
|
-
case 2:
|
|
337
|
-
if (tag !== 18) {
|
|
338
|
-
break;
|
|
339
|
-
}
|
|
340
|
-
message.clientSeed = reader.string();
|
|
341
|
-
continue;
|
|
342
|
-
case 3:
|
|
343
|
-
if (tag !== 26) {
|
|
344
|
-
break;
|
|
345
|
-
}
|
|
346
|
-
message.hashchainServerHash = reader.bytes();
|
|
347
|
-
continue;
|
|
348
|
-
}
|
|
349
|
-
if ((tag & 7) === 4 || tag === 0) {
|
|
350
|
-
break;
|
|
351
|
-
}
|
|
352
|
-
reader.skipType(tag & 7);
|
|
353
|
-
}
|
|
354
|
-
return message;
|
|
355
|
-
},
|
|
356
|
-
fromJSON(object) {
|
|
357
|
-
return {
|
|
358
|
-
target: isSet(object.target) ? globalThis.Number(object.target) : 0,
|
|
359
|
-
clientSeed: isSet(object.clientSeed) ? globalThis.String(object.clientSeed) : "",
|
|
360
|
-
hashchainServerHash: isSet(object.hashchainServerHash)
|
|
361
|
-
? bytesFromBase64(object.hashchainServerHash)
|
|
362
|
-
: new Uint8Array(0),
|
|
363
|
-
};
|
|
364
|
-
},
|
|
365
|
-
toJSON(message) {
|
|
366
|
-
const obj = {};
|
|
367
|
-
if (message.target !== 0) {
|
|
368
|
-
obj.target = message.target;
|
|
369
|
-
}
|
|
370
|
-
if (message.clientSeed !== "") {
|
|
371
|
-
obj.clientSeed = message.clientSeed;
|
|
372
|
-
}
|
|
373
|
-
if (message.hashchainServerHash.length !== 0) {
|
|
374
|
-
obj.hashchainServerHash = base64FromBytes(message.hashchainServerHash);
|
|
375
|
-
}
|
|
376
|
-
return obj;
|
|
377
|
-
},
|
|
378
|
-
create(base) {
|
|
379
|
-
return exports.PosthashDice.fromPartial(base ?? {});
|
|
380
|
-
},
|
|
381
|
-
fromPartial(object) {
|
|
382
|
-
const message = createBasePosthashDice();
|
|
383
|
-
message.target = object.target ?? 0;
|
|
384
|
-
message.clientSeed = object.clientSeed ?? "";
|
|
385
|
-
message.hashchainServerHash = object.hashchainServerHash ?? new Uint8Array(0);
|
|
386
|
-
return message;
|
|
387
|
-
},
|
|
388
|
-
};
|
|
389
|
-
function createBasePosthashPlinko() {
|
|
390
|
-
return { rows: 0, riskLevel: "", clientSeed: "", hashchainServerHash: new Uint8Array(0) };
|
|
391
|
-
}
|
|
392
|
-
exports.PosthashPlinko = {
|
|
393
|
-
encode(message, writer = minimal_1.default.Writer.create()) {
|
|
394
|
-
if (message.rows !== 0) {
|
|
395
|
-
writer.uint32(8).uint32(message.rows);
|
|
396
|
-
}
|
|
397
|
-
if (message.riskLevel !== "") {
|
|
398
|
-
writer.uint32(18).string(message.riskLevel);
|
|
399
|
-
}
|
|
400
|
-
if (message.clientSeed !== "") {
|
|
401
|
-
writer.uint32(26).string(message.clientSeed);
|
|
402
|
-
}
|
|
403
|
-
if (message.hashchainServerHash.length !== 0) {
|
|
404
|
-
writer.uint32(34).bytes(message.hashchainServerHash);
|
|
405
|
-
}
|
|
406
|
-
return writer;
|
|
407
|
-
},
|
|
408
|
-
decode(input, length) {
|
|
409
|
-
const reader = input instanceof minimal_1.default.Reader ? input : minimal_1.default.Reader.create(input);
|
|
410
|
-
let end = length === undefined ? reader.len : reader.pos + length;
|
|
411
|
-
const message = createBasePosthashPlinko();
|
|
412
|
-
while (reader.pos < end) {
|
|
413
|
-
const tag = reader.uint32();
|
|
414
|
-
switch (tag >>> 3) {
|
|
415
|
-
case 1:
|
|
416
|
-
if (tag !== 8) {
|
|
417
|
-
break;
|
|
418
|
-
}
|
|
419
|
-
message.rows = reader.uint32();
|
|
420
|
-
continue;
|
|
421
|
-
case 2:
|
|
422
|
-
if (tag !== 18) {
|
|
423
|
-
break;
|
|
424
|
-
}
|
|
425
|
-
message.riskLevel = reader.string();
|
|
426
|
-
continue;
|
|
427
|
-
case 3:
|
|
428
|
-
if (tag !== 26) {
|
|
429
|
-
break;
|
|
430
|
-
}
|
|
431
|
-
message.clientSeed = reader.string();
|
|
432
|
-
continue;
|
|
433
|
-
case 4:
|
|
434
|
-
if (tag !== 34) {
|
|
435
|
-
break;
|
|
436
|
-
}
|
|
437
|
-
message.hashchainServerHash = reader.bytes();
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
if ((tag & 7) === 4 || tag === 0) {
|
|
441
|
-
break;
|
|
442
|
-
}
|
|
443
|
-
reader.skipType(tag & 7);
|
|
444
|
-
}
|
|
445
|
-
return message;
|
|
446
|
-
},
|
|
447
|
-
fromJSON(object) {
|
|
448
|
-
return {
|
|
449
|
-
rows: isSet(object.rows) ? globalThis.Number(object.rows) : 0,
|
|
450
|
-
riskLevel: isSet(object.riskLevel) ? globalThis.String(object.riskLevel) : "",
|
|
451
|
-
clientSeed: isSet(object.clientSeed) ? globalThis.String(object.clientSeed) : "",
|
|
452
|
-
hashchainServerHash: isSet(object.hashchainServerHash)
|
|
453
|
-
? bytesFromBase64(object.hashchainServerHash)
|
|
454
|
-
: new Uint8Array(0),
|
|
455
|
-
};
|
|
456
|
-
},
|
|
457
|
-
toJSON(message) {
|
|
458
|
-
const obj = {};
|
|
459
|
-
if (message.rows !== 0) {
|
|
460
|
-
obj.rows = Math.round(message.rows);
|
|
461
|
-
}
|
|
462
|
-
if (message.riskLevel !== "") {
|
|
463
|
-
obj.riskLevel = message.riskLevel;
|
|
464
|
-
}
|
|
465
|
-
if (message.clientSeed !== "") {
|
|
466
|
-
obj.clientSeed = message.clientSeed;
|
|
467
|
-
}
|
|
468
|
-
if (message.hashchainServerHash.length !== 0) {
|
|
469
|
-
obj.hashchainServerHash = base64FromBytes(message.hashchainServerHash);
|
|
470
|
-
}
|
|
471
|
-
return obj;
|
|
472
|
-
},
|
|
473
|
-
create(base) {
|
|
474
|
-
return exports.PosthashPlinko.fromPartial(base ?? {});
|
|
475
|
-
},
|
|
476
|
-
fromPartial(object) {
|
|
477
|
-
const message = createBasePosthashPlinko();
|
|
478
|
-
message.rows = object.rows ?? 0;
|
|
479
|
-
message.riskLevel = object.riskLevel ?? "";
|
|
480
|
-
message.clientSeed = object.clientSeed ?? "";
|
|
481
|
-
message.hashchainServerHash = object.hashchainServerHash ?? new Uint8Array(0);
|
|
482
|
-
return message;
|
|
483
|
-
},
|
|
484
|
-
};
|
|
485
|
-
function bytesFromBase64(b64) {
|
|
486
|
-
if (globalThis.Buffer) {
|
|
487
|
-
return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
const bin = globalThis.atob(b64);
|
|
491
|
-
const arr = new Uint8Array(bin.length);
|
|
492
|
-
for (let i = 0; i < bin.length; ++i) {
|
|
493
|
-
arr[i] = bin.charCodeAt(i);
|
|
494
|
-
}
|
|
495
|
-
return arr;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
function base64FromBytes(arr) {
|
|
499
|
-
if (globalThis.Buffer) {
|
|
500
|
-
return globalThis.Buffer.from(arr).toString("base64");
|
|
501
|
-
}
|
|
502
|
-
else {
|
|
503
|
-
const bin = [];
|
|
504
|
-
arr.forEach((byte) => {
|
|
505
|
-
bin.push(globalThis.String.fromCharCode(byte));
|
|
506
|
-
});
|
|
507
|
-
return globalThis.btoa(bin.join(""));
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
238
|
function isSet(value) {
|
|
511
239
|
return value !== null && value !== undefined;
|
|
512
240
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actuallyfair/verifier",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"clean": "rm -rf dist && mkdir dist && rm -rf src/generated && mkdir src/generated",
|
|
9
9
|
"build": "npm run clean && npm run generate && tsc",
|
|
10
|
-
"generate": "protoc --proto_path=./protobuf --plugin=./node_modules/.bin/protoc-gen-ts_proto
|
|
10
|
+
"generate": "protoc --proto_path=./protobuf --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_opt=esModuleInterop=true --ts_proto_opt=exportCommonSymbols=false --ts_proto_out=./src/generated ./protobuf/context/*.proto ./protobuf/amount.proto ./protobuf/currency.proto",
|
|
11
|
+
"decode": "tsx ./src/cli/context-codec.ts decode",
|
|
12
|
+
"encode": "tsx ./src/cli/context-codec.ts encode",
|
|
11
13
|
"prepublishOnly": "npm run build"
|
|
12
14
|
},
|
|
13
15
|
"publishConfig": {
|
|
@@ -4,9 +4,9 @@ import "context/fair-coin-toss.proto";
|
|
|
4
4
|
import "context/crash.proto";
|
|
5
5
|
import "context/hilo.proto";
|
|
6
6
|
import "context/crash-dice.proto";
|
|
7
|
+
import "context/multi-roulette.proto";
|
|
7
8
|
import "context/mines.proto";
|
|
8
9
|
import "context/tower.proto";
|
|
9
|
-
import "context/multi-roulette.proto";
|
|
10
10
|
import "context/plinko.proto";
|
|
11
11
|
|
|
12
12
|
message Context {
|
|
@@ -19,28 +19,8 @@ message Context {
|
|
|
19
19
|
Mines mines = 6;
|
|
20
20
|
Tower tower = 7;
|
|
21
21
|
Plinko plinko = 8;
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
message PosthashContext {
|
|
26
|
-
oneof payload {
|
|
27
|
-
PosthashInit init = 1;
|
|
28
|
-
PosthashDice dice = 2;
|
|
29
|
-
PosthashPlinko plinko = 3;
|
|
22
|
+
PosthashInit init = 9;
|
|
30
23
|
}
|
|
31
24
|
}
|
|
32
25
|
|
|
33
26
|
message PosthashInit {}
|
|
34
|
-
|
|
35
|
-
message PosthashDice {
|
|
36
|
-
double target = 1;
|
|
37
|
-
string client_seed = 2;
|
|
38
|
-
bytes hashchain_server_hash = 3;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
message PosthashPlinko {
|
|
42
|
-
uint32 rows = 1;
|
|
43
|
-
string risk_level = 2;
|
|
44
|
-
string client_seed = 3;
|
|
45
|
-
bytes hashchain_server_hash = 4;
|
|
46
|
-
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Context } from "../generated/context";
|
|
2
|
+
|
|
3
|
+
type Mode = "decode" | "encode";
|
|
4
|
+
|
|
5
|
+
function isMode(value: string | undefined): value is Mode {
|
|
6
|
+
return value === "decode" || value === "encode";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function normalizeBase64(input: string): string {
|
|
10
|
+
const cleaned = input.replace(/\s+/g, "").replace(/-/g, "+").replace(/_/g, "/");
|
|
11
|
+
const padding = cleaned.length % 4;
|
|
12
|
+
return padding === 0 ? cleaned : `${cleaned}${"=".repeat(4 - padding)}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function readStdin(): Promise<string> {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
let data = "";
|
|
18
|
+
process.stdin.setEncoding("utf8");
|
|
19
|
+
process.stdin.on("data", (chunk) => {
|
|
20
|
+
data += chunk;
|
|
21
|
+
});
|
|
22
|
+
process.stdin.on("end", () => resolve(data));
|
|
23
|
+
process.stdin.on("error", reject);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function readInput(args: string[]): Promise<string> {
|
|
28
|
+
if (args.length > 0) {
|
|
29
|
+
return args.join(" ").trim();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (process.stdin.isTTY) {
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const data = await readStdin();
|
|
37
|
+
return data.trim();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function usage(mode?: Mode): string[] {
|
|
41
|
+
if (mode === "decode") {
|
|
42
|
+
return ["Usage: npm run decode -- <base64>", " cat context.b64 | npm run decode"];
|
|
43
|
+
}
|
|
44
|
+
if (mode === "encode") {
|
|
45
|
+
return ["Usage: npm run encode -- '<json>'", " cat context.json | npm run encode"];
|
|
46
|
+
}
|
|
47
|
+
return [
|
|
48
|
+
"Usage: npm run decode -- <base64>",
|
|
49
|
+
" npm run encode -- '<json>'",
|
|
50
|
+
" cat context.b64 | npm run decode",
|
|
51
|
+
" cat context.json | npm run encode",
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function printUsage(mode?: Mode): void {
|
|
56
|
+
for (const line of usage(mode)) {
|
|
57
|
+
console.error(line);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function errorMessage(error: unknown): string {
|
|
62
|
+
if (error instanceof Error) {
|
|
63
|
+
return error.message;
|
|
64
|
+
}
|
|
65
|
+
return String(error);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function main(): Promise<void> {
|
|
69
|
+
const [modeRaw, ...rest] = process.argv.slice(2);
|
|
70
|
+
if (!isMode(modeRaw)) {
|
|
71
|
+
printUsage();
|
|
72
|
+
process.exit(1);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const input = await readInput(rest);
|
|
77
|
+
if (!input) {
|
|
78
|
+
printUsage(modeRaw);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
if (modeRaw === "decode") {
|
|
85
|
+
const base64 = normalizeBase64(input);
|
|
86
|
+
const bytes = Buffer.from(base64, "base64");
|
|
87
|
+
const message = Context.decode(bytes);
|
|
88
|
+
const json = Context.toJSON(message);
|
|
89
|
+
process.stdout.write(`${JSON.stringify(json, null, 2)}\n`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const parsed = JSON.parse(input) as unknown;
|
|
94
|
+
const message = Context.fromJSON(parsed);
|
|
95
|
+
const encoded = Context.encode(message).finish();
|
|
96
|
+
process.stdout.write(`${Buffer.from(encoded).toString("base64")}\n`);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(`Failed to ${modeRaw} context: ${errorMessage(error)}`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void main();
|
package/src/compute-wager.ts
CHANGED
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
FairCoinToss_Choice,
|
|
13
13
|
} from "./generated/context/fair-coin-toss";
|
|
14
14
|
import { bytesToHex } from "@noble/hashes/utils";
|
|
15
|
+
import { CrashDice } from "./generated/context/crash-dice";
|
|
15
16
|
import { MultiRoulette } from "./generated/context/multi-roulette";
|
|
17
|
+
import { Plinko } from "./generated/context/plinko";
|
|
16
18
|
|
|
17
19
|
export function computeFairCoinTossResult(sig: Uint8Array) {
|
|
18
20
|
// We're going to hash the signature just to really be sure its fairly distributed
|
|
@@ -65,8 +67,30 @@ export function computeCrashResult(
|
|
|
65
67
|
return doComputeCrashResult(hmac(sha256, vxSignature, gameHash), houseEdge);
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
export
|
|
69
|
-
|
|
70
|
+
export type CrashDiceOutcome = {
|
|
71
|
+
multiplier: number;
|
|
72
|
+
target: number;
|
|
73
|
+
win: boolean;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export function computeCrashDiceResult(hash: Uint8Array, clientSeed: string) {
|
|
77
|
+
const rollHash = hmacSha256(hash, clientSeed);
|
|
78
|
+
return multiplierFromHash(rollHash);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function computeCrashDiceOutcome(
|
|
82
|
+
hash: Uint8Array,
|
|
83
|
+
clientSeed: string,
|
|
84
|
+
bet: CrashDice
|
|
85
|
+
): CrashDiceOutcome {
|
|
86
|
+
const multiplier = computeCrashDiceResult(hash, clientSeed);
|
|
87
|
+
const target = bet.target;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
multiplier,
|
|
91
|
+
target,
|
|
92
|
+
win: multiplier >= target,
|
|
93
|
+
};
|
|
70
94
|
}
|
|
71
95
|
|
|
72
96
|
// returns the index of which roulette outcome was picked
|
|
@@ -243,3 +267,69 @@ export function computePlinkoHouseEdge(possibilities: number[]) {
|
|
|
243
267
|
}
|
|
244
268
|
return ev;
|
|
245
269
|
}
|
|
270
|
+
|
|
271
|
+
export type PlinkoResult = {
|
|
272
|
+
slot: number;
|
|
273
|
+
multiplier: number;
|
|
274
|
+
win: boolean;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
export function computePlinkoResult(
|
|
278
|
+
hash: Uint8Array,
|
|
279
|
+
clientSeed: string,
|
|
280
|
+
bet: Plinko
|
|
281
|
+
): PlinkoResult {
|
|
282
|
+
const possibilities = bet.possibilities;
|
|
283
|
+
if (possibilities.length < 2) {
|
|
284
|
+
throw new Error("invalid possibilities ");
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const probabilities = computePlinkoPascalsProbabilities(possibilities.length);
|
|
288
|
+
const rollHash = hmacSha256(hash, clientSeed);
|
|
289
|
+
const roll = uniformFromHash(rollHash);
|
|
290
|
+
const slot = pickSlot(probabilities, roll);
|
|
291
|
+
const multiplier = possibilities[slot] ?? 0;
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
slot,
|
|
295
|
+
multiplier,
|
|
296
|
+
win: multiplier >= 1,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function hmacSha256(key: Uint8Array, message: string): Uint8Array {
|
|
301
|
+
const data = new TextEncoder().encode(message);
|
|
302
|
+
return hmac(sha256, key, data);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function multiplierFromHash(hash: Uint8Array): number {
|
|
306
|
+
if (hash.length < 4) {
|
|
307
|
+
throw new Error("Hash must be at least 4 bytes.");
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const value = (hash[0] << 24) | (hash[1] << 16) | (hash[2] << 8) | hash[3];
|
|
311
|
+
const normalized = value >>> 0;
|
|
312
|
+
const max = 2 ** 32;
|
|
313
|
+
const multiplierTimes100 = Math.floor((100 * max) / (max - normalized));
|
|
314
|
+
return multiplierTimes100 / 100;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function uniformFromHash(hash: Uint8Array): number {
|
|
318
|
+
if (hash.length < 4) {
|
|
319
|
+
throw new Error("Hash must be at least 4 bytes.");
|
|
320
|
+
}
|
|
321
|
+
const value = (hash[0] << 24) | (hash[1] << 16) | (hash[2] << 8) | hash[3];
|
|
322
|
+
const normalized = value >>> 0;
|
|
323
|
+
return normalized / 2 ** 32;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function pickSlot(probabilities: number[], roll: number): number {
|
|
327
|
+
let cumulative = 0;
|
|
328
|
+
for (let i = 0; i < probabilities.length; i += 1) {
|
|
329
|
+
cumulative += probabilities[i];
|
|
330
|
+
if (roll <= cumulative) {
|
|
331
|
+
return i;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return probabilities.length - 1;
|
|
335
|
+
}
|