Currency formatter

Format a decimal amount with currency selected by its ISO 4217 numeric code. Runs locally in your browser via WebAssembly.

CLI #

go install github.com/royalicing/qip@latest
printf %s '1234567.895' | qip run currency-format-en-us.wasm '?currency=840'
# $1,234,567.90

JavaScript #

const currencyFormatter = await WebAssembly.instantiateStreaming(
  fetch("/components/utf8/currency-format-en-us.wasm"),
);
const encoder = new TextEncoder(), decoder = new TextDecoder();

function formatCurrency(amount, currency) {
  const { memory, input_ptr, output_ptr, uniform_set_currency, render } = currencyFormatter.instance.exports;
  const input = encoder.encode(amount);
  uniform_set_currency(currency);
  new Uint8Array(memory.buffer, input_ptr(), input.length).set(input);
  const outputSize = render(input.length);
  return decoder.decode(new Uint8Array(memory.buffer, output_ptr(), outputSize));
}

console.log(formatCurrency("1234567.895", 840));
// $1,234,567.90

The amount is ASCII decimal text, not a JavaScript Number, so the component performs decimal rounding without an intervening binary floating-point conversion.

Download #

Details #

Each currency-format-<locale>.wasm keeps its locale and formatting data fixed while the integer uniform selects one of 155 current country currencies plus XDR. Metals, testing, no-currency, fund, accounting-unit, and indexed-unit codes remain outside their scope. Components range from 2.2 to 2.6 KiB and have no dependency on the browser, operating system locale, or host ICU version.

Amounts are ASCII decimals matching -?[0-9]+(\.[0-9]+)?, avoiding JavaScript floating-point conversion. Each module applies its locale's grouping and the currency's ISO minor units. Invalid input and unsupported codes trap. The page loads locale modules on demand.

Each locale has an independent compliance/currency-format-<locale>.comply.wasm executable specification. Every supported currency is dueled against JavaScript Intl.NumberFormat, including locale-specific grouping thresholds, separators, affix placement, Arabic-Indic digits, bidi markers, zero- and three-digit currencies, negative zero, rounding carries, and generated decimal inputs.

Convert alphabetic codes #

The companion component converts all 178 current ISO 4217 alphabetic codes to three-digit ASCII numeric codes. It keeps leading zeroes, which are significant in the standard representation:

echo -n AUD | qip run iso-4217-alpha-to-numeric.wasm
# 036

echo -n BHD | qip run iso-4217-alpha-to-numeric.wasm
# 048

Input is exactly three uppercase ASCII letters. Unknown, lowercase, or malformed codes trap. Its compliance component exhaustively declares all 178 mappings from the SIX Group ISO 4217 List One published 2026-01-01, plus rejection cases.

This component is intentionally narrower than Intl.NumberFormat. It does not accept exponent notation, NaN, infinity, signs other than a leading minus, configurable fraction digits, or runtime locale selection. Use host Intl when differing platform behavior is acceptable and you need its full range of options.