npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

monie-utils

v1.1.1

Published

A comprehensive TypeScript library for money-related utilities including currency formatting, conversion, validation, and financial calculations

Readme

💰 Monie Utils

A comprehensive TypeScript library for money-related utilities including currency formatting, conversion, validation, and financial calculations.

npm version License: MIT TypeScript

✨ Features

  • 🎯 Type-safe - Built with TypeScript for excellent developer experience
  • 🌍 International - Support for multiple currencies and locales
  • 💱 Currency operations - Formatting, conversion, and validation
  • 🧮 Financial calculations - Interest, loans, investments, and more
  • 📊 Business utilities - Payment processing, subscriptions, analytics
  • 🚀 Lightweight - Tree-shakeable with zero dependencies
  • Well-tested - Comprehensive test coverage
  • 📚 Well-documented - Extensive documentation and examples

🚀 Installation

npm install monie-utils
yarn add monie-utils
pnpm add monie-utils

📖 Quick Start

import { 
  isValidAmount, 
  isValidCurrency, 
} from 'monie-utils';

// Validate amounts
console.log(isValidAmount(100.50)); // true
console.log(isValidAmount(NaN)); // false

// Validate currencies
console.log(isValidCurrency('USD')); // true
console.log(isValidCurrency('BTC')); // true
console.log(isValidCurrency('INVALID')); // false

📚 API Reference

Currency Formatting

formatCurrency(amount: number, currency: string, options?: FormatCurrencyOptions): FormattedCurrency

Formats a currency amount with locale-specific formatting.

formatCurrency(1234.56, 'USD')
// Returns: { formatted: '$1,234.56', amount: 1234.56, currency: 'USD', locale: 'en-US', isCompact: false }

formatCurrency(1234.56, 'EUR', { locale: 'de-DE', showCode: true })
// Returns: { formatted: '1.234,56 EUR', amount: 1234.56, currency: 'EUR', locale: 'de-DE', isCompact: false }

formatMoney(amount: number, currency: string, locale?: string): string

Simple string formatting for currency amounts.

formatMoney(1234.56, 'USD')
// Returns: '$1,234.56'

formatMoney(1234.56, 'EUR', 'de-DE')
// Returns: '1.234,56 €'

formatCents(cents: number, currency: string, options?: FormatCurrencyOptions): FormattedCurrency

Formats amounts from smallest currency unit (cents/satoshis).

formatCents(12345, 'USD')
// Returns: { formatted: '$123.45', amount: 123.45, currency: 'USD', locale: 'en-US', isCompact: false }

formatCents(10000000, 'BTC')
// Returns: { formatted: '₿0.10000000', amount: 0.1, currency: 'BTC', locale: 'en-US', isCompact: false }

formatCompactCurrency(amount: number, currency: string, options?: FormatCurrencyOptions): FormattedCurrency

Formats large amounts in compact notation (1M, 1B, etc.).

formatCompactCurrency(1500000, 'USD')
// Returns: { formatted: '$1.5M', amount: 1500000, currency: 'USD', locale: 'en-US', isCompact: true }

formatCompactCurrency(2500000000, 'USD')
// Returns: { formatted: '$2.5B', amount: 2500000000, currency: 'USD', locale: 'en-US', isCompact: true }

Percentage Formatting

formatPercentage(decimal: number, options?: PercentageOptions): string

Formats decimal values as percentages.

formatPercentage(0.1525)
// Returns: '15.25%'

formatPercentage(0.1525, { precision: 1, locale: 'de-DE' })
// Returns: '15,3 %'

Localization

formatCurrencyByLocale(amount: number, currency: string, locale: string): string

Formats currency with specific locale rules.

formatCurrencyByLocale(1234.56, 'USD', 'en-US')
// Returns: '$1,234.56'

formatCurrencyByLocale(1234.56, 'EUR', 'de-DE')
// Returns: '1.234,56 €'

getLocaleCurrencyInfo(locale: string): LocaleCurrencyInfo

Gets currency information for a locale.

getLocaleCurrencyInfo('en-US')
// Returns: { currency: 'USD', symbol: '$', name: 'US Dollar' }

getLocaleCurrencyInfo('de-DE')
// Returns: { currency: 'EUR', symbol: '€', name: 'Euro' }

formatWithGrouping(amount: number, locale?: string): string

Adds thousand separators based on locale.

formatWithGrouping(1234567.89)
// Returns: '1,234,567.89'

formatWithGrouping(1234567.89, 'de-DE')
// Returns: '1.234.567,89'

formatDecimalPlaces(amount: number, decimalPlaces: number): string

Formats number with specific decimal places.

formatDecimalPlaces(123.456789, 2)
// Returns: '123.46'

formatDecimalPlaces(123.1, 4)
// Returns: '123.1000'

Validation and Parsing

isValidAmount(amount: unknown): amount is number

Checks if a value is a valid money amount.

isValidAmount(100.50)
// Returns: true

isValidAmount(NaN)
// Returns: false

isValidCurrency(currencyCode): currencyCode is string

Validates currency codes against ISO 4217 and cryptocurrencies.

isValidCurrency('USD')
// Returns: true

isValidCurrency('BTC')
// Returns: true

isValidCurrency('INVALID')
// Returns: false

isPositiveAmount(amount: number): boolean

Checks if an amount is positive.

isPositiveAmount(100)
// Returns: true

isPositiveAmount(-50)
// Returns: false

isWithinRange(amount: number, min: number, max: number): boolean

Checks if an amount is within a specified range.

isWithinRange(50, 10, 100)
// Returns: true

isWithinRange(150, 10, 100)
// Returns: false

parseAmount(amountString: string): ParsedAmount

Parses string to number amount.

parseAmount('123.45')
// Returns: { amount: 123.45, isValid: true }

parseAmount('invalid')
// Returns: { amount: 0, isValid: false }

parseCurrencyString(currencyString: string): ParsedCurrency

Extracts amount and currency from formatted string.

parseCurrencyString('$123.45')
// Returns: { amount: 123.45, currency: 'USD', isValid: true }

parseCurrencyString('€1.234,56')
// Returns: { amount: 1234.56, currency: 'EUR', isValid: true }

normalizeAmount(amount: number, decimalPlaces?: number): number

Normalizes amount to standard format.

normalizeAmount(123.456789)
// Returns: 123.46

normalizeAmount(123.456789, 4)
// Returns: 123.4568

parseFormattedCurrency(formattedString: string, locale?: string): ParsedCurrency

Parses formatted currency string with locale awareness.

parseFormattedCurrency('$1,234.56', 'en-US')
// Returns: { amount: 1234.56, currency: 'USD', isValid: true }

parseFormattedCurrency('1.234,56 €', 'de-DE')
// Returns: { amount: 1234.56, currency: 'EUR', isValid: true }

Currency Conversion

convertCurrency(amount: number, fromCurrency: string, toCurrency: string, rate?: number): ConversionResult

Converts between currencies with exchange rates.

convertCurrency(100, 'USD', 'EUR', 0.85)
// Returns: { amount: 85, fromCurrency: 'USD', toCurrency: 'EUR', rate: 0.85 }

convertCurrency(100, 'USD', 'USD')
// Returns: { amount: 100, fromCurrency: 'USD', toCurrency: 'USD', rate: 1 }

convertWithFee(amount: number, rate: number, feePercentage: number): ConversionWithFee

Converts currency with transaction fee.

convertWithFee(100, 0.85, 2.5)
// Returns: { convertedAmount: 85, fee: 2.125, totalCost: 87.125, effectiveRate: 0.8713 }

bulkConvert(amounts: number[], fromCurrency: string, toCurrency: string, rate: number): BulkConversionResult

Converts multiple amounts at once.

bulkConvert([100, 200, 300], 'USD', 'EUR', 0.85)
// Returns: { convertedAmounts: [85, 170, 255], totalOriginal: 600, totalConverted: 510, rate: 0.85 }

Arithmetic Operations

roundMoney(amount: number, precision?: number): number

Rounds money to specified precision.

roundMoney(123.456)
// Returns: 123.46

roundMoney(123.456, 1)
// Returns: 123.5

addMoney(amount1: number, amount2: number, currency?: string): number

Adds two money amounts.

addMoney(100.25, 50.75)
// Returns: 151

addMoney(100.25, 50.75, 'USD')
// Returns: 151

subtractMoney(amount1: number, amount2: number, currency?: string): number

Subtracts money amounts.

subtractMoney(100.75, 25.25)
// Returns: 75.5

subtractMoney(100.75, 25.25, 'USD')
// Returns: 75.5

multiplyMoney(amount: number, multiplier: number): number

Multiplies money by a number.

multiplyMoney(50.25, 3)
// Returns: 150.75

multiplyMoney(100, 1.5)
// Returns: 150

divideMoney(amount: number, divisor: number): number

Divides money by a number.

divideMoney(150, 3)
// Returns: 50

divideMoney(100, 4)
// Returns: 25

calculateTip(amount: number, percentage: number): number

Calculates tip amount.

calculateTip(100, 15)
// Returns: 15

calculateTip(85.50, 20)
// Returns: 17.1

calculateTax(amount: number, taxRate: number): number

Calculates tax amount.

calculateTax(100, 8.5)
// Returns: 8.5

calculateTax(250, 10)
// Returns: 25

calculateDiscount(amount: number, discountRate: number): number

Calculates discount amount.

calculateDiscount(100, 10)
// Returns: 10

calculateDiscount(250, 15)
// Returns: 37.5

calculateSimpleInterest(principal: number, rate: number, time: number): number

Calculates simple interest.

calculateSimpleInterest(1000, 5, 2)
// Returns: 100

calculateSimpleInterest(5000, 3.5, 1.5)
// Returns: 262.5

calculateCompoundInterest(principal: number, rate: number, time: number, frequency?: number): CompoundInterestResult

Calculates compound interest.

calculateCompoundInterest(1000, 5, 2)
// Returns: { finalAmount: 1102.5, interestEarned: 102.5, effectiveRate: 5.125 }

calculateCompoundInterest(1000, 5, 2, 12)
// Returns: { finalAmount: 1104.89, interestEarned: 104.89, effectiveRate: 5.244 }

splitAmount(totalAmount: number, numberOfParts: number): number[]

Splits amount into equal parts.

splitAmount(100, 3)
// Returns: [33.33, 33.33, 33.34]

splitAmount(150, 4)
// Returns: [37.5, 37.5, 37.5, 37.5]

distributeProportionally(totalAmount: number, ratios: number[]): number[]

Distributes amount by ratios.

distributeProportionally(100, [1, 2, 3])
// Returns: [16.67, 33.33, 50]

distributeProportionally(500, [40, 30, 30])
// Returns: [200, 150, 150]

calculatePercentageOfTotal(amount: number, total: number): number

Calculates percentage share.

calculatePercentageOfTotal(25, 100)
// Returns: 25

calculatePercentageOfTotal(150, 500)
// Returns: 30

Loan and Credit Utilities

calculateMonthlyPayment(principal: number, rate: number, termMonths: number): number

Calculates monthly loan payment.

calculateMonthlyPayment(200000, 4.5, 360)
// Returns: 1013.37

calculateMonthlyPayment(50000, 6, 60)
// Returns: 966.64

calculateLoanBalance(principal: number, rate: number, termMonths: number, paymentsMade: number): number

Calculates remaining loan balance.

calculateLoanBalance(200000, 4.5, 360, 12)
// Returns: 197834.23

calculateLoanBalance(50000, 6, 60, 24)
// Returns: 28844.35

calculateTotalInterest(principal: number, rate: number, termMonths: number): number

Calculates total interest over loan term.

calculateTotalInterest(200000, 4.5, 360)
// Returns: 164813.42

calculateTotalInterest(50000, 6, 60)
// Returns: 7998.12

generateAmortizationSchedule(principal: number, rate: number, termMonths: number): AmortizationEntry[]

Generates complete amortization schedule.

generateAmortizationSchedule(100000, 5, 12)
// Returns: [
//   { month: 1, payment: 8560.75, principal: 8144.08, interest: 416.67, balance: 91855.92 },
//   { month: 2, payment: 8560.75, principal: 8178.02, interest: 382.73, balance: 83677.90 },
//   ...
// ]

calculateCreditUtilization(usedCredit: number, totalCredit: number): number

Calculates credit utilization ratio.

calculateCreditUtilization(2500, 10000)
// Returns: 25

calculateCreditUtilization(1200, 5000)
// Returns: 24

calculateMinimumPayment(balance: number, rate: number, minimumRate: number): number

Calculates minimum credit payment.

calculateMinimumPayment(5000, 18, 2)
// Returns: 100

calculateMinimumPayment(2500, 24, 3)
// Returns: 75

calculatePayoffTime(balance: number, payment: number, rate: number): PayoffResult

Calculates time to pay off debt.

calculatePayoffTime(5000, 200, 18)
// Returns: { months: 30, totalInterest: 983.45, totalPaid: 5983.45 }

calculatePayoffTime(10000, 300, 24)
// Returns: { months: 43, totalInterest: 2804.32, totalPaid: 12804.32 }

Investment and Returns

calculateROI(initialInvestment: number, finalValue: number): number

Calculates return on investment.

calculateROI(10000, 12000)
// Returns: 20

calculateROI(5000, 4500)
// Returns: -10

calculateAnnualizedReturn(initialValue: number, finalValue: number, years: number): number

Calculates annualized return.

calculateAnnualizedReturn(10000, 15000, 3)
// Returns: 14.47

calculateAnnualizedReturn(5000, 7500, 2)
// Returns: 22.47

calculateDividendYield(dividendPerShare: number, pricePerShare: number): number

Calculates dividend yield.

calculateDividendYield(2.50, 50)
// Returns: 5

calculateDividendYield(1.25, 75)
// Returns: 1.67

calculateFutureValue(presentValue: number, rate: number, periods: number): number

Calculates future value.

calculateFutureValue(10000, 7, 10)
// Returns: 19671.51

calculateFutureValue(5000, 5, 20)
// Returns: 13266.49

Subscription and Recurring Payments

calculateSubscriptionValue(monthlyAmount: number, months: number): number

Calculates total subscription cost.

calculateSubscriptionValue(29.99, 12)
// Returns: 359.88

calculateSubscriptionValue(99, 6)
// Returns: 594

compareSubscriptionPlans(plans: SubscriptionPlan[]): PlanComparison[]

Compares subscription plans.

compareSubscriptionPlans([
  { name: 'Basic', monthlyPrice: 10, features: [] },
  { name: 'Pro', monthlyPrice: 25, features: [] }
])
// Returns: [
//   { plan: 'Basic', monthlyPrice: 10, annualPrice: 120, savings: 0 },
//   { plan: 'Pro', monthlyPrice: 25, annualPrice: 300, savings: 0 }
// ]

calculateProrationAmount(amount: number, daysUsed: number, totalDays: number): number

Calculates prorated amount.

calculateProrationAmount(100, 15, 30)
// Returns: 50

calculateProrationAmount(299, 10, 31)
// Returns: 96.45

calculateUpgradeCredit(oldPlan: SubscriptionPlan, newPlan: SubscriptionPlan, daysRemaining: number): UpgradeCredit

Calculates upgrade credit.

calculateUpgradeCredit(
  { name: 'Basic', monthlyPrice: 10 },
  { name: 'Pro', monthlyPrice: 25 },
  15
)
// Returns: { credit: 5, additionalCost: 12.5, totalCost: 7.5 }

calculateAnnualEquivalent(amount: number, frequency: 'monthly' | 'weekly' | 'quarterly'): number

Converts to annual amount.

calculateAnnualEquivalent(100, 'monthly')
// Returns: 1200

calculateAnnualEquivalent(25, 'weekly')
// Returns: 1300

calculateNextPaymentDate(startDate: Date, frequency: 'monthly' | 'weekly' | 'quarterly'): Date

Calculates next payment date.

calculateNextPaymentDate(new Date('2024-01-15'), 'monthly')
// Returns: Date object for 2024-02-15

calculateNextPaymentDate(new Date('2024-01-15'), 'weekly')
// Returns: Date object for 2024-01-22

calculateTotalRecurringCost(amount: number, frequency: 'monthly' | 'weekly' | 'quarterly', duration: number): number

Calculates total recurring cost.

calculateTotalRecurringCost(50, 'monthly', 12)
// Returns: 600

calculateTotalRecurringCost(25, 'weekly', 52)
// Returns: 1300

Utility Functions

roundToNearestCent(amount: number): number

Rounds to nearest cent.

roundToNearestCent(123.456)
// Returns: 123.46

roundToNearestCent(99.994)
// Returns: 99.99

roundToBankersRounding(amount: number, decimalPlaces?: number): number

Applies banker's rounding (round half to even).

roundToBankersRounding(2.125, 2)
// Returns: 2.12

roundToBankersRounding(2.135, 2)
// Returns: 2.14

truncateToDecimalPlaces(amount: number, places: number): number

Truncates without rounding.

truncateToDecimalPlaces(123.789, 2)
// Returns: 123.78

truncateToDecimalPlaces(99.999, 1)
// Returns: 99.9

ceilToNearestCent(amount: number): number

Ceils to nearest cent.

ceilToNearestCent(123.451)
// Returns: 123.46

ceilToNearestCent(99.001)
// Returns: 99.01

formatThousands(number: number, options?: ThousandsOptions): string

Adds thousand separators.

formatThousands(1234567.89)
// Returns: '1,234,567.89'

formatThousands(1234567.89, { thousandsSeparator: '.', decimalSeparator: ',' })
// Returns: '1.234.567,89'

formatToHundreds(amount: number, options?: ThousandsOptions): string

Formats cents to dollars with separators.

formatToHundreds(123456)
// Returns: '1,234.56'

formatToHundreds(987654, { thousandsSeparator: ' ', decimalSeparator: ',' })
// Returns: '9 876,54'

removeFormattingFromNumber(formattedString: string): string

Removes formatting characters.

removeFormattingFromNumber('$1,234.56')
// Returns: '1234.56'

removeFormattingFromNumber('€ 1.234,56')
// Returns: '1234.56'

convertToWords(amount: number, options?: { currency?: string }): NumberToWordsResult

Converts number to words.

convertToWords(123.45)
// Returns: { words: 'one hundred twenty-three and forty-five cents' }

convertToWords(1500, { currency: 'USD' })
// Returns: { words: 'one thousand five hundred dollars', currency: 'USD' }

formatAccountNumber(accountNumber: string, options?: AccountNumberOptions): FormattedAccountResult

Formats account numbers with masking.

formatAccountNumber('1234567890')
// Returns: { formatted: '******7890', masked: true, groupSize: 4 }

formatAccountNumber('1234567890', { maskCharacter: 'X', showLast: 6 })
// Returns: { formatted: 'XXXX567890', masked: true, groupSize: 4 }

🧪 Development

Prerequisites

  • Node.js 18+
  • npm, yarn, or pnpm

Setup

# Clone the repository
git clone https://github.com/spiderocious/monie-utils.git
cd monie-utils

# Install dependencies
npm install

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Build the library
npm run build

# Lint and format
npm run lint
npm run format

Scripts

  • npm run dev - Start development server with Vite
  • npm run build - Build the library with tsup
  • npm test - Run tests with Jest
  • npm run test:watch - Run tests in watch mode
  • npm run test:coverage - Run tests with coverage report
  • npm run lint - Lint code with ESLint
  • npm run lint:fix - Fix linting issues
  • npm run format - Format code with Prettier
  • npm run type-check - Run TypeScript type checking

🙏 Acknowledgments

  • Inspired by financial libraries from Stripe, PayStack, Monnify, and other payment processors
  • Built with modern TypeScript and development tools
  • Thanks to all contributors and the open-source community

Made with ❤️ by Oluwaferanmi (https://github.com/spiderocious)