librsigstopup
Safe, precise, and observable top‑up loan calculator – with JSON API, structured logging, and full traceability.
Table of Contents
- Installation
- Quick Start
- Library API
- Configuration
- Error Handling
- Logging & Tracing
- JSON API
- Development
- Contributing
- License
Installation
Add this to your Cargo.toml:
[]
= "0.1.0"
= { = "1", = ["rt"] } # if you need async runtime
Rust version requirement: 1.95 or later.
Quick Start
Basic synchronous usage (async wrapper)
use ;
async
Using JSON input
let json = r#"{
"pinjaman": 10000000,
"angsuran": 500000,
"sisa_tenor": 5,
"diskon": 200000,
"pajak": 150000
}"#;
let response = handler.calculate_from_json.await.unwrap;
println!;
Custom configuration
use ;
let config = builder
.insurance_percentage // 2% insurance
.admin_fee // Rp 100k admin fee
.enable_logging
.log_level
.build;
let handler = new.with_config;
Library API
TopUpHandler
Main entry point for calculations.
CalculatorConfig
Controls insurance percentage, admin fee, and logging behaviour.
| Field | Type | Default | Description |
|---|---|---|---|
insurance |
InsuranceConfig |
percentage: 0.015 (1.5%) |
Insurance rate applied to principal. |
tax |
TaxConfig |
admin_fee: 120_000 |
Fixed administrative fee. |
enable_logging |
bool |
true |
Enable structured JSON logs. |
log_level |
String |
"info" |
Log level filter. |
Use the builder to create a custom config:
let config = builder
.insurance_percentage // 2.5% (converted to 0.025 internally)
.admin_fee
.enable_logging
.log_level
.build;
LoanInput & LoanResult
LoanInput – required fields (all Decimal except sisa_tenor):
| Field | Type | Description |
|---|---|---|
pinjaman |
Decimal |
Loan principal (must be >0) |
angsuran |
Decimal |
Monthly installment (≥0) |
sisa_tenor |
u32 |
Remaining months |
diskon |
Decimal |
Discount (default 0) |
pajak |
Decimal |
Input tax (default 0) |
Builder with fallible build():
let input = builder
.pinjaman
.angsuran
.sisa_tenor
.build?; // returns Result<LoanInput, ValidationError>
LoanResult contains:
total_didapat– final amount the customer receives.calculations– intermediate values (sisa_pokok,asuransi,pajak, etc.)metadata– calculation time, formula, warnings.
CalculationError & ApiError
All errors implement std::error::Error and serialise to JSON.
Convert to user‑friendly ApiError:
let api_err: ApiError = calculation_error.into;
println!; // e.g. "VALIDATION_ERROR"
Configuration
Builder Pattern
All configuration uses a fluent builder with validation.
let config = builder
.insurance_percentage // 1.75%
.admin_fee // Rp 125,000
.enable_logging
.log_level
.build;
Missing fields fall back to defaults. Percentages are divided by 100 internally (2.5 → 0.025).
Serialization
CalculatorConfig implements Serialize/Deserialize – perfect for loading from file or environment.
let json = r#"{
"insurance": { "percentage": "0.02" },
"tax": { "base_amount": "0", "admin_fee": "150000" },
"enable_logging": false,
"log_level": "error"
}"#;
let config: CalculatorConfig = from_str.unwrap;
Error Handling
The library distinguishes between recoverable and unrecoverable errors.
match handler.calculate.await
All errors provide .to_json() for structured logging.
Logging & Tracing
The library uses the [tracing] crate with JSON formatting. Call init_logging() once at startup:
init_logging;
Every calculation emits structured events:
calculation_started– includesrequest_idand input.calculation_completed– includes total, duration, result.input_validated,calculate_insurance,calculate_tax, etc.
Set the log level via RUST_LOG environment variable:
RUST_LOG=debug
Disable logging via CalculatorConfig::builder().enable_logging(false).build().
JSON API
The library exposes a JSON‑friendly interface for easy integration.
Request (CalculationRequest):
Response (CalculationResponse):
Health check endpoint:
let health = handler.health_check.await;
// { "status": "healthy", "timestamp": "...", "version": "0.1.0", "config": {...} }
Development
Project Structure
.
├── Cargo.toml
├── src/
│ ├── core/ # Pure calculation logic
│ │ ├── loan.rs # LoanInput, builder, validation
│ │ ├── insurance_or_cp.rs
│ │ ├── tax.rs
│ │ ├── remaining_installments.rs
│ │ ├── total.rs
│ │ └── ...
│ ├── handler/ # API handlers, config, errors
│ │ ├── config.rs # CalculatorConfig & builder
│ │ ├── error.rs # Error types & conversions
│ │ ├── types.rs # Request/response DTOs
│ │ └── mod.rs # TopUpHandler implementation
│ └── lib.rs # Public exports & logging init
├── tests/ # Integration tests
├── benches/ # Benchmarks (Criterion)
└── examples/ # Usage examples
Features
json-logging(default) – JSON log output.verbose– Enable verbose tracing (more spans).android– Support Android logging viaandroid_logger.ffi– Build C‑compatible static library (seecrate-type = ["staticlib"]).
Contributing
- Fork the repository.
- Create a feature branch (
git checkout -b feat/your-feature). - Commit changes with clear messages.
- Run
cargo testandcargo clippyto ensure quality. - Push and open a Pull Request.
All contributions are welcome – bug reports, feature requests, documentation improvements.
License
MIT License – see LICENSE for details.
Acknowledgements
- Built on [
rust_decimal] for precise financial arithmetic. - Structured logging with [
tracing] andtracing-subscriber. - Inspired by real‑world top‑up loan workflows in Indonesian fintech.
Repository: https://github.com/neuxdotdev/librsigstopup
Crates.io: https://crates.io/crates/librsigstopup