Midas.Fintech
1.0.2
dotnet add package Midas.Fintech --version 1.0.2
NuGet\Install-Package Midas.Fintech -Version 1.0.2
<PackageReference Include="Midas.Fintech" Version="1.0.2" />
<PackageVersion Include="Midas.Fintech" Version="1.0.2" />
<PackageReference Include="Midas.Fintech" />
paket add Midas.Fintech --version 1.0.2
#r "nuget: Midas.Fintech, 1.0.2"
#:package Midas.Fintech@1.0.2
#addin nuget:?package=Midas.Fintech&version=1.0.2
#tool nuget:?package=Midas.Fintech&version=1.0.2
Midas.Fintech
Open-source fintech primitives for .NET — African payments edition. Built by Midas Path Software Solutions in partnership with Sikani Technologies Pty Ltd.
Why this exists
Processing payments across Ghana and West Africa involves a well-defined but tedious set of primitives: pesewa-accurate money arithmetic, PCI DSS-compliant card masking, Luhn validation, mobile-money network types, gateway amount formatting, and transaction state machines.
Midas.Fintech packages all of these into a single, zero-dependency .NET library — with an API
that deliberately mirrors the @txmo-dev/midas-fintech TypeScript package so full-stack teams
use the same mental model on both sides.
Powers
| Product | Role |
|---|---|
| Sikani SmartPOS (Sikani Technologies Pty Ltd) | Money, card, and transaction utilities in the backend API |
| Midas HMS (Midas Path Software Solutions) | Patient billing, insurance claim amounts |
Installation
dotnet add package Midas.Fintech
Targets net8.0, net9.0, and net10.0. Zero external dependencies.
API Reference
Money — Immutable money value object
All arithmetic operates in minor units (pesewas, cents, etc.) to avoid floating-point errors.
using Midas.Fintech;
var price = Money.Of(12.50m, CurrencyCode.GHS); // 1250 pesewas
var tax = Money.Of(0.50m, CurrencyCode.GHS);
var total = price + tax; // Money.Of(13.00, GHS)
total.Amount // 13.00m
total.MinorUnits // 1300
total.Format() // "₵ 13.00"
total.IsPositive // true
// Multiply / divide
var half = total / 2m; // ₵ 6.50
var fee = total * 0.015m; // ₵ 0.20 (rounded half-away-from-zero)
// Cross-currency guard
var usd = Money.Of(5.00m, CurrencyCode.USD);
total + usd; // throws InvalidOperationException: Currency mismatch
Currency — ISO 4217 metadata
Supported: GHS, USD, EUR, GBP, NGN, KES, ZAR
var info = Currency.Get(CurrencyCode.GHS);
info.Symbol // "₵"
info.Name // "Ghanaian Cedi"
info.DecimalPlaces // 2
Currency.TryParse("ghs", out var code); // true, code = CurrencyCode.GHS
CardUtilities — PCI DSS-compliant card helpers
using Midas.Fintech;
// Masking
CardUtilities.MaskPan("4111111111111111"); // "411111******1111"
CardUtilities.MaskPanShort("4111111111111111"); // "****1111"
// Luhn
CardUtilities.IsValidLuhn("4111111111111111"); // true
CardUtilities.IsValidLuhn("1234567890123456"); // false
// Brand detection
CardUtilities.DetectBrand("4111111111111111"); // Visa
CardUtilities.DetectBrand("5500000000000004"); // Mastercard
CardUtilities.DetectBrand("378282246310005"); // Amex
CardUtilities.DetectBrand("6391000000000000"); // GhIPSS
// Expiry
CardUtilities.IsValidExpiry(12, 2030); // true
CardUtilities.IsValidExpiry(1, 2020); // false
TransactionHelpers — Status machine helpers
using Midas.Fintech;
TransactionHelpers.IsTerminal(TransactionStatus.Completed); // true
TransactionHelpers.IsTerminal(TransactionStatus.Pending); // false
TransactionHelpers.CanReverse(TransactionStatus.Completed); // true
TransactionHelpers.IsPending(TransactionStatus.Processing); // true
// Unique reference generation
TransactionHelpers.GenerateRef(); // "TXN-M4BCDEF-XY7KP"
TransactionHelpers.GenerateRef("PAY"); // "PAY-X3YDGKH-MQ92R"
// Phone masking
TransactionHelpers.MaskPhoneNumber("0244567890"); // "024****890"
AmountUtilities — Gateway formatting
using Midas.Fintech;
AmountUtilities.ToMinorUnits(12.50m); // 1250
AmountUtilities.FromMinorUnits(1250); // 12.50m
AmountUtilities.FormatForGateway(1250); // "000000001250" ← Theteller/PaySwitch
AmountUtilities.IsValid(12.50m); // true
AmountUtilities.IsValid(-1m); // false
AmountUtilities.PercentageFee(100m, 1.5m); // 1.50m
Real-world payment flow
using Midas.Fintech;
// ── 1. Validate and mask card at point-of-capture ──────────────────────────
var rawPan = "4111111111111111";
if (!CardUtilities.IsValidLuhn(rawPan))
throw new InvalidOperationException("Invalid card number.");
var brand = CardUtilities.DetectBrand(rawPan); // CardBrand.Visa
var maskedPan = CardUtilities.MaskPan(rawPan); // "411111******1111"
var shortPan = CardUtilities.MaskPanShort(rawPan); // "****1111"
// → Store maskedPan only. Never persist rawPan.
// ── 2. Build the transaction amount ────────────────────────────────────────
var subtotal = Money.Of(49.99m, CurrencyCode.GHS);
var vatRate = 0.125m; // 12.5% VAT
var vat = subtotal * vatRate; // ₵ 6.25
var total = subtotal + vat; // ₵ 56.24
Console.WriteLine($"Total: {total.Format()}"); // "₵ 56.24"
Console.WriteLine($"Total (pesewas): {total.MinorUnits}"); // 5624
// ── 3. Format amount for the PaySwitch / Theteller gateway ─────────────────
var gatewayAmount = AmountUtilities.FormatForGateway(total.MinorUnits);
// → "000000005624"
// ── 4. Generate a cryptographically-safe transaction reference ─────────────
var txRef = TransactionHelpers.GenerateRef("TXN");
// → "TXN-M4BCDEF-XY7KP"
// ── 5. Submit to gateway ────────────────────────────────────────────────────
var payload = new
{
Amount = gatewayAmount, // "000000005624"
Reference = txRef, // "TXN-M4BCDEF-XY7KP"
CardNumber = maskedPan, // "411111******1111" (never raw)
Description = $"Payment · {shortPan} · {brand}",
};
// ── 6. Track status ─────────────────────────────────────────────────────────
// After receiving gateway callback:
var status = TransactionStatus.Completed;
Console.WriteLine(TransactionHelpers.IsTerminal(status)); // true
Console.WriteLine(TransactionHelpers.CanReverse(status)); // true
Test coverage
- 80 % coverage threshold enforced in CI.
- Tests live in
Midas.Packages.Tests/MidasFintech/. - Benchmarks live in
Midas.Packages.Benchmarks/FintechBenchmarks.cs.
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.