This crate provides a generic Currency and corresponding Amount type that can handle basic
arithmetic operations and formatting of arbitrary currencies and cryptocurrencies. Main
features include:
- Built-in support for all ISO-4217 currencies with proper precision and formatting
- Support for a variety of cryptocurrencies, also with proper underlying data types and
formatting. Accurate implementations for
ETH,BTC,DOT, and a variety of other cryptocurrencies are included. - The ability to specify whether an
Amountis forced to only make use of unchecked math, or not, at compile-time. Normally this is impossible to control since thecore:opsoperators are set up such that the checked operators require their unchecked counterparts to be implemented on the host type, however I have gone out of my way to make it possible to implement unchecked math only, and control it easily with aAmount<ETH, Checked>-style switch. This is extremely desirable for scenarios where panicking could cause a catastrophic issue, and the way it is set up, programmers are forced to consume theOptionreturned by the checked ops. - An easy-to-use macro,
define_currency!that can define new currencies on-the-fly. - A painstakingly wrapped version of
primitive_types::U256that implements many more usefulnum-traitsandnum-integertraits than what Parity includes with thenum-traitsfeature, and are often required when working with amounts of a currency. - All provided currencies implement most useful
num-traitsandnum-integertraits. - Thorough testing of all of the above.
#[test]
fn show_off_currency_math() {
use currency::*;
let apple_cost = amt!(USD, "$3.24");
let orange_cost = Amount::<USD>::from_raw(7_97);
assert!(apple_cost < orange_cost);
assert!(apple_cost + orange_cost > orange_cost);
assert_eq!(format!("{}", apple_cost * orange_cost), "$25.82");
assert_eq!(format!("{}", apple_cost * 3), "$9.72");
let mut total = amt!(DOT, "57622449841.0000000004 DOT");
total -= amt!(DOT, "1000.0 DOT");
total *= Amount::from_raw(2_0000000000u64.into());
assert_eq!(format!("{}", total), "115244897682.0000000008 DOT");
}
#[test]
fn show_off_checked_math() {
use currency::*;
use safety::*;
// When using currency amounts with `Safety = Checked`, the Amount struct has been specially set
// up so that only checked math will be allowed, and you can still use the normal
// operator-based syntax. Thus currency amounts like this should never panic and are
// suitable for use in critical/infallible environments.
let drink_cost = amt_checked!(USD, "$6.29");
let movie_cost = Amount::<USD, Checked>::from_raw(24_99);
let Some(outing_cost) = drink_cost + movie_cost else {
unimplemented!("compiler forces you to handle this!")
};
assert_eq!(format!("{}", outing_cost), "$31.28");
}- Additional macros for defining an
Amountvia a decimal literal - Currency conversion facilities, possibly including an online data source
- Add
Signednesssupport toAmount - Additional testing
- Support for negative amounts via an additional const generic defaulting to
Positive