shufflecom-calculations 2.2.26 → 2.2.28

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.
@@ -44,7 +44,7 @@ exports.ADDRESS_LINK_PREFIXES_TESTNET = {
44
44
  [chain_1.Chain.BINANCE_SMART_CHAIN]: 'https://testnet.bscscan.com/address/{address}',
45
45
  [chain_1.Chain.TON]: 'https://testnet.tonviewer.com/{address}',
46
46
  [chain_1.Chain.AVAXC]: 'https://testnet.snowtrace.io/address/{address}',
47
- [chain_1.Chain.ARBITRUM]: 'https://sepolia.arbiscan.io/tx/{address}',
47
+ [chain_1.Chain.ARBITRUM]: 'https://sepolia.arbiscan.io/address/{address}',
48
48
  [chain_1.Chain.BASE]: 'https://sepolia.basescan.org/address/{address}',
49
49
  };
50
50
  exports.ADDRESS_LINK_PREFIXES_MAINNET = {
@@ -59,7 +59,7 @@ exports.ADDRESS_LINK_PREFIXES_MAINNET = {
59
59
  [chain_1.Chain.BINANCE_SMART_CHAIN]: 'https://bscscan.com/address/{address}',
60
60
  [chain_1.Chain.TON]: 'https://tonviewer.com/{address}',
61
61
  [chain_1.Chain.AVAXC]: 'https://snowtrace.io/address/{address}',
62
- [chain_1.Chain.ARBITRUM]: 'https://arbiscan.io/tx/{address}',
62
+ [chain_1.Chain.ARBITRUM]: 'https://arbiscan.io/address/{address}',
63
63
  [chain_1.Chain.BASE]: 'https://basescan.org/address/{address}',
64
64
  };
65
65
  const getExternalTxLinkOfChain = (txId, chain, isTest = false) => {
@@ -1 +1 @@
1
- {"version":3,"file":"getExternalTxLinkOfChain.js","sourceRoot":"","sources":["../../src/utils/getExternalTxLinkOfChain.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"getExternalTxLinkOfChain.js","sourceRoot":"","sources":["../../src/utils/getExternalTxLinkOfChain.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shufflecom-calculations",
3
- "version": "2.2.26",
3
+ "version": "2.2.28",
4
4
  "description": "",
5
5
  "types": "lib/index.d.ts",
6
6
  "main": "lib/index.js",
@@ -14,5 +14,5 @@
14
14
  },
15
15
  "author": "",
16
16
  "license": "ISC",
17
- "gitHead": "85bef9f6b2bece1a68385d1bbca3e35ea0c5f4f1"
17
+ "gitHead": "f93f069df131f9667420808c2c2e6f255f8e96a2"
18
18
  }
@@ -156,7 +156,11 @@ export class Blackjack {
156
156
  return true;
157
157
  }
158
158
 
159
- static getHandOutcome(dealerCards: readonly number[], playerCards: readonly number[], hasSplit: boolean): { multiplier: BigNumber; outcome: HandOutcome } {
159
+ static getHandOutcome(
160
+ dealerCards: readonly number[],
161
+ playerCards: readonly number[],
162
+ hasSplit: boolean,
163
+ ): { multiplier: BigNumber; outcome: HandOutcome } {
160
164
  const dealerBlackjack = this.isBlackjack(dealerCards);
161
165
  const playerBlackjack = this.isBlackjack(playerCards);
162
166
 
@@ -194,7 +198,10 @@ export class Blackjack {
194
198
  }
195
199
  }
196
200
 
197
- static calcSideBetWins(dealerUpCard: number, playerCards: readonly number[]): { perfectPair?: PerfectPairType; twentyOnePlusThree?: TwentyOnePlusThreeType } {
201
+ static calcSideBetWins(
202
+ dealerUpCard: number,
203
+ playerCards: readonly number[],
204
+ ): { perfectPair?: PerfectPairType; twentyOnePlusThree?: TwentyOnePlusThreeType } {
198
205
  const results: { perfectPair?: PerfectPairType; twentyOnePlusThree?: TwentyOnePlusThreeType } = {};
199
206
  const dealerCardDetails = CardGames.getCardDetails(dealerUpCard);
200
207
  const playerCard0 = CardGames.getCardDetails(playerCards[0]);
@@ -230,7 +237,9 @@ export class Blackjack {
230
237
  A: [14, 1],
231
238
  };
232
239
 
233
- const cardValues = [...cardValueMap[playerCard0.value], ...cardValueMap[playerCard1.value], ...cardValueMap[dealerCardDetails.value]].sort((a, b) => a - b);
240
+ const cardValues = [...cardValueMap[playerCard0.value], ...cardValueMap[playerCard1.value], ...cardValueMap[dealerCardDetails.value]].sort(
241
+ (a, b) => a - b,
242
+ );
234
243
 
235
244
  const isFlush = dealerCardDetails.suit === playerCard0.suit && playerCard0.suit === playerCard1.suit;
236
245
  const firstThreeCards = cardValues.slice(0, 3) as [number, number, number];
@@ -275,7 +284,7 @@ export class Blackjack {
275
284
  K: 10,
276
285
  };
277
286
 
278
- let aceCount = CardGames.getCardDetailsArr(cards).filter((card) => card.value === 'A').length;
287
+ let aceCount = CardGames.getCardDetailsArr(cards).filter(card => card.value === 'A').length;
279
288
  let cardSum = CardGames.getCardDetailsArr(cards).reduce((acc, cur) => acc + cardValueMap[cur.value], 0);
280
289
 
281
290
  if (aceCount === 0) {
@@ -340,12 +349,36 @@ export class Blackjack {
340
349
  return newDealerHand;
341
350
  }
342
351
 
352
+ static getMaxPotentialPayout({
353
+ mainBetAmount,
354
+ twentyOnePlusThreeAmount,
355
+ perfectPairAmount,
356
+ }: {
357
+ mainBetAmount: BigNumber;
358
+ twentyOnePlusThreeAmount: BigNumber;
359
+ perfectPairAmount: BigNumber;
360
+ mainHandDoubleDown?: boolean;
361
+ }) {
362
+ const mainHandPayout = mainBetAmount.times(2.5);
363
+
364
+ const twentyOnePlusThreeMaxPayout = BigNumber.max(...Object.values(twentyOnePlusThreePayout)).times(twentyOnePlusThreeAmount);
365
+
366
+ const perfectPairMaxPayout = BigNumber.max(...Object.values(perfectPairPayout)).times(perfectPairAmount);
367
+
368
+ return mainHandPayout.plus(twentyOnePlusThreeMaxPayout).plus(perfectPairMaxPayout);
369
+ }
370
+
343
371
  /**
344
372
  *
345
373
  * Called after bet ends. Players can still win insurance or sidebets even if they lose the main bet
346
374
  * @returns total payout amount
347
375
  */
348
- static getGameOutcome(data: SettleBetVars): { payout: BigNumber; multiplier: BigNumber; mainHandOutcome: HandOutcome; splitHandOutcome: HandOutcome } {
376
+ static getGameOutcome(data: SettleBetVars): {
377
+ payout: BigNumber;
378
+ multiplier: BigNumber;
379
+ mainHandOutcome: HandOutcome;
380
+ splitHandOutcome: HandOutcome;
381
+ } {
349
382
  if (data.dealerHand.length < 2) {
350
383
  throw new Error('Dealer hole card is missing');
351
384
  }
@@ -360,9 +393,15 @@ export class Blackjack {
360
393
  let perfectPairPayoutAmt = new BigNumber(0);
361
394
  let twentyOnePlusThreePayoutAmt = new BigNumber(0);
362
395
 
363
- const { mainHandOutcome, payout: mainBetPayout, splitHandOutcome } = Blackjack.getMainBetPayout({ ...data, mainHandBetAmount, splitHandBetAmount });
396
+ const {
397
+ mainHandOutcome,
398
+ payout: mainBetPayout,
399
+ splitHandOutcome,
400
+ } = Blackjack.getMainBetPayout({ ...data, mainHandBetAmount, splitHandBetAmount });
364
401
 
365
- const playerHand: [number, number] = data.hasSplit ? [data.mainPlayerHand[0], data.splitPlayerHand[0]] : [data.mainPlayerHand[0], data.mainPlayerHand[1]];
402
+ const playerHand: [number, number] = data.hasSplit
403
+ ? [data.mainPlayerHand[0], data.splitPlayerHand[0]]
404
+ : [data.mainPlayerHand[0], data.mainPlayerHand[1]];
366
405
 
367
406
  const { perfectPair, twentyOnePlusThree } = Blackjack.calcSideBetWins(data.dealerHand[0], playerHand);
368
407
 
@@ -376,7 +415,11 @@ export class Blackjack {
376
415
 
377
416
  const payout = mainBetPayout.plus(perfectPairPayoutAmt).plus(twentyOnePlusThreePayoutAmt);
378
417
  const insuranceCost = data.boughtInsurance ? data.mainBetAmount.dividedBy(2) : new BigNumber(0); // insurance costs half of the main bet
379
- const totalBetAmount = mainHandBetAmount.plus(splitHandBetAmount).plus(data.perfectPairAmount).plus(data.twentyOnePlusThreeAmount).plus(insuranceCost);
418
+ const totalBetAmount = mainHandBetAmount
419
+ .plus(splitHandBetAmount)
420
+ .plus(data.perfectPairAmount)
421
+ .plus(data.twentyOnePlusThreeAmount)
422
+ .plus(insuranceCost);
380
423
 
381
424
  let multiplier = payout.dividedBy(totalBetAmount);
382
425
 
package/src/games/keno.ts CHANGED
@@ -127,6 +127,16 @@ export class Keno {
127
127
  return new BigNumber(config.payout[risk][matchedTiles.length] ?? 0);
128
128
  }
129
129
 
130
+ static getMaxMultiplier(risk: KenoRiskLevel, selectedTiles: number[]) {
131
+ const config = this.configs().find(config => config.tiles === selectedTiles.length);
132
+
133
+ if (!config) {
134
+ throw new Error(`No configuration found for ${selectedTiles.length} tiles`);
135
+ }
136
+
137
+ return new BigNumber(config.payout[risk][selectedTiles.length] ?? 0);
138
+ }
139
+
130
140
  static getResults(hexStr: string[], rows: number): number[] {
131
141
  const results: number[] = [];
132
142
  const grids = Array.from(Array(TOTAL_TILES.toNumber()).keys());
@@ -143,9 +153,7 @@ export class Keno {
143
153
  position = position.plus(new BigNumber(value).dividedBy(BYTE_TOTAL.pow(j + 1)));
144
154
  }
145
155
 
146
- position = position
147
- .multipliedBy(TOTAL_TILES.minus(new BigNumber(8 * counter + i)))
148
- .integerValue(BigNumber.ROUND_DOWN);
156
+ position = position.multipliedBy(TOTAL_TILES.minus(new BigNumber(8 * counter + i))).integerValue(BigNumber.ROUND_DOWN);
149
157
 
150
158
  results.push(grids.splice(position.toNumber(), 1)[0] + 1); // (0 to 39) + 1 = 1 + 40
151
159
  }
@@ -155,8 +163,6 @@ export class Keno {
155
163
  }
156
164
 
157
165
  static getChance({ correctPicks, picked }: { correctPicks: number; picked: number }) {
158
- return new BigNumber(nCr(10, correctPicks))
159
- .multipliedBy(nCr(30, picked - correctPicks))
160
- .dividedBy(new BigNumber(nCr(40, picked)));
166
+ return new BigNumber(nCr(10, correctPicks)).multipliedBy(nCr(30, picked - correctPicks)).dividedBy(new BigNumber(nCr(40, picked)));
161
167
  }
162
168
  }
@@ -67,39 +67,25 @@ const plinkoConfigs: PlinkConfig[] = [
67
67
  {
68
68
  rows: 14,
69
69
  payout: {
70
- [PlinkoRiskLevel.LOW_RISK]: [
71
- 7.1, 4, 1.9, 1.4, 1.3, 1.1, 1, 0.5, 1, 1.1, 1.3, 1.4, 1.9, 4, 7.1,
72
- ],
70
+ [PlinkoRiskLevel.LOW_RISK]: [7.1, 4, 1.9, 1.4, 1.3, 1.1, 1, 0.5, 1, 1.1, 1.3, 1.4, 1.9, 4, 7.1],
73
71
  [PlinkoRiskLevel.MEDIUM_RISK]: [58, 15, 7, 4, 1.9, 1, 0.5, 0.2, 0.5, 1, 1.9, 4, 7, 15, 58],
74
- [PlinkoRiskLevel.HIGH_RISK]: [
75
- 420, 56, 18, 5, 1.9, 0.3, 0.2, 0.2, 0.2, 0.3, 1.9, 5, 18, 56, 420,
76
- ],
72
+ [PlinkoRiskLevel.HIGH_RISK]: [420, 56, 18, 5, 1.9, 0.3, 0.2, 0.2, 0.2, 0.3, 1.9, 5, 18, 56, 420],
77
73
  },
78
74
  },
79
75
  {
80
76
  rows: 15,
81
77
  payout: {
82
78
  [PlinkoRiskLevel.LOW_RISK]: [15, 8, 3, 2, 1.5, 1.1, 1, 0.7, 0.7, 1, 1.1, 1.5, 2, 3, 8, 15],
83
- [PlinkoRiskLevel.MEDIUM_RISK]: [
84
- 88, 18, 11, 5, 3, 1.3, 0.5, 0.3, 0.3, 0.5, 1.3, 3, 5, 11, 18, 88,
85
- ],
86
- [PlinkoRiskLevel.HIGH_RISK]: [
87
- 620, 83, 27, 8, 3, 0.5, 0.2, 0.2, 0.2, 0.2, 0.5, 3, 8, 27, 83, 620,
88
- ],
79
+ [PlinkoRiskLevel.MEDIUM_RISK]: [88, 18, 11, 5, 3, 1.3, 0.5, 0.3, 0.3, 0.5, 1.3, 3, 5, 11, 18, 88],
80
+ [PlinkoRiskLevel.HIGH_RISK]: [620, 83, 27, 8, 3, 0.5, 0.2, 0.2, 0.2, 0.2, 0.5, 3, 8, 27, 83, 620],
89
81
  },
90
82
  },
91
83
  {
92
84
  rows: 16,
93
85
  payout: {
94
- [PlinkoRiskLevel.LOW_RISK]: [
95
- 16, 9, 2, 1.4, 1.4, 1.2, 1.1, 1, 0.5, 1, 1.1, 1.2, 1.4, 1.4, 2, 9, 16,
96
- ],
97
- [PlinkoRiskLevel.MEDIUM_RISK]: [
98
- 110, 41, 10, 5, 3, 1.5, 1, 0.5, 0.3, 0.5, 1, 1.5, 3, 5, 10, 41, 110,
99
- ],
100
- [PlinkoRiskLevel.HIGH_RISK]: [
101
- 1000, 130, 26, 9, 4, 2, 0.2, 0.2, 0.2, 0.2, 0.2, 2, 4, 9, 26, 130, 1000,
102
- ],
86
+ [PlinkoRiskLevel.LOW_RISK]: [16, 9, 2, 1.4, 1.4, 1.2, 1.1, 1, 0.5, 1, 1.1, 1.2, 1.4, 1.4, 2, 9, 16],
87
+ [PlinkoRiskLevel.MEDIUM_RISK]: [110, 41, 10, 5, 3, 1.5, 1, 0.5, 0.3, 0.5, 1, 1.5, 3, 5, 10, 41, 110],
88
+ [PlinkoRiskLevel.HIGH_RISK]: [1000, 130, 26, 9, 4, 2, 0.2, 0.2, 0.2, 0.2, 0.2, 2, 4, 9, 26, 130, 1000],
103
89
  },
104
90
  },
105
91
  ];
@@ -117,9 +103,7 @@ export class Plinko {
117
103
  }
118
104
 
119
105
  static calculateChances(rows: number): BigNumber[] {
120
- return Object.keys(Array(rows + 1)).map(position =>
121
- this.calculateChance(rows, parseInt(position)),
122
- );
106
+ return Object.keys(Array(rows + 1)).map(position => this.calculateChance(rows, parseInt(position)));
123
107
  }
124
108
 
125
109
  static calculateMultiplier(risk: PlinkoRiskLevel, rows: number, results: number[]) {
@@ -133,6 +117,16 @@ export class Plinko {
133
117
  return new BigNumber(config.payout[risk][position]);
134
118
  }
135
119
 
120
+ static getMaxMultiplier(risk: PlinkoRiskLevel, rows: number) {
121
+ const config = this.configs().find(config => config.rows === rows);
122
+
123
+ if (!config) {
124
+ throw new Error(`No configuration found for ${rows} rows`);
125
+ }
126
+
127
+ return new BigNumber(Math.max(...config.payout[risk]));
128
+ }
129
+
136
130
  static getResults(hexStr: string[], rows: number): number[] {
137
131
  const results: number[] = [];
138
132
  hexStr.map(hexToBytes).every(gameResultBytes => {
@@ -144,7 +144,9 @@ const isValidStraight = (num: number): boolean => {
144
144
  export const isValidStreet = (street: streetValue): boolean => {
145
145
  const sortedStreet = (street as unknown as number[]).sort((a, b) => a - b);
146
146
 
147
- return sortedStreet.length === 3 && STREET_VALUES.some((val) => val[0] === sortedStreet[0] && val[1] === sortedStreet[1] && val[2] === sortedStreet[2]);
147
+ return (
148
+ sortedStreet.length === 3 && STREET_VALUES.some(val => val[0] === sortedStreet[0] && val[1] === sortedStreet[1] && val[2] === sortedStreet[2])
149
+ );
148
150
  };
149
151
 
150
152
  // for corners (up, down, left, right, and diagonally adjacent)
@@ -174,7 +176,7 @@ export const cornerNumbers = (num: straightValue): straightValue[] => {
174
176
  possibleCornerNumbers = [num - 4, num - 3, num - 1, num + 2, num + 3];
175
177
  }
176
178
 
177
- return possibleCornerNumbers.filter((num) => isValidStraight(num)) as straightValue[];
179
+ return possibleCornerNumbers.filter(num => isValidStraight(num)) as straightValue[];
178
180
  };
179
181
 
180
182
  // up, down, left, right
@@ -193,7 +195,7 @@ export const isValidSplit = (firstNumber: straightValue, secondNumber: straightV
193
195
  possibleSplitNumbers = [firstNumber - 3, firstNumber - 1, firstNumber + 3];
194
196
  }
195
197
 
196
- const filteredPossibleSplitNumbers = possibleSplitNumbers.filter((num) => isValidStraight(num)) as straightValue[];
198
+ const filteredPossibleSplitNumbers = possibleSplitNumbers.filter(num => isValidStraight(num)) as straightValue[];
197
199
 
198
200
  if (firstNumber !== 0 && secondNumber !== 0) {
199
201
  return filteredPossibleSplitNumbers.includes(secondNumber);
@@ -206,7 +208,12 @@ export const isValidSplit = (firstNumber: straightValue, secondNumber: straightV
206
208
  return false; // should never reach here
207
209
  };
208
210
 
209
- export const isValidCorner = (firstNumber: straightValue, secondNumber: straightValue, thirdNumber: straightValue, fourthNumber: straightValue): boolean => {
211
+ export const isValidCorner = (
212
+ firstNumber: straightValue,
213
+ secondNumber: straightValue,
214
+ thirdNumber: straightValue,
215
+ fourthNumber: straightValue,
216
+ ): boolean => {
210
217
  // all 4 numbers MUST be adjacent to every other number
211
218
  const numbersAdjacentToFirstNumber = cornerNumbers(firstNumber);
212
219
  const numbersAdjacentToSecondNumber = cornerNumbers(secondNumber);
@@ -416,8 +423,8 @@ export class Roulette {
416
423
  return resultNum;
417
424
  }
418
425
 
419
- static getPayout(inputs: RouletteInput, result: straightValue): BigNumber {
420
- if (!this.validateInputs(inputs)) {
426
+ static getPayout(inputs: RouletteInput, result: straightValue, skipValidation?: boolean): BigNumber {
427
+ if (!skipValidation && !this.validateInputs(inputs)) {
421
428
  throw new Error('Invalid inputs');
422
429
  }
423
430
 
@@ -491,9 +498,25 @@ export class Roulette {
491
498
  return totalPayout;
492
499
  }
493
500
 
501
+ static getMaxMultiplier(inputs: RouletteInput, betAmount: BigNumber): BigNumber {
502
+ const maxPotentialPayout = BigNumber.max(...STRAIGHT_VALUES.map(possibleResult => this.getPayout(inputs, possibleResult, true)));
503
+
504
+ return maxPotentialPayout.dividedBy(betAmount).decimalPlaces(4);
505
+ }
506
+
494
507
  static validateInputs(inputs: RouletteInput): boolean {
495
- const { straightValues, splitValues, streetValues, cornerValues, doubleStreetValues, parityValues, colorValues, columnValues, dozenValues, halfValues } =
496
- inputs;
508
+ const {
509
+ straightValues,
510
+ splitValues,
511
+ streetValues,
512
+ cornerValues,
513
+ doubleStreetValues,
514
+ parityValues,
515
+ colorValues,
516
+ columnValues,
517
+ dozenValues,
518
+ halfValues,
519
+ } = inputs;
497
520
  // user must bet on at least one thing
498
521
  if (
499
522
  straightValues.length === 0 &&
@@ -510,11 +533,11 @@ export class Roulette {
510
533
  return false;
511
534
  }
512
535
 
513
- const straightsValid = straightValues.every((input) => isValidStraight(input.straightNumber));
514
- const splitsValid = splitValues.every((input) => isValidSplit(input.firstNumber, input.secondNumber));
515
- const streetsValid = streetValues.every((input) => isValidStreet(input.street));
516
- const cornersValid = cornerValues.every((input) => isValidCorner(input.firstNumber, input.secondNumber, input.thirdNumber, input.fourthNumber));
517
- const doubleStreetsValid = doubleStreetValues.every((input) => isValidDoubleStreet(input.firstStreet, input.secondStreet));
536
+ const straightsValid = straightValues.every(input => isValidStraight(input.straightNumber));
537
+ const splitsValid = splitValues.every(input => isValidSplit(input.firstNumber, input.secondNumber));
538
+ const streetsValid = streetValues.every(input => isValidStreet(input.street));
539
+ const cornersValid = cornerValues.every(input => isValidCorner(input.firstNumber, input.secondNumber, input.thirdNumber, input.fourthNumber));
540
+ const doubleStreetsValid = doubleStreetValues.every(input => isValidDoubleStreet(input.firstStreet, input.secondStreet));
518
541
 
519
542
  return straightsValid && splitsValid && streetsValid && cornersValid && doubleStreetsValid;
520
543
  }
@@ -38,25 +38,28 @@ export const WHEEL_MULTIPLIERS: Record<WheelSegments, Record<WheelRiskLevel, num
38
38
  },
39
39
  [WheelSegments.FORTY]: {
40
40
  [WheelRiskLevel.LOW]: [
41
- 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2,
42
- 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
41
+ 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5,
42
+ 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
43
43
  ],
44
44
  [WheelRiskLevel.MEDIUM]: [
45
45
  2, 0, 1.5, 0, 3, 0, 2, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0, 2, 0, 1.5, 0, 1.6, 0, 1.5, 0, 3, 0, 2, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0, 2, 0, 1.5, 0,
46
46
  ],
47
- [WheelRiskLevel.HIGH]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39.6],
47
+ [WheelRiskLevel.HIGH]: [
48
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39.6,
49
+ ],
48
50
  },
49
51
  [WheelSegments.FIFTY]: {
50
52
  [WheelRiskLevel.LOW]: [
51
- 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2,
52
- 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
53
+ 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5,
54
+ 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0, 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
53
55
  ],
54
56
  [WheelRiskLevel.MEDIUM]: [
55
- 1.5, 0, 2, 0, 1.5, 0, 3, 0, 1.5, 0, 2, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0, 1.5, 0, 2, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0, 1.5, 0, 2, 0, 1.5, 0, 2, 0, 1.5, 0, 5, 0,
56
- 1.5, 0, 2, 0, 1.5, 0,
57
+ 1.5, 0, 2, 0, 1.5, 0, 3, 0, 1.5, 0, 2, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0, 1.5, 0, 2, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0, 1.5, 0, 2, 0, 1.5, 0, 2, 0, 1.5,
58
+ 0, 5, 0, 1.5, 0, 2, 0, 1.5, 0,
57
59
  ],
58
60
  [WheelRiskLevel.HIGH]: [
59
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49.5,
61
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62
+ 0, 49.5,
60
63
  ],
61
64
  },
62
65
  };
@@ -71,7 +74,10 @@ export const WHEEL_SEGMENTS_TO_NUMBER: Record<WheelSegments, number> = {
71
74
 
72
75
  export class Wheel {
73
76
  static getResult(hexStr: string, segments: WheelSegments, risk: WheelRiskLevel): { resultSegment: number; multiplier: BigNumber } {
74
- const resultSegment = this.getRandomNumberFromHexStr(hexStr).multipliedBy(WHEEL_SEGMENTS_TO_NUMBER[segments]).integerValue(BigNumber.ROUND_DOWN).toNumber();
77
+ const resultSegment = this.getRandomNumberFromHexStr(hexStr)
78
+ .multipliedBy(WHEEL_SEGMENTS_TO_NUMBER[segments])
79
+ .integerValue(BigNumber.ROUND_DOWN)
80
+ .toNumber();
75
81
  const multiplier = BigNumber(WHEEL_MULTIPLIERS[segments][risk][resultSegment]);
76
82
  return { resultSegment, multiplier };
77
83
  }
@@ -91,4 +97,9 @@ export class Wheel {
91
97
 
92
98
  return result;
93
99
  }
100
+
101
+ static getMaxMultiplier(segments: WheelSegments, risk: WheelRiskLevel): BigNumber {
102
+ const maxMultiplier = BigNumber.max(...WHEEL_MULTIPLIERS[segments][risk]);
103
+ return maxMultiplier;
104
+ }
94
105
  }
@@ -44,7 +44,7 @@ export const ADDRESS_LINK_PREFIXES_TESTNET: Record<Chain, string> = {
44
44
  [Chain.BINANCE_SMART_CHAIN]: 'https://testnet.bscscan.com/address/{address}',
45
45
  [Chain.TON]: 'https://testnet.tonviewer.com/{address}',
46
46
  [Chain.AVAXC]: 'https://testnet.snowtrace.io/address/{address}',
47
- [Chain.ARBITRUM]: 'https://sepolia.arbiscan.io/tx/{address}',
47
+ [Chain.ARBITRUM]: 'https://sepolia.arbiscan.io/address/{address}',
48
48
  [Chain.BASE]: 'https://sepolia.basescan.org/address/{address}',
49
49
  };
50
50
 
@@ -60,7 +60,7 @@ export const ADDRESS_LINK_PREFIXES_MAINNET: Record<Chain, string> = {
60
60
  [Chain.BINANCE_SMART_CHAIN]: 'https://bscscan.com/address/{address}',
61
61
  [Chain.TON]: 'https://tonviewer.com/{address}',
62
62
  [Chain.AVAXC]: 'https://snowtrace.io/address/{address}',
63
- [Chain.ARBITRUM]: 'https://arbiscan.io/tx/{address}',
63
+ [Chain.ARBITRUM]: 'https://arbiscan.io/address/{address}',
64
64
  [Chain.BASE]: 'https://basescan.org/address/{address}',
65
65
  };
66
66