@moneypot/hub 1.9.0-dev.2 → 1.9.0-dev.4
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,9 @@
|
|
|
1
|
+
export declare function formatCurrency(amount: number, currency: {
|
|
2
|
+
displayUnitScale: number;
|
|
3
|
+
displayUnitName: string;
|
|
4
|
+
}, options?: {
|
|
5
|
+
excludeUnit?: boolean;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function pluralize(word: string, count: number, suffix?: string): string;
|
|
8
|
+
export declare function getDecimalPlaces(displayUnitScale: number): number;
|
|
9
|
+
export declare function truncateDecimalPrecision(value: number, decimals: number): number;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export function formatCurrency(amount, currency, options = {
|
|
2
|
+
excludeUnit: false,
|
|
3
|
+
}) {
|
|
4
|
+
const decimalPlaces = getDecimalPlaces(currency.displayUnitScale);
|
|
5
|
+
const scaledAmount = amount / (currency.displayUnitScale || 1);
|
|
6
|
+
const truncatedAmount = truncateDecimalPrecision(scaledAmount, decimalPlaces);
|
|
7
|
+
const formatter = new Intl.NumberFormat("en-US", {
|
|
8
|
+
minimumFractionDigits: decimalPlaces,
|
|
9
|
+
maximumFractionDigits: decimalPlaces,
|
|
10
|
+
useGrouping: true,
|
|
11
|
+
});
|
|
12
|
+
const formatted = formatter.format(truncatedAmount);
|
|
13
|
+
if (options.excludeUnit) {
|
|
14
|
+
return formatted;
|
|
15
|
+
}
|
|
16
|
+
return `${formatted} ${pluralize(currency.displayUnitName, truncatedAmount)}`;
|
|
17
|
+
}
|
|
18
|
+
export function pluralize(word, count, suffix = "s") {
|
|
19
|
+
return count === 1 ? word : word + suffix;
|
|
20
|
+
}
|
|
21
|
+
export function getDecimalPlaces(displayUnitScale) {
|
|
22
|
+
return displayUnitScale < 10 ? 0 : Math.log10(displayUnitScale);
|
|
23
|
+
}
|
|
24
|
+
export function truncateDecimalPrecision(value, decimals) {
|
|
25
|
+
if (decimals < 0) {
|
|
26
|
+
throw new Error("Decimals must be a non-negative integer");
|
|
27
|
+
}
|
|
28
|
+
if (!Number.isFinite(value)) {
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
const str = value.toString();
|
|
32
|
+
const dotIndex = str.indexOf(".");
|
|
33
|
+
if (dotIndex === -1) {
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
const truncatedStr = decimals === 0
|
|
37
|
+
? str.substring(0, dotIndex)
|
|
38
|
+
: str.substring(0, dotIndex + decimals + 1);
|
|
39
|
+
return parseFloat(truncatedStr);
|
|
40
|
+
}
|
|
@@ -8,6 +8,7 @@ import { dbInsertHubHash, dbLockHubHashChain, } from "../hash-chain/db-hash-chai
|
|
|
8
8
|
import { getIntermediateHash, getPreimageHash, } from "../hash-chain/get-hash.js";
|
|
9
9
|
import { makeFinalHash, pickRandomOutcome } from "../hash-chain/util.js";
|
|
10
10
|
import { logger } from "../logger.js";
|
|
11
|
+
import { formatCurrency } from "../format-currency.js";
|
|
11
12
|
const FLOAT_EPSILON = 1e-10;
|
|
12
13
|
function sum(ns) {
|
|
13
14
|
return ns.reduce((a, b) => a + b, 0);
|
|
@@ -154,7 +155,7 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
154
155
|
const dbCurrency = await superuserPool
|
|
155
156
|
.query({
|
|
156
157
|
text: `
|
|
157
|
-
SELECT key
|
|
158
|
+
SELECT key, display_unit_name, display_unit_scale
|
|
158
159
|
FROM hub.currency
|
|
159
160
|
WHERE key = $1
|
|
160
161
|
AND casino_id = $2
|
|
@@ -192,7 +193,7 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
192
193
|
const maxProfitMultiplier = Math.max(...input.outcomes.map((o) => o.profit));
|
|
193
194
|
const maxPayout = input.wager * maxProfitMultiplier;
|
|
194
195
|
if (maxPayout > dbHouseBankroll.amount) {
|
|
195
|
-
throw new GraphQLError(`House cannot cover potential payout (${maxPayout}). Bankroll: ${dbHouseBankroll.amount}`);
|
|
196
|
+
throw new GraphQLError(`House cannot cover potential payout (${maxPayout} units). Bankroll: ${dbHouseBankroll.amount} units`);
|
|
196
197
|
}
|
|
197
198
|
const riskLimitsResult = RiskLimitsSchema.safeParse(betConfig.riskPolicy
|
|
198
199
|
? betConfig.riskPolicy({
|
|
@@ -208,11 +209,23 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
|
|
|
208
209
|
const riskLimits = riskLimitsResult.data;
|
|
209
210
|
if (riskLimits.maxWager != null &&
|
|
210
211
|
input.wager > riskLimits.maxWager) {
|
|
211
|
-
throw new GraphQLError(`Wager exceeds limit (${riskLimits.maxWager
|
|
212
|
+
throw new GraphQLError(`Wager exceeds limit (${formatCurrency(riskLimits.maxWager, {
|
|
213
|
+
displayUnitName: dbCurrency.display_unit_name,
|
|
214
|
+
displayUnitScale: dbCurrency.display_unit_scale,
|
|
215
|
+
})}). Your wager: ${formatCurrency(input.wager, {
|
|
216
|
+
displayUnitName: dbCurrency.display_unit_name,
|
|
217
|
+
displayUnitScale: dbCurrency.display_unit_scale,
|
|
218
|
+
})}`);
|
|
212
219
|
}
|
|
213
220
|
if (riskLimits.maxPayout != null &&
|
|
214
221
|
maxPayout > riskLimits.maxPayout) {
|
|
215
|
-
throw new GraphQLError(`Payout exceeds limit (${riskLimits.maxPayout
|
|
222
|
+
throw new GraphQLError(`Payout exceeds limit (${formatCurrency(riskLimits.maxPayout, {
|
|
223
|
+
displayUnitName: dbCurrency.display_unit_name,
|
|
224
|
+
displayUnitScale: dbCurrency.display_unit_scale,
|
|
225
|
+
})}). Your payout: ${formatCurrency(maxPayout, {
|
|
226
|
+
displayUnitName: dbCurrency.display_unit_name,
|
|
227
|
+
displayUnitScale: dbCurrency.display_unit_scale,
|
|
228
|
+
})}`);
|
|
216
229
|
}
|
|
217
230
|
const dbHashChain = await dbLockHubHashChain(pgClient, {
|
|
218
231
|
userId: session.user_id,
|