Kotlin Multiplatform Money Formatter

Most features within Cash App revolve around money. We must display money accurately and understandably so our customers can make informed financial decisions. But what it means to be accurate and understandable varies based on the context! Let’s take 1,000 US Dollars as an example:

That’s just a single currency in a single locale! Users can select a preferred denomination for Bitcoin, so one might see 0.0001 BTC while another sees 10,000 sats. A Spanish speaker in Spain might expect to see their balance formatted as 1.000,00 US$.

Payment Entry Pad Money Tab Bitcoin

So we set off to design a solution that would accomplish multiple goals:

That’s a tall order, but Kotlin Multiplatform gave us a viable path forward. With Kotlin Multiplatform, we could choose the best pieces of the ten existing formatters and provide a single, well-documented interface to everyone at Cash App!

Of course, there were some challenges along the way. One such challenge was localization. Our existing money formatters worked in only English, and localized number formatting is a challenging problem. Luckily, the platforms that we target have already solved it! Kotlin Multiplatform allowed us to split our formatting into two phases. First, we call platform-specific code for localized number formatting (e.g., NSNumberFormatter on iOS, the ICU library built into Android). Then we apply some Cash App specific adjustments in common Kotlin code. Leaning on native platform logic means we don’t have to become experts in each locale and keep the library lightweight.

Another challenge was handling scale and precision. 32-bit integers might not be large enough to display amounts in some currencies while floating point numbers can introduce subtle rounding errors for fractional amounts. It’s essential to get these things right when customers trust you with their money! We’re cautious about how we represent money across the rest of the Cash App ecosystem, and we needed to ensure we didn’t lose precision in the formatter. Kotlin Multiplatform allowed us to delegate to platform types like BigDecimal for Java or BigInt for JavaScript. The flexibility to mix common code with platform-specific code meant that we could have the best of both worlds and didn’t have to reinvent the wheel.

We’re currently working with Cash App developers to migrate to the new multiplatform money formatter and deprecate the legacy platform-specific implementations. We’ve been careful to test those migrations thoroughly, asserting that the output from the new library matches the old implementation and gating rollouts with feature flags. If you use Cash App for Android, you’ve already seen it in action!

If we want to add support for new currencies in the future, the process is as easy as adding another entry in the library, and it should work on all platforms.

We’ve thoroughly enjoyed developing with Kotlin Multiplatform and find immense value in its benefits! We highly recommend developers take a look if ensuring consistency across platforms is essential to them.

This post is part of Cash App’s Summer of Kotlin Multiplatform series.