zakat 0.3.0

A type-safe, comprehensive, and Fiqh-compliant Zakat calculation library. Supports Gold, Silver, Business, Agriculture, Livestock, Professional Income, and Modern Assets (Crypto/Stocks).
Documentation
███████╗ █████╗ ██╗  ██╗ █████╗ ████████╗
╚══███╔╝██╔══██╗██║ ██╔╝██╔══██╗╚══██╔══╝
  ███╔╝ ███████║█████╔╝ ███████║   ██║   
 ███╔╝  ██╔══██║██╔═██╗ ██╔══██║   ██║   
███████╗██║  ██║██║  ██╗██║  ██║   ██║   
╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝   

Zakat

Crates.io Docs.rs License: MIT

Rust library for Islamic Zakat calculation. Uses rust_decimal for precision.

Features

  • Gold, Silver, Business, Agriculture, Livestock, Mining & Rikaz
  • Stocks, Mutual Funds, Crypto (as liquid assets)
  • Professional Income (Gross/Net)
  • Zakat Fitrah
  • Configurable Nisab thresholds
  • Portfolio aggregation
  • Asset Labeling (e.g., "Main Store", "Crypto Wallet")
  • Input Sanitization (Rejects negative values)
  • Flexible Configuration (Env Vars, JSON, Fluent Builder)
  • Fiqh Compliance (Jewelry exemptions, Madhab-specific rules)
  • Detailed Reporting (Livestock in-kind details, metadata support)

Install

[dependencies]

zakat = "0.3.0"

rust_decimal = "1.39"

serde = { version = "1.0", features = ["derive"] }

serde_json = "1.0"

Usage

Business Zakat

Note: You can pass standard Rust types (i32, f64, &str) directly to all constructors. There is no need to manually convert to Decimal or use the dec!() macro anymore.

use zakat::{ZakatConfig, CalculateZakat, AssetBuilder};
use zakat::maal::business::{BusinessAssets, BusinessZakatCalculator};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ZakatConfig::new(65, 1)?; // gold $65/g, silver $1/g

    // Use Builder Pattern for clearer asset definition
    let assets = BusinessAssets::builder()
        .cash(50000)
        .inventory(20000)
        .receivables(5000)
        .liabilities(1000) // Deductible short-term debts
        .build()?;

    let calc = BusinessZakatCalculator::new(assets, &config)?
                     .with_label("Main Store")
                     .with_hawl(true);

    let result = calc.calculate_zakat()?;

    if result.is_payable {
        println!("Zakat for {}: ${}", result.label.unwrap_or_default(), result.zakat_due);
    }
    Ok(())
}

Portfolio

use zakat::{ZakatConfig, ZakatPortfolio, WealthType};
use zakat::maal::precious_metals::PreciousMetals;
use zakat::maal::investments::{InvestmentAssets, InvestmentType};
use zakat::maal::income::{IncomeZakatCalculator, IncomeCalculationMethod};
use rust_decimal_macros::dec;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ZakatConfig::new(65, 1)?;

    let portfolio = ZakatPortfolio::new()
        .add(IncomeZakatCalculator::new(
            5000, 0, IncomeCalculationMethod::Gross, &config
        )?.with_label("Monthly Salary"))
        .add(PreciousMetals::new(
            100, WealthType::Gold
        )?.with_label("Wife's Gold"))
        .add(InvestmentAssets::new(
            20000, InvestmentType::Crypto
        )?.with_debt(2000)?.with_label("Binance Portfolio"));

    let result = portfolio.calculate_total(&config)?;
    println!("Total Zakat Due: ${}", result.total_zakat_due);
    
    // Check for partial failures
    if !result.is_clean() {
        println!("Warning: {} items failed to calculate", result.failures().len());
    }

    // Iterate successful details
    for detail in result.successes() {
        if let Some(label) = &detail.label {
            println!(" - {}: ${}", label, detail.zakat_due);
        }
    }
    Ok(())
}

Configuration

use zakat::{ZakatConfig, Madhab, AssetBuilder};

// Load from Environment Variables (ZAKAT_GOLD_PRICE, etc.)
let config = ZakatConfig::from_env()?;

// Or load from JSON
let config = ZakatConfig::try_from_json("config.json")?;

// Or using Value Builder
let config = ZakatConfig::builder()
    .gold_price(100.0)
    .silver_price(1.0)
    .madhab(Madhab::Hanafi)
    .build()?;

Advanced Assets (Jewelry & Livestock)

use zakat::maal::precious_metals::{PreciousMetal, JewelryUsage};
use zakat::maal::livestock::{LivestockAssets, LivestockType, LivestockPrices};

// Personal Jewelry (Exempt in Shafi/Maliki, Payable in Hanafi)
let necklace = PreciousMetals::new(100.0, WealthType::Gold)?
    .with_usage(JewelryUsage::PersonalUse)
    .with_label("Wife's Wedding Necklace");

// Livestock Reporting
let prices = LivestockPrices::builder()
    .sheep_price(200)
    .cow_price(1500)
    .camel_price(3000)
    .build()?;
let camels = LivestockAssets::new(30, LivestockType::Camel, prices);

let result = camels.calculate_zakat(&config)?;

if result.is_payable {
    // Access detailed "in-kind" payment info
    use zakat::types::PaymentPayload;
    if let PaymentPayload::Livestock { description, .. } = result.payload {
        println!("Pay Due: {}", description);
        // Output: "Pay Due: 1 Bint Makhad"
    }
}

Custom Nisab

use zakat::ZakatConfig;

let config = ZakatConfig::new(65.0, 1.0)?
    .with_gold_nisab(87)
    .with_agriculture_nisab(700);

Modules

Module Nisab
maal::precious_metals 85g Gold / 595g Silver
maal::business 85g Gold
maal::income 85g Gold
maal::investments 85g Gold
maal::agriculture 653 kg
maal::livestock Count-based
maal::mining Rikaz: None / Mines: 85g Gold
fitrah N/A

Contributing

  1. Add tests
  2. Use rust_decimal
  3. Run cargo test

Support

GitHub Sponsors Ko-fi Patreon PayPal Saweria

"Those who spend their wealth in the cause of Allah..."Al-Baqarah 2:262

License

MIT