libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit c4d6004bfa395140a228591147128405c0bdb557
parent 4944834d97639dabaca459edb092fe646775cf38
Author: Antoine A <>
Date:   Wed, 27 May 2026 09:55:32 +0200

nexus: finish serve cmd

Diffstat:
Mcrates/libeufin-bank/src/db.rs | 2+-
Mcrates/libeufin-bank/src/lib.rs | 1+
Mcrates/libeufin-nexus/src/config.rs | 13+++++++++++--
Mcrates/libeufin-nexus/src/lib.rs | 48+++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/crates/libeufin-bank/src/db.rs b/crates/libeufin-bank/src/db.rs @@ -492,7 +492,7 @@ mod test { ]; for (mode, rounding) in checks { for (rounded, amounts) in *rounding { - for amount in amounts.clone().into_iter() { + for amount in amounts.clone() { assert_eq!( decimal(format!("{rounded}")), apply( diff --git a/crates/libeufin-bank/src/lib.rs b/crates/libeufin-bank/src/lib.rs @@ -120,6 +120,7 @@ pub enum Cmd { #[arg(long)] current_token: Option<Base32<32>>, }, + /// Run libeufin-bank HTTP server Serve, /// Create an account, returning the payto://-URI associated with it CreateAccount { diff --git a/crates/libeufin-nexus/src/config.rs b/crates/libeufin-nexus/src/config.rs @@ -28,7 +28,10 @@ use libeufin_ebics::{ dialect::Dialect, }; use regex::Regex; -use taler_api::config::DbCfg; +use taler_api::{ + Serve, + config::{ApiCfg, DbCfg}, +}; use taler_common::{ config::{Config, ValueErr}, types::{ @@ -211,6 +214,9 @@ pub struct NexusCfg { pub fetch: OnceCell<NexusFetchCfg>, pub submit: OnceCell<NexusSubmitCfg>, pub ebics: OnceCell<NexusEbicsConfig>, + pub wire_cfg: Option<ApiCfg>, + pub revenue_cfg: Option<ApiCfg>, + pub serve_cfg: Serve, } impl NexusCfg { @@ -219,12 +225,15 @@ impl NexusCfg { Ok(Self { currency: s.currency("currency").require()?, account_type: s.parse("account type", "ACCOUNT_TYPE").require()?, - cfg, + wire_cfg: ApiCfg::parse(cfg.section("nexus-httpd-wire-gateway-api"))?, + revenue_cfg: ApiCfg::parse(cfg.section("nexus-httpd-revenue-api"))?, + serve_cfg: Serve::parse(cfg.section("nexus-httpd"))?, keys: OnceCell::new(), host: OnceCell::new(), fetch: OnceCell::new(), submit: OnceCell::new(), ebics: OnceCell::new(), + cfg, }) } diff --git a/crates/libeufin-nexus/src/lib.rs b/crates/libeufin-nexus/src/lib.rs @@ -17,7 +17,7 @@ * <http://www.gnu.org/licenses/> */ -use std::{str::FromStr, time::Duration}; +use std::{str::FromStr, sync::Arc, time::Duration}; use anyhow::{anyhow, bail}; use compact_str::{CompactString, CompactStringExt}; @@ -33,6 +33,7 @@ use libeufin_ebics::{ }; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use sqlx::PgPool; +use taler_api::api::TalerRouter; use taler_build::long_version; use taler_common::{ CommonArgs, @@ -44,9 +45,11 @@ use taler_common::{ utils::date_to_utc_ts, }, }; +use taler_test_utils::Router; use tracing::{debug, error, info, warn}; use crate::{ + api::NexusApi, config::{NexusCfg, NexusKeysCfg}, db::{ dbinit, @@ -137,7 +140,12 @@ pub enum Cmd { #[arg(long, requires = "transient")] checkpoint: bool, }, - Serve {}, + /// Run libeufin-nexus HTTP server + Serve { + /// Check whether an API is in use (if it's useful to start the HTTP server). Exit with 0 if at least one API is enabled, otherwise 1 + #[arg(long)] + check: bool, + }, /// Initiate an outgoing payment InitiatePayment { /// The amount to transfer, payto 'amount' parameter takes the precedence @@ -422,7 +430,41 @@ pub async fn run(cfg: Config, cmd: Cmd) -> anyhow::Result<()> { ) .await?; } - Cmd::Serve {} => todo!(), + Cmd::Serve { check } => { + let cfg = NexusCfg::parse(cfg)?; + if check { + let mut start_server = false; + for (name, api) in [ + ("Wire Gateway API", cfg.wire_cfg), + ("Revenue API", cfg.revenue_cfg), + ] { + if api.is_some() { + start_server = true; + info!("{name} is enabled: starting the server") + } + } + + if !start_server { + info!("All APIs are disabled: not starting the server"); + std::process::exit(1); + } + } else { + let pool = pool(&cfg.cfg).await?; + + let payto = cfg.ebics()?.account.as_uri(); + let api = Arc::new(NexusApi::start(pool, payto, cfg.currency).await); + let mut server = Router::new(); + if let Some(it) = cfg.wire_cfg { + server = server + .wire_gateway(api.clone(), it.auth.method()) + .prepared_transfer(api.clone()); + } + if let Some(it) = cfg.revenue_cfg { + server = server.revenue(api.clone(), it.auth.method()) + } + server.finalize().serve(&cfg.serve_cfg, None).await?; + } + } Cmd::Manual {} => todo!(), Cmd::List(cmd) => { let pool = pool(&cfg).await?;