minted_finance 1.0.2
minted_finance: ^1.0.2 copied to clipboard
Well-modelled Dart value types for finance: IBAN, BIC, ISIN and payment card numbers, with their real check digits. Part of the minted family.
minted_finance #
IBANs, BICs, ISINs and payment card numbers as well-modelled value types.
Part of the minted family: pure-Dart value types built on
parse, don't validate, so the parser is the only door in and anything that came through it is
well-formed by construction. Once you hold an Iban, it is a checksum-valid IBAN.
Install #
dart pub add minted_finance
minted comes with it, holding the vocabulary a parse hands back
(ParseOutcome, MintedFailure), and so does
minted_constraints for the primitives this package's
getters return. Nothing here drags in
another domain's engine.
What's in the box #
| Type | What it guarantees | Standard |
|---|---|---|
Iban |
structure, country length, and the mod-97 checksum | ISO 13616 |
Bic |
a SWIFT code: structure and a real country, folded to 11 | ISO 9362 |
PaymentCardNumber |
digits, the 8-to-19 window, and Luhn; masked when printed | ISO/IEC 7812 |
Isin |
a securities ID: charset, two-letter prefix, and Luhn over its letter expansion | ISO 6166 |
The check digits actually run: Iban computes mod-97 rather than matching a country's shape, and
PaymentCardNumber is a class rather than an extension type precisely so printing one can't leak
a PAN.
A quick taste #
final iban = Iban.tryParse('gb29 nwbk 6016 1331 9268 19')!;
iban.value; // 'GB29NWBK60161331926819' (compact)
iban.countryCode; // 'GB'
iban.checkDigits; // (first: Digit, second: Digit)
iban.formatted; // 'GB29 NWBK 6016 1331 9268 19' (grouped paper form)
// Bic: the 8- and 11-character spellings of one office are the same value, XXX being the office:
final bic = Bic.tryParse('deut de ff')!;
bic.value; // 'DEUTDEFFXXX'
bic.bic8; // 'DEUTDEFF' (the short form, rebuilt)
bic == Bic.tryParse('DEUTDEFFXXX'); // true
Bic.tryParse('DEUTZZFF'); // null: ZZ is not a country
// PaymentCardNumber masks itself, so a stray log line can't leak the number:
final card = PaymentCardNumber.tryParse('4111 1111 1111 1111')!;
'$card'; // 'PaymentCardNumber(••••1111)'
card.value; // '4111111111111111' (the only member that hands the number back)
card.cardScheme; // CardScheme.visa (read off the prefix, never validated)
// the scheme also reads from partial input, so a form can show the brand while you type:
PaymentCardNumber.cardSchemesOf('4'); // {CardScheme.visa}
PaymentCardNumber.tryParse('4111111111111112'); // null: fails the Luhn check
// Isin runs Luhn over the number with each letter expanded to two digits:
final isin = Isin.tryParse('au0000xvgza3')!;
isin.value; // 'AU0000XVGZA3'
isin.nsin; // '0000XVGZA'
Isin.tryParse('US0378331006'); // null: fails the Luhn check
The runnable version is the example.
One shape, every type #
Type.tryParse(input)hands back the value, ornullwhen the input isn't validType.parse(input)hands back aParseOutcome: the value, or a typed failure (IbanFailure,BicFailure,IsinFailure,PaymentCardNumberFailure) you canswitchon, or read as a form-field message via.reasonOrNull. No door throws- value equality, a canonical
.valuenormalised on parse, andfromComponentsfor parts you already hold
The minted README is the family guide: the package index,
handling failures, and the one caveat (never cast into a minted type).