taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

commit 040c91a04f9ebe328e9cdc1cae2832cb9417c53e
parent 3cbe83571b65c0a4f1ff69f83b68542e2b076c03
Author: Antoine A <>
Date:   Tue, 30 Dec 2025 13:07:00 +0100

cyclos: add dev cmd

Diffstat:
Ataler-cyclos/src/dev.rs | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtaler-cyclos/src/lib.rs | 1+
Mtaler-cyclos/src/main.rs | 7++++++-
Mtaler-magnet-bank/src/main.rs | 4++--
4 files changed, 120 insertions(+), 3 deletions(-)

diff --git a/taler-cyclos/src/dev.rs b/taler-cyclos/src/dev.rs @@ -0,0 +1,111 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ + +use clap::ValueEnum; +use taler_common::{config::Config, types::amount::Decimal}; +use tracing::info; + +use crate::{ + config::HarnessCfg, + cyclos_api::{api::CyclosAuth, client::Client, types::OrderBy}, + worker::{Tx, extract_tx_info}, +}; + +#[derive(Debug, Clone, PartialEq, Eq, ValueEnum)] +pub enum Account { + Wire, + Harness, +} + +#[derive(clap::Subcommand, Debug)] +pub enum DevCmd { + Tx { + account: Account, + }, + Transfer { + debtor: Account, + amount: Decimal, + subject: String, + }, +} + +pub async fn dev(cfg: &Config, cmd: DevCmd) -> anyhow::Result<()> { + let client = reqwest::Client::new(); + let cfg = HarnessCfg::parse(cfg)?; + let wire = Client { + client: &client, + api_url: &cfg.worker.host.api_url, + auth: &CyclosAuth::Basic { + username: cfg.worker.host.username, + password: cfg.worker.host.password, + }, + }; + let client = Client { + client: &client, + api_url: &cfg.worker.host.api_url, + auth: &CyclosAuth::Basic { + username: cfg.username, + password: cfg.password, + }, + }; + match cmd { + DevCmd::Tx { account } => { + let client = match account { + Account::Wire => wire, + Account::Harness => client, + }; + let mut page_idx = 0; + loop { + let page = client + .history(*cfg.worker.account_type_id, OrderBy::DateAsc, page_idx) + .await?; + for transfer in page.page { + let tx = extract_tx_info(transfer); + match tx { + Tx::In(tx_in) => info!(target: "dev", "in {tx_in}"), + Tx::Out(tx_out) => info!(target: "dev", "out {tx_out}"), + } + } + + if !page.has_next_page { + break; + } else { + page_idx += 1; + } + } + } + DevCmd::Transfer { + debtor, + amount, + subject, + } => { + let (debtor, creditor) = match debtor { + Account::Wire => (wire, client), + Account::Harness => (client, wire), + }; + let tx = debtor + .direct_payment( + *creditor.whoami().await?.id, + *cfg.worker.payment_type_id, + amount, + &subject, + ) + .await?; + println!("Sent tx {}", tx.id); + } + } + Ok(()) +} diff --git a/taler-cyclos/src/lib.rs b/taler-cyclos/src/lib.rs @@ -33,6 +33,7 @@ pub mod db; pub mod notification; pub mod setup; pub mod worker; +pub mod dev; pub async fn run_serve(cfg: &Config, pool: PgPool) -> anyhow::Result<()> { let cfg = ServeCfg::parse(cfg)?; diff --git a/taler-cyclos/src/main.rs b/taler-cyclos/src/main.rs @@ -23,6 +23,7 @@ use taler_cyclos::{ config::{ServeCfg, parse_account_payto}, constants::CONFIG_SOURCE, db::{dbinit, pool}, + dev::{self, DevCmd}, run_serve, setup, worker::run_worker, }; @@ -66,6 +67,9 @@ enum Command { }, #[command(subcommand)] TalerDeployment(TalerDeployment), + /// Hidden dev commands + #[command(subcommand, hide(true))] + Dev(DevCmd), #[command(subcommand)] Config(ConfigCmd), } @@ -104,7 +108,8 @@ async fn run(cmd: Command, cfg: &Config) -> anyhow::Result<()> { let client = reqwest::Client::new(); run_worker(cfg, &pool, &client, transient).await?; } - Command::Config(cfg_cmd) => cfg_cmd.run(cfg)?, + Command::Config(cmd) => cmd.run(cfg)?, + Command::Dev(cmd) => dev::dev(cfg, cmd).await?, Command::TalerDeployment(cmd) => match cmd { TalerDeployment::ExchangePayto => { let payto = parse_account_payto(cfg)?; diff --git a/taler-magnet-bank/src/main.rs b/taler-magnet-bank/src/main.rs @@ -108,8 +108,8 @@ async fn run(cmd: Command, cfg: &Config) -> anyhow::Result<()> { let client = reqwest::Client::new(); run_worker(cfg, &pool, &client, transient).await?; } - Command::Config(cfg_cmd) => cfg_cmd.run(cfg)?, - Command::Dev(dev_cmd) => dev::dev(cfg, dev_cmd).await?, + Command::Config(cmd) => cmd.run(cfg)?, + Command::Dev(cmd) => dev::dev(cfg, cmd).await?, Command::TalerDeployment(cmd) => match cmd { TalerDeployment::ExchangePayto => { let payto = parse_account_payto(cfg)?;