shufflecom-calculations 6.7.1 → 6.7.2

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.
@@ -0,0 +1,11 @@
1
+ import BigNumber from 'bignumber.js';
2
+ type PurchaseBonusPercentType = 'bps' | 'raw';
3
+ export interface SweepStakePurchaseBonusAnchorPointSchema {
4
+ usdAmount: number;
5
+ percent: number;
6
+ }
7
+ export declare function derivePurchaseBonusMultiplier(percentType: PurchaseBonusPercentType, { usdReadable, anchorPoints }: {
8
+ usdReadable: BigNumber.Value;
9
+ anchorPoints: SweepStakePurchaseBonusAnchorPointSchema[];
10
+ }): BigNumber;
11
+ export {};
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.derivePurchaseBonusMultiplier = void 0;
7
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
8
+ const PERCENT_DIVISOR = {
9
+ bps: 10000,
10
+ raw: 100,
11
+ };
12
+ function derivePurchaseBonusMultiplier(percentType, { usdReadable, anchorPoints }) {
13
+ const deposit = new bignumber_js_1.default(usdReadable);
14
+ if (anchorPoints.length === 0 || !deposit.isFinite() || deposit.lte(0))
15
+ return new bignumber_js_1.default(0);
16
+ const divisor = PERCENT_DIVISOR[percentType];
17
+ const toMultiplier = (percent) => new bignumber_js_1.default(percent).div(divisor);
18
+ const sorted = [...anchorPoints].sort((a, b) => a.usdAmount - b.usdAmount);
19
+ const first = sorted[0];
20
+ const last = sorted[sorted.length - 1];
21
+ if (deposit.lt(first.usdAmount))
22
+ return new bignumber_js_1.default(0);
23
+ if (deposit.gte(last.usdAmount))
24
+ return toMultiplier(last.percent);
25
+ const hiIndex = sorted.findIndex(anchor => deposit.lt(anchor.usdAmount));
26
+ const lo = sorted[hiIndex - 1];
27
+ const hi = sorted[hiIndex];
28
+ const slope = new bignumber_js_1.default(hi.percent).minus(lo.percent).div(hi.usdAmount - lo.usdAmount);
29
+ const pct = deposit.minus(lo.usdAmount).times(slope).plus(lo.percent);
30
+ return toMultiplier(pct);
31
+ }
32
+ exports.derivePurchaseBonusMultiplier = derivePurchaseBonusMultiplier;
33
+ //# sourceMappingURL=derive-purchase-bonus-multiplier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-purchase-bonus-multiplier.js","sourceRoot":"","sources":["../../src/utils/derive-purchase-bonus-multiplier.ts"],"names":[],"mappings":";;;;;;AAAA,gEAAqC;AAIrC,MAAM,eAAe,GAA6C;IAChE,GAAG,EAAE,KAAM;IACX,GAAG,EAAE,GAAG;CACT,CAAC;AAgBF,SAAgB,6BAA6B,CAC3C,WAAqC,EACrC,EAAE,WAAW,EAAE,YAAY,EAA8F;IAEzH,MAAM,OAAO,GAAG,IAAI,sBAAS,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,sBAAS,CAAC,CAAC,CAAC,CAAC;IAEhG,MAAM,OAAO,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,CAAC,OAAwB,EAAE,EAAE,CAAC,IAAI,sBAAS,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEvF,MAAM,MAAM,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEvC,IAAI,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,sBAAS,CAAC,CAAC,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAGnE,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IACzE,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IAC/B,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAE3B,MAAM,KAAK,GAAG,IAAI,sBAAS,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC3F,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;IACtE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC;AAzBD,sEAyBC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shufflecom-calculations",
3
- "version": "6.7.1",
3
+ "version": "6.7.2",
4
4
  "description": "",
5
5
  "types": "lib/index.d.ts",
6
6
  "main": "lib/index.js",
@@ -19,5 +19,5 @@
19
19
  },
20
20
  "author": "",
21
21
  "license": "ISC",
22
- "gitHead": "95c91f287455e4c560530d39b5ba0ef101c6a798"
22
+ "gitHead": "3784c9535594ada13ca83abbb5b4fa8aeb7d821f"
23
23
  }
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export { ChatMessageType, ChatMessage } from './utils/chat-message.type';
8
8
  export { DatesCalculator } from './utils/dates-calculator';
9
9
  export { VipBonusIssuanceStatus } from './utils/vip-bonus.type';
10
10
  export { deriveBonusIssuances } from './utils/derive-vip-bonus';
11
+ export { derivePurchaseBonusMultiplier } from './utils/derive-purchase-bonus-multiplier';
11
12
  export { convertBs58ToUuid, convertUuidToBs58 } from './utils/uuid-converter';
12
13
  export { Dice, DiceDirection } from './games/dice';
13
14
  export { Roulette } from './games/roulette';
@@ -0,0 +1,50 @@
1
+ import BigNumber from 'bignumber.js';
2
+ import { derivePurchaseBonusMultiplier } from './derive-purchase-bonus-multiplier';
3
+
4
+ const bonus = (usd: number, multiplier: BigNumber) => new BigNumber(usd).times(multiplier).decimalPlaces(2, BigNumber.ROUND_DOWN).toString();
5
+
6
+ describe('derivePurchaseBonusMultiplier', () => {
7
+ const ascBps = [
8
+ { usdAmount: 50, percent: 4000 },
9
+ { usdAmount: 10, percent: 3000 },
10
+ ];
11
+ const ascRaw = [
12
+ { usdAmount: 10, percent: 30 },
13
+ { usdAmount: 50, percent: 40 },
14
+ ];
15
+ const descBps = [
16
+ { usdAmount: 10, percent: 4000 },
17
+ { usdAmount: 50, percent: 3000 },
18
+ ];
19
+
20
+ it('returns 0 with no anchors', () => {
21
+ expect(derivePurchaseBonusMultiplier('bps', { usdReadable: 15, anchorPoints: [] }).toNumber()).toBe(0);
22
+ });
23
+
24
+ it('returns 0 below the lowest anchor', () => {
25
+ expect(derivePurchaseBonusMultiplier('bps', { usdReadable: 5, anchorPoints: ascBps }).toNumber()).toBe(0);
26
+ });
27
+
28
+ it('returns the anchor percent on an exact anchor', () => {
29
+ expect(derivePurchaseBonusMultiplier('bps', { usdReadable: 10, anchorPoints: ascBps }).toNumber()).toBe(0.3);
30
+ expect(derivePurchaseBonusMultiplier('bps', { usdReadable: 50, anchorPoints: ascBps }).toNumber()).toBe(0.4);
31
+ });
32
+
33
+ it('caps at the highest anchor', () => {
34
+ expect(derivePurchaseBonusMultiplier('bps', { usdReadable: 500, anchorPoints: ascBps }).toNumber()).toBe(0.4);
35
+ });
36
+
37
+ it('interpolates increasing anchors (bps & raw give same result)', () => {
38
+ const m1 = derivePurchaseBonusMultiplier('bps', { usdReadable: 15, anchorPoints: ascBps });
39
+ const m2 = derivePurchaseBonusMultiplier('raw', { usdReadable: 15, anchorPoints: ascRaw });
40
+ expect(m1.toNumber()).toBe(0.3125);
41
+ expect(m2.toNumber()).toBe(0.3125);
42
+ expect(bonus(15, m1)).toBe('4.68');
43
+ });
44
+
45
+ it('interpolates decreasing anchors', () => {
46
+ const m = derivePurchaseBonusMultiplier('bps', { usdReadable: 15, anchorPoints: descBps });
47
+ expect(m.toNumber()).toBe(0.3875);
48
+ expect(bonus(15, m)).toBe('5.81');
49
+ });
50
+ });
@@ -0,0 +1,49 @@
1
+ import BigNumber from 'bignumber.js';
2
+
3
+ type PurchaseBonusPercentType = 'bps' | 'raw';
4
+
5
+ const PERCENT_DIVISOR: Record<PurchaseBonusPercentType, number> = {
6
+ bps: 10_000,
7
+ raw: 100,
8
+ };
9
+
10
+ export interface SweepStakePurchaseBonusAnchorPointSchema {
11
+ usdAmount: number;
12
+ percent: number;
13
+ }
14
+
15
+ /**
16
+ * Derives the purchase bonus multiplier for a deposit by linearly interpolating between anchor points.
17
+ *
18
+ * @param percentType - the unit that `anchorPoints[].percent` is stored in:
19
+ * - `'bps'`: basis points, where 10_000 = 100% (e.g. 250 = 2.5%). Stored/admin configured values use this.
20
+ * - `'raw'`: whole percent, where 100 = 100% (e.g. 2.5 = 2.5%).
21
+ *
22
+ * @returns the multiplier as a fraction (e.g. 0.025 for 2.5%), or 0 when the deposit is below the first anchor point.
23
+ */
24
+ export function derivePurchaseBonusMultiplier(
25
+ percentType: PurchaseBonusPercentType,
26
+ { usdReadable, anchorPoints }: { usdReadable: BigNumber.Value; anchorPoints: SweepStakePurchaseBonusAnchorPointSchema[] },
27
+ ): BigNumber {
28
+ const deposit = new BigNumber(usdReadable);
29
+ if (anchorPoints.length === 0 || !deposit.isFinite() || deposit.lte(0)) return new BigNumber(0);
30
+
31
+ const divisor = PERCENT_DIVISOR[percentType];
32
+ const toMultiplier = (percent: BigNumber.Value) => new BigNumber(percent).div(divisor);
33
+
34
+ const sorted = [...anchorPoints].sort((a, b) => a.usdAmount - b.usdAmount);
35
+ const first = sorted[0];
36
+ const last = sorted[sorted.length - 1];
37
+
38
+ if (deposit.lt(first.usdAmount)) return new BigNumber(0);
39
+ if (deposit.gte(last.usdAmount)) return toMultiplier(last.percent);
40
+
41
+ // first <= deposit < last, so hiIndex is always >= 1 and lo.usdAmount <= deposit < hi.usdAmount
42
+ const hiIndex = sorted.findIndex(anchor => deposit.lt(anchor.usdAmount));
43
+ const lo = sorted[hiIndex - 1];
44
+ const hi = sorted[hiIndex];
45
+
46
+ const slope = new BigNumber(hi.percent).minus(lo.percent).div(hi.usdAmount - lo.usdAmount);
47
+ const pct = deposit.minus(lo.usdAmount).times(slope).plus(lo.percent);
48
+ return toMultiplier(pct);
49
+ }