taler-rust

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

dev.rs (4800B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 
     17 use anyhow::anyhow;
     18 use clap::ValueEnum;
     19 use jiff::Zoned;
     20 use taler_common::{
     21     config::Config,
     22     types::{amount::Amount, payto::PaytoImpl},
     23 };
     24 use tracing::info;
     25 
     26 use crate::{
     27     HuIban, HuPayto, TransferHuPayto,
     28     config::WorkerCfg,
     29     magnet_api::{
     30         client::AuthClient,
     31         types::{Direction, Order},
     32     },
     33     setup,
     34     worker::{Tx, extract_tx_info},
     35 };
     36 
     37 #[derive(Debug, Clone, PartialEq, Eq, ValueEnum)]
     38 pub enum DirArg {
     39     #[value(alias("in"))]
     40     Incoming,
     41     #[value(alias("out"))]
     42     Outgoing,
     43     Both,
     44 }
     45 
     46 #[derive(clap::Subcommand, Debug)]
     47 pub enum DevCmd {
     48     /// Print account info
     49     Accounts,
     50     Tx {
     51         account: HuIban,
     52         #[clap(long, short, value_enum, default_value_t = DirArg::Both)]
     53         direction: DirArg,
     54     },
     55     Transfer {
     56         #[clap(long)]
     57         debtor: HuPayto,
     58         #[clap(long)]
     59         creditor: TransferHuPayto,
     60         #[clap(long)]
     61         amount: Option<Amount>,
     62         #[clap(long)]
     63         subject: Option<String>,
     64     },
     65 }
     66 
     67 pub async fn dev(cfg: &Config, cmd: DevCmd) -> anyhow::Result<()> {
     68     let cfg = WorkerCfg::parse(cfg)?;
     69     let keys = setup::load(&cfg)?;
     70     let client = reqwest::Client::new();
     71     let client = AuthClient::new(&client, &cfg.api_url, &cfg.consumer).upgrade(&keys.access_token);
     72     match cmd {
     73         DevCmd::Accounts => {
     74             let res = client.list_accounts().await?;
     75             for partner in res.partners {
     76                 for account in partner.bank_accounts {
     77                     let payto = account.iban.as_full_payto(&partner.partner.name);
     78                     info!(target: "dev", "{} {} {}", account.code, account.currency.symbol, payto);
     79                 }
     80             }
     81         }
     82         DevCmd::Tx { account, direction } => {
     83             let dir = match direction {
     84                 DirArg::Incoming => Direction::Incoming,
     85                 DirArg::Outgoing => Direction::Outgoing,
     86                 DirArg::Both => Direction::Both,
     87             };
     88             // Register incoming
     89             let mut next = None;
     90             loop {
     91                 let page = client
     92                     .page_tx(
     93                         dir,
     94                         Order::Ascending,
     95                         100,
     96                         account.bban(),
     97                         &next,
     98                         next.is_none(),
     99                     )
    100                     .await?;
    101                 next = page.next;
    102                 for item in page.list {
    103                     let tx = extract_tx_info(item.tx);
    104                     match tx {
    105                         Tx::In(tx_in) => info!(target: "dev", "in  {tx_in}"),
    106                         Tx::Out(tx_out) => info!(target: "dev", "out {tx_out}"),
    107                     }
    108                 }
    109                 if next.is_none() {
    110                     break;
    111                 }
    112             }
    113         }
    114         DevCmd::Transfer {
    115             debtor,
    116             creditor,
    117             amount,
    118             subject,
    119         } => {
    120             let account = client.account(debtor.bban()).await?;
    121             let amount = creditor
    122                 .amount
    123                 .clone()
    124                 .or(amount)
    125                 .ok_or_else(|| anyhow!("Missing amount"))?;
    126             let subject = creditor
    127                 .subject
    128                 .clone()
    129                 .or(subject)
    130                 .ok_or_else(|| anyhow!("Missing subject"))?;
    131 
    132             let now = Zoned::now();
    133             let date = now.date();
    134 
    135             let init = client
    136                 .init_tx(
    137                     account.code,
    138                     amount.val as f64,
    139                     &subject,
    140                     &date,
    141                     &creditor.name,
    142                     creditor.bban(),
    143                 )
    144                 .await?;
    145             client
    146                 .submit_tx(
    147                     &keys.signing_key,
    148                     &account.number,
    149                     init.code,
    150                     init.amount,
    151                     &date,
    152                     creditor.bban(),
    153                 )
    154                 .await?;
    155         }
    156     }
    157     Ok(())
    158 }