open-standards/openpay/crates/op-fx/src/lib.rs
Transaction Science 70ecd6caa0 Initial import — three open standards under one shelf
Transaction Science open standards monorepo. Each subdirectory is a
self-contained reference protocol with its own README and licence.

- openpay/    Apache-2.0  payment-acceptance stack (Rust, 26 crates)
- smart-byte/ CC-BY-4.0   content-addressed value carrier (spec)
- eoc/        CC-BY-4.0   energy-optimised compute (spec)

The wire format and the right to fork are public. The optional hosted
services are the offer; the protocols are not.
2026-05-23 07:58:09 -04:00

50 lines
2 KiB
Rust

//! # `op-fx` — Foreign-exchange primitives for `OpenPay`
//!
//! Integer-exact currency conversion with deterministic rounding,
//! pluggable quote sources, and TTL-based caching. The reference
//! stack ships no network clients — operators wire their preferred
//! FX feed (Wise, Open Exchange Rates, internal mid-market, bank
//! API) behind the [`QuoteProvider`] trait.
//!
//! ## Why integer math
//!
//! FX is one of the most-cited examples of "don't use floats for
//! money." A 0.0001 rounding error on `$10M` is $1000 the bank
//! cares about. We represent rates as
//! **parts per million** (`u64`): `1.000000 = 1_000_000`. Six
//! decimal places of precision is the FX industry standard for
//! spot rates; carrying more is meaningless given bid/ask spreads.
//!
//! Conversion math: `target_minor = source_minor * rate_ppm /
//! 1_000_000`, with a caller-chosen [`RoundingMode`] for the
//! remainder. No floats anywhere in the conversion pipeline.
//!
//! ## What the crate does NOT do
//!
//! - **No HTTP client.** [`QuoteProvider`] is the seam; the only
//! concrete impls shipped are [`StaticQuoteProvider`] (fixed
//! rate table, for tests + operator-locked rates) and
//! [`CachedQuoteProvider`] (TTL wrapper).
//! - **No spread / fee modeling.** Operators apply their own
//! spread by adjusting the rate they hand to the provider.
//! - **No triangulation.** A USD/JPY quote is direct; we don't
//! auto-route via USD/EUR + EUR/JPY. Operators who need cross-
//! rates assemble them themselves.
//! - **No hedging engine.** Quote validity windows are reported,
//! not enforced — callers check `valid_until_unix_secs`.
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_errors_doc)]
pub mod convert;
pub mod error;
pub mod provider;
pub mod quote;
pub use convert::{RoundingMode, convert};
pub use error::{Error, Result};
pub use provider::{CachedQuoteProvider, QuoteProvider, StaticQuoteProvider};
pub use quote::Quote;