// From any currency, to any currency:
fx.convert(12.99, {from: "GBP", to: "HKD"});

// Chaining sugar:
fx(1000).from("USD").to("GBP");
fx(1000).to("AED");

// With simple settings and defaults, making this possible:
fx.convert(5318008);
fx(5318008).to("AED");

// Can also be used as a nodeJS or requireJS/AMD module
var fx = require("moneyjs");
require(["moneyjs"], function(fx) { /* ... */ });

// Read more below or jump to the downloads, demo playground or documentation
// by @josscrowcroft

 

Currency conversion should be easy.

I was growing tired of trying to adapt those 10-year-old "FREE Currency Converter JavaScripts!" into something workable for our enterprise app at demand analytics - so I wrote a simple library, with one function: to convert a value from any currency to any other currency.

Aside: exchange rate data should be free.

This tied in closely with the “They want how much per month for their exchange-rates API?!” conundrum, where all the (freely available) data is hidden behind a hefty paywall - so I figured I could take a shot at that, too.

The Open Source Exchange Rates API project is powered by a simple nodeJS scraper, the lovable (and deadly) Currency Bot, which collects all the exchange rates from the Google Calculator API (one by one) every hour, then pushes them in JSON format to a public GitHub repository for everybody to use as a de-facto API.

The rates are also available historically for any day since the project started, and could soon be extended to provide data going back several years.

In the documentation, there are examples showing how to integrate the API data (or any exchange-rate data) with the library, in only a few lines of code.

You only need the conversion rates relative to any single currency, in order to be able to convert values between any other two currencies; money.js does it all for you.

Downloads

NB: money.js is currently alpha, and hasn't had enough testing. Give it a week or two to hammer out any bugs, before using it in a production website/app.

»  money.js development version (4.3 kb)

»  money.min.js production/minified version (1.1 kb)

There are more download options available on the GitHub repository, at josscrowcroft/money.js.

Demo Playground

Oh hey! You can use this JavaScript Sandbox to play around with money.js and kick the tires a bit. It's running in a separate (sandboxed) scope, but you have access to jQuery, underscore, accounting.js and money.js. You can use :load script.js to load extra libraries, or try :help if stuck.

Exchange rates should be set up already (defaults = from: "USD", to: "GBP") but if not, try refreshing the page. There are also some sample commands to try out.

sandbox console loading...
Some sample commands to get you started:

Documentation

Basic Installation

You've probably figured this one out, but here's how to use money.js as a standalone library (for modules and script loaders, there are guides lower down.) Just download the minified or development version of money.js, and include it like this:

<script src="path/to/money.js"></script>

You'll need to do one more thing before you can use it, though, which is...

Setting up exchange rates with fx.rates

First and foremost, to convert currencies, you're going to need some exchange rates, and a base currency. (As long as you have exchange rates for every currency you need relative to one single other currency, money.js can convert between any two; see fx.convert for details on that.)

The library doesn't really care which format you use for the currency names, how accurate they are, or which currency is your base rate - all that matters is the object format, shown below.

Rates are stored in the fx.rates object, while the base currency is stored in fx.base. They look kinda like this:

fx.base = "USD";
fx.rates = {
	"EUR" : 0.74510096, // eg. 1 USD === 0.74510096 EUR
	"GBP" : 0.64771034,
	"HKD" : 7.78191949,
	"USD" : 1,          // always include the base rate (1:1)
	/* etc */
}

You can include as many or as few currencies as you need, and the rates can be approximate, historical or just plain wrong (though I wouldn't recommend it.)

But where do the exchange rates come from?

You can use the latest rates from the Open Source Exchange Rates API, which are delivered in JSON format, ready for use with money.js. Ideally, you could load them inline into the HTML (on the server) - but you can also easily load them in via AJAX, or a script loader. With jQuery, you could do this:

<script type="text/javascript"></script>
    // Load exchange rates data via the cross-domain/AJAX proxy:
    $.getJSON(
        'http://openexchangerates.org/latest.json',
        function(data) {
            // Check money.js has finished loading:
            if ( typeof fx !== "undefined" && fx.rates ) {
                fx.rates = data.rates;
                fx.base = data.base;
            } else {
                // If not, apply to fxSetup global:
                var fxSetup = {
                    rates : data.rates,
                    base : data.base
                }
            }
        }
    );
</script>

AJAX works great, but you'll need to wait until the GET request has completed before you can get converting, and if it fails, you should have a plan B.

A slightly better and more reliable way is to bootstrap the exchange rates inline into your HTML page, using CURL or some other library to grab the file, then printing them out in a script tag. Here's a PHP example:

<!-- assuming you've already loaded money.js, above -->
<script type="text/javascript">
	fx.rates = {<?php echo json_encode($rates); ?>};
	fx.base = "<?php echo $base ?>";
</script>

For a solid solution, Currency Bot recommends combining both approaches - inlining the approximate/cached exchange rates, then grabbing the most up-to-date rates via AJAX at load time, replacing the bootstrapped data once the request completes.

There are more examples and methods of grabbing the latest (and historical) data on the Open Source Exchange Rates project homepage.

Again, whichever API or data source you use, all you need to make certain of is that there is a base currency, and that the exchange rates are in the object format given above.

fx.settings and fxSetup

You can use fx.settings to set default from and to currencies, after the library has loaded. If you want or need to set these before the library has loaded, create a global object called fxSetup, with the same properties:

// Using `fx.settings` (must be after loading the library)
fx.settings = {
	from : "GBP",
	to : "AED"
};

// Using `fxSetup` (must be before loading the library; see note)
var fxSetup = {
	from : "GBP",
	to : "AED"
};

Note about using fxSetup: If using fxSetup, the variable needs to be available to the library (in scope) - so use window.fxSetup if needed. Also note that the fxSetup method won't work if using money.js as an AMD / CommonJS module, because it won't have access to outside variables (so use fx.settings for those).

Oh, and you can also use fxSetup to load in the exchange rates and base currency before loading the library, which would look something like this:

// Adding exchange rates and base currency to `fxSetup`:
var fxSetup = {
	from : "GBP",
	to : "AED",
	base : "USD",
	rates : {
		"AED" : 3.67290571
		/* etc. */
	}
};

fx.convert(val, [opts])

The basic function of the library - converts a value from one currency to another. Uses the default from and to currencies in fx.settings, or those given in opts:

// Using defaults:
fx.settings = { from: "USD", to: "GBP" };
fx.convert(1000); // 647.71034

// With options:
fx.convert(1000, {to: "HKD"}); // 7781.91949 (default `from` currency)
fx.convert(1000, {from: "GBP", to: "HKD"}); // 12014.50549

fx.convert can convert from any currency to any currency, provided they're both in the fx.rates object. For example, if all rates are relative to USD (1:1), and you have the rate for USD:GBP and USD:HKD, you can specify {from: "GBP", to: "HKD"} - money.js will figure out the rate between the two currencies.

Currency names

Currency names directly reference entries in the fx.rates object, so you're not limited to using the standard 3-letter currency codes. If for some reason your exchange rates API gives pounds (£) as "Great British Pounds Sterling", that's what you'd use instead of "GBP", naturally. Same goes for other currencies.

If you pass in a currency in from or to for which you don't have an exchange rate, money.js will throw an error to let you know that the rate wasn't found.

A little note about accuracy

It's a really good idea to inform your users that the exchange rates / currency conversion is for informational purposes only. Bear in mind that no exchange rates can be truly accurate, because everybody takes their cut when money changes currency and rates do tend to fluctuate. And you don't want to be dealing with customers who are angry because their bank charged them $1.40 more than your website quoted. Lecture over!

fx.noConflict() available in standalone mode (not AMD/CJS)

Let's face it, fx is a pretty common namespace (think 'animation'), so money.js stores a reference to the previous global value of fx, if any, in case you need to restore it.

If you're using another library that creates a global fx object or function, you can use fx.noConflict to restore its value and, at the same time, assign the money.js library object to another variable:

// Assign the money.js library to a global money object:
var money = fx.noConflict();

// `fx` is now back to whatever it was before money.js was loaded, and you can still use the library via the `money` reference, like so:
money.convert(5318008);
money.settings.from = "JPY";
money(5318008).to("HKD");

Chaining with fx(val)

money.js provides basic 'chaining' (i.e. connecting method calls together, with each acting on the value returned by the previous.)

This allows a more expressive, human-readable way of writing code, where the underlying functions are exactly the same. The methods are as follows:

fx() returns a wrapped fx object for chaining (doesn't do any converting)
fx(16288) // (fxWrapper)
.from() returns a wrapped fx object, with the value converted from base to from currency:
fx(16288).from("HKD") // (fxWrapper)
.to() takes a wrapped fx object and converts to target currency:
fx(16288).to("GBP"); // 10549.90608307 (uses default `from` currency)
fx(16288).from("AED").to("GBP"); // 2872.35962914
.convert() takes a wrapped fx object and performs fx.convert(val, [opts]) on it:
fx(16288).convert(); // uses default `from` / `to` currencies
fx(16288).convert({ from:"HKD", to:"GBP" }); // 1355.69458109

Usage with accounting.js

money.js works great with accounting.js - a library that provides reliable localisation and formatting of money and currency. Here are a few examples, just for kicks:

var value = accounting.unformat(someNumber); // clean up number (eg. user input)
var toCurrency = "GBP"; // or some user input
accounting.formatMoney( fx.convert(value, {from:"USD", to: toCurrency}), {
	symbol: toCurrency,
	format: "%v %s"
}); // eg. "53,180.08 GBP"

The reason this is a good idea is that, by design, money.js returns a floating point value with high precision, eg. 8 decimal places (depending on the precision of the relative exchange rates and input value), which is pretty useless if you're displaying prices of things, which generally have 0 or 2 decimal places. accounting.js takes care of all the formatting you'll need for displaying your ready-converted currencies.

You could use val.toFixed(2) of course, but we're all (mostly) aware of how quirky (read: ‘argh’) that can be:

// accounting.toFixed() is a replacement for (Number).toFixed():
(0.615).toFixed(2);           // "0.61" <== wtfjs??
accounting.toFixed(0.615, 2); // "0.62" <== that's better

Usage in nodeJS/npm (CommonJS)

money.js can easily be used inside nodeJS or any other CommonJS module loader:

var fx = require("/path/to/moneyjs");
// Now load in your exchange rates and create `fx.settings` if needed

Soon you'll be able to install it via node package mananger, with npm install moneyjs, but not yet.

Usage as a RequireJS/AMD module

money.js also exposes itself (ha ha) as an AMD module, for script loaders such as RequireJS. This assumes you've read up on AMD modules and understand the syntax:

// Usage as a dependency:
require(["path/to/money"], function(fx) {
	// Now you have a well-scoped `fx` object to use!
	fx.convert(5318008);
});

You'll need to set up money.js inside the callback function, with fx.rates, fx.base and (optionally) fx.settings - once those are set up, they'll also be set up anywhere else you use fx.

That just about sums it up

That's really all you need to remember - fx.rates and fx.base are important, and your basic function is fx.convert(val, [opts]), which can be written like this: fx(val).from("USD").to("GBP") or in several other ways (re-read the docs if unsure.)

Feedback / bugs:

If you have any feedback, any at all, tweet @josscrowcroft, or head over to the money.js github repository and create a new issue. I'm expecting a few bugs to crop up here and there, so you can help a tonne by reporting them and making suggestions!

Pull requests / contributions are similarly welcome. Get forkin'.