commit c4d6004bfa395140a228591147128405c0bdb557
parent 4944834d97639dabaca459edb092fe646775cf38
Author: Antoine A <>
Date: Wed, 27 May 2026 09:55:32 +0200
nexus: finish serve cmd
Diffstat:
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?;