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 }), }; }