40 lines
1.3 KiB
TypeScript
40 lines
1.3 KiB
TypeScript
import type { Money } from '../../../../common/money.types';
|
|
|
|
import { DECIMAL_RADIX, decimalFromString, formatDecimal } from '../../../../common/decimal';
|
|
|
|
export const ZERO_KOPECKS = 0n;
|
|
|
|
const RUB_DECIMAL_PLACES = 2;
|
|
|
|
const MIN_KOPECKS = -9_223_372_036_854_775_808n;
|
|
const MAX_KOPECKS = 9_223_372_036_854_775_807n;
|
|
|
|
export function parseRubMoney(money: Money, positive = false): bigint {
|
|
if (
|
|
money?.currency !== 'RUB' ||
|
|
typeof money.value !== 'string' ||
|
|
money.value !== money.value.trim()
|
|
) {
|
|
throw new TypeError('Expected RUB money with a decimal string');
|
|
}
|
|
const amount = decimalFromString(money.value);
|
|
if (amount.scale > RUB_DECIMAL_PLACES) {
|
|
throw new RangeError('RUB money supports at most two decimal places');
|
|
}
|
|
const kopecks = amount.value * DECIMAL_RADIX ** BigInt(RUB_DECIMAL_PLACES - amount.scale);
|
|
if (kopecks < MIN_KOPECKS || kopecks > MAX_KOPECKS) {
|
|
throw new RangeError('RUB money is outside the signed 64-bit range');
|
|
}
|
|
if (positive && kopecks <= ZERO_KOPECKS) {
|
|
throw new RangeError('Operation amount must be positive');
|
|
}
|
|
return kopecks;
|
|
}
|
|
|
|
export function rubMoney(kopecks: bigint): Money {
|
|
return {
|
|
currency: 'RUB',
|
|
value: formatDecimal({ value: kopecks, scale: RUB_DECIMAL_PLACES }),
|
|
};
|
|
}
|