taler-rust

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

commit 124cee60a5900413da674278ab1668a66f1c9a7a
parent 03b336f51b2c04ae357f426b4b62ca7d8fcb56c8
Author: Antoine A <>
Date:   Tue, 31 Mar 2026 11:31:51 +0200

common: rename Taler Wire Transfer Gateway to Taler Prepared Transfer and improve testing

Diffstat:
Mcommon/taler-api/src/api.rs | 8++++----
Mcommon/taler-api/src/api/transfer.rs | 16++++++++--------
Mcommon/taler-api/src/constants.rs | 2+-
Mcommon/taler-api/src/db.rs | 14++++++++++++++
Mcommon/taler-api/tests/api.rs | 28++++++++++++++++++----------
Mcommon/taler-api/tests/common/mod.rs | 13+++++++++----
Mcommon/taler-api/tests/security.rs | 2+-
Mcommon/taler-common/src/api_transfer.rs | 16++++++++--------
Mcommon/taler-common/src/types/amount.rs | 4++++
Mcommon/taler-common/src/types/payto.rs | 8++++----
Mcommon/taler-test-utils/src/routine.rs | 107++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mtaler-cyclos/src/api.rs | 16++++++++--------
Mtaler-magnet-bank/src/api.rs | 16++++++++--------
13 files changed, 168 insertions(+), 82 deletions(-)

diff --git a/common/taler-api/src/api.rs b/common/taler-api/src/api.rs @@ -35,7 +35,7 @@ use wire::WireGateway; use crate::{ Listener, Serve, - api::transfer::WireTransferGateway, + api::transfer::PreparedTransfer, auth::{AuthMethod, AuthMiddlewareState}, error::{ApiResult, failure, failure_code}, }; @@ -80,7 +80,7 @@ impl<S: Send + Clone + Sync + 'static> RouterUtils for Router<S> { pub trait TalerRouter { fn wire_gateway<T: WireGateway>(self, api: Arc<T>, auth: AuthMethod) -> Self; - fn wire_transfer_gateway<T: WireTransferGateway>(self, api: Arc<T>) -> Self; + fn prepared_transfer<T: PreparedTransfer>(self, api: Arc<T>) -> Self; fn revenue<T: Revenue>(self, api: Arc<T>, auth: AuthMethod) -> Self; fn finalize(self) -> Self; fn serve( @@ -95,8 +95,8 @@ impl TalerRouter for Router { self.nest("/taler-wire-gateway", wire::router(api, auth)) } - fn wire_transfer_gateway<T: WireTransferGateway>(self, api: Arc<T>) -> Self { - self.nest("/taler-wire-transfer-gateway", transfer::router(api)) + fn prepared_transfer<T: PreparedTransfer>(self, api: Arc<T>) -> Self { + self.nest("/taler-prepared-transfer", transfer::router(api)) } fn revenue<T: Revenue>(self, api: Arc<T>, auth: AuthMethod) -> Self { diff --git a/common/taler-api/src/api/transfer.rs b/common/taler-api/src/api/transfer.rs @@ -26,14 +26,14 @@ use axum::{ use jiff::{SignedDuration, Timestamp}; use taler_common::{ api_transfer::{ - RegistrationRequest, RegistrationResponse, SubjectFormat, Unregistration, - WireTransferConfig, + PreparedTransferConfig, RegistrationRequest, RegistrationResponse, SubjectFormat, + Unregistration, }, error_code::ErrorCode, }; use crate::{ - constants::WIRE_GATEWAY_API_VERSION, + constants::PREPARED_TRANSFER_API_VERSION, crypto::check_eddsa_signature, error::{ApiResult, failure, failure_code}, json::Req, @@ -41,7 +41,7 @@ use crate::{ use super::TalerApi; -pub trait WireTransferGateway: TalerApi { +pub trait PreparedTransfer: TalerApi { fn supported_formats(&self) -> &[SubjectFormat]; fn registration( &self, @@ -53,7 +53,7 @@ pub trait WireTransferGateway: TalerApi { ) -> impl std::future::Future<Output = ApiResult<()>> + Send; } -pub fn router<I: WireTransferGateway>(state: Arc<I>) -> Router { +pub fn router<I: PreparedTransfer>(state: Arc<I>) -> Router { Router::new() .route( "/registration", @@ -96,9 +96,9 @@ pub fn router<I: WireTransferGateway>(state: Arc<I>) -> Router { .route( "/config", get(async |State(state): State<Arc<I>>| { - Json(WireTransferConfig { - name: "taler-wire-transfer-gateway", - version: WIRE_GATEWAY_API_VERSION, + Json(PreparedTransferConfig { + name: "taler-prepared-transfer", + version: PREPARED_TRANSFER_API_VERSION, currency: state.currency(), implementation: Some(state.implementation()), supported_formats: state.supported_formats().to_vec(), diff --git a/common/taler-api/src/constants.rs b/common/taler-api/src/constants.rs @@ -15,7 +15,7 @@ */ pub const WIRE_GATEWAY_API_VERSION: &str = "5:0:0"; -pub const WIRE_GATEWAY_TRANSFER_API_VERSION: &str = "1:0:0"; +pub const PREPARED_TRANSFER_API_VERSION: &str = "1:0:0"; pub const REVENUE_API_VERSION: &str = "1:0:0"; pub const MAX_PAGE_SIZE: i64 = 1024; pub const MAX_TIMEOUT_MS: u64 = 60 * 60 * 10; // 1H diff --git a/common/taler-api/src/db.rs b/common/taler-api/src/db.rs @@ -223,6 +223,11 @@ pub trait TypeHelper { index: I, currency: &Currency, ) -> sqlx::Result<Amount>; + fn try_get_opt_amount<I: sqlx::ColumnIndex<Self>>( + &self, + index: I, + currency: &Currency, + ) -> sqlx::Result<Option<Amount>>; /** Flag consider NULL and false to be the same */ fn try_get_flag<I: sqlx::ColumnIndex<Self>>(&self, index: I) -> sqlx::Result<bool>; @@ -271,6 +276,15 @@ impl TypeHelper for PgRow { Ok(Amount::new_decimal(currency, decimal)) } + fn try_get_opt_amount<I: sqlx::ColumnIndex<Self>>( + &self, + index: I, + currency: &Currency, + ) -> sqlx::Result<Option<Amount>> { + let decimal: Option<Decimal> = self.try_get(index)?; + Ok(decimal.map(|decimal| Amount::new_decimal(currency, decimal))) + } + fn try_get_flag<I: sqlx::ColumnIndex<Self>>(&self, index: I) -> sqlx::Result<bool> { let opt_bool: Option<bool> = self.try_get(index)?; Ok(opt_bool.unwrap_or(false)) diff --git a/common/taler-api/tests/api.rs b/common/taler-api/tests/api.rs @@ -14,6 +14,8 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ +use std::sync::LazyLock; + use axum::http::StatusCode; use common::setup; use jiff::Timestamp; @@ -22,11 +24,15 @@ use taler_api::db::TypeHelper as _; use taler_common::{ api_common::{EddsaPublicKey, HashCode, ShortHashCode}, api_revenue::RevenueConfig, - api_transfer::WireTransferConfig, + api_transfer::PreparedTransferConfig, api_wire::{OutgoingHistory, TransferResponse, TransferState, WireConfig}, db::IncomingType, error_code::ErrorCode, - types::{amount::amount, payto::payto, url}, + types::{ + amount::amount, + payto::{PaytoURI, payto}, + url, + }, }; use taler_test_utils::{ json, @@ -42,6 +48,8 @@ use crate::common::db::{AddIncomingResult, add_incoming}; mod common; +static PAYTO: LazyLock<PaytoURI> = LazyLock::new(|| payto("payto://test?receiver-name=Test")); + #[tokio::test] async fn errors() { let (server, _) = setup().await; @@ -63,9 +71,9 @@ async fn config() { .await .assert_ok_json::<WireConfig>(); server - .get("/taler-wire-transfer-gateway/config") + .get("/taler-prepared-transfer/config") .await - .assert_ok_json::<WireTransferConfig>(); + .assert_ok_json::<PreparedTransferConfig>(); server .get("/taler-revenue/config") .await @@ -75,7 +83,7 @@ async fn config() { #[tokio::test] async fn transfer() { let (server, _) = setup().await; - transfer_routine(&server, TransferState::success, &payto("payto://test")).await; + transfer_routine(&server, TransferState::success, &PAYTO).await; } #[tokio::test] @@ -92,7 +100,7 @@ async fn outgoing_history() { "amount": amount(format!("EUR:0.0{i}")), "exchange_base_url": url("http://exchange.taler"), "wtid": ShortHashCode::rand(), - "credit_account": url("payto://test"), + "credit_account": PAYTO.clone(), })) .await .assert_ok_json::<TransferResponse>(); @@ -104,13 +112,13 @@ async fn outgoing_history() { #[tokio::test] async fn admin_add_incoming() { let (server, _) = setup().await; - admin_add_incoming_routine(&server, &payto("payto://test"), true).await; + admin_add_incoming_routine(&server, &PAYTO, true).await; } #[tokio::test] async fn revenue() { let (server, _) = setup().await; - revenue_routine(&server, &payto("payto://test"), true).await; + revenue_routine(&server, &PAYTO, true).await; } #[tokio::test] @@ -159,7 +167,7 @@ async fn register_mapped(pool: &PgPool, account_pub: &EddsaPublicKey) { let reason = match add_incoming( pool, &amount("EUR:42"), - &payto("payto://test"), + &PAYTO, "lol", &Timestamp::now(), IncomingType::map, @@ -203,7 +211,7 @@ async fn registration() { let (server, pool) = setup().await; registration_routine( &server, - &payto("payto://test"), + &PAYTO, || check_in(&pool), |account_pub| { let account_pub = account_pub.clone(); diff --git a/common/taler-api/tests/common/mod.rs b/common/taler-api/tests/common/mod.rs @@ -21,7 +21,7 @@ use jiff::Timestamp; use sqlx::PgPool; use taler_api::{ api::{ - Router, TalerApi, TalerRouter as _, revenue::Revenue, transfer::WireTransferGateway, + Router, TalerApi, TalerRouter as _, revenue::Revenue, transfer::PreparedTransfer, wire::WireGateway, }, auth::AuthMethod, @@ -41,7 +41,11 @@ use taler_common::{ }, db::IncomingType, error_code::ErrorCode, - types::{amount::Currency, payto::payto, timestamp::TalerTimestamp}, + types::{ + amount::Currency, + payto::{FullQuery, payto}, + timestamp::TalerTimestamp, + }, }; use taler_test_utils::db::db_test_setup_manual; use tokio::sync::watch::Sender; @@ -68,6 +72,7 @@ impl TalerApi for TestApi { impl WireGateway for TestApi { async fn transfer(&self, req: TransferRequest) -> ApiResult<TransferResponse> { + req.credit_account.query::<FullQuery>()?; let result = db::transfer(&self.pool, &req).await?; match result { db::TransferResult::Success(transfer_response) => Ok(transfer_response), @@ -192,7 +197,7 @@ impl Revenue for TestApi { } } -impl WireTransferGateway for TestApi { +impl PreparedTransfer for TestApi { fn supported_formats(&self) -> &[SubjectFormat] { &[SubjectFormat::SIMPLE] } @@ -248,7 +253,7 @@ pub fn test_api(pool: PgPool, currency: Currency) -> Router { let state = Arc::new(wg); Router::new() .wire_gateway(state.clone(), AuthMethod::None) - .wire_transfer_gateway(state.clone()) + .prepared_transfer(state.clone()) .revenue(state, AuthMethod::None) } diff --git a/common/taler-api/tests/security.rs b/common/taler-api/tests/security.rs @@ -40,7 +40,7 @@ async fn body_parsing() { amount: Amount::zero(&eur), exchange_base_url: url("https://test.com"), wtid: Base32::rand(), - credit_account: payto("payto:://test"), + credit_account: payto("payto:://test?receiver-name=lol"), metadata: None, }; diff --git a/common/taler-common/src/api_transfer.rs b/common/taler-common/src/api_transfer.rs @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -//! Type for the Taler Wire Transfer Gateway HTTP API <https://docs.taler.net/core/api-bank-wire-transfer.html#taler-wire-transfer-gateway-http-api> +//! Type for the Taler Wire Transfer Gateway HTTP API <https://docs.taler.net/core/api-bank-transfer.html#taler-prepared-transfer-http-api> use compact_str::CompactString; use url::Url; @@ -28,7 +28,7 @@ use crate::{ use super::api_common::EddsaPublicKey; use serde::{Deserialize, Serialize}; -/// <https://docs.taler.net/core/api-bank-wire-transfer.html#tsref-type-SubjectFormat> +/// <https://docs.taler.net/core/api-bank-transfer.html#tsref-type-SubjectFormat> #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[allow(non_camel_case_types)] pub enum SubjectFormat { @@ -37,9 +37,9 @@ pub enum SubjectFormat { CH_QR_BILL, } -/// <https://docs.taler.net/core/api-bank-wire-transfer.html#tsref-type-WireTransferConfig> +/// <https://docs.taler.net/core/api-bank-transfer.html#tsref-type-PreparedTransferConfig> #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct WireTransferConfig<'a> { +pub struct PreparedTransferConfig<'a> { pub name: &'a str, pub version: &'a str, pub currency: &'a str, @@ -68,7 +68,7 @@ pub enum PublicKeyAlg { EdDSA, } -/// <https://docs.taler.net/core/api-bank-wire-transfer.html#tsref-type-RegistrationRequest> +/// <https://docs.taler.net/core/api-bank-transfer.html#tsref-type-RegistrationRequest> #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RegistrationRequest { pub credit_amount: Amount, @@ -80,7 +80,7 @@ pub struct RegistrationRequest { pub recurrent: bool, } -/// <https://docs.taler.net/core/api-bank-wire-transfer.html#tsref-type-TransferSubject> +/// <https://docs.taler.net/core/api-bank-transfer.html#tsref-type-TransferSubject> #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "type")] pub enum TransferSubject { @@ -98,14 +98,14 @@ pub enum TransferSubject { }, } -/// <https://docs.taler.net/core/api-bank-wire-transfer.html#tsref-type-RegistrationResponse> +/// <https://docs.taler.net/core/api-bank-transfer.html#tsref-type-RegistrationResponse> #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RegistrationResponse { pub subjects: Vec<TransferSubject>, pub expiration: TalerTimestamp, } -/// <https://docs.taler.net/core/api-bank-wire-transfer.html#tsref-type-Unregistration> +/// <https://docs.taler.net/core/api-bank-transfer.html#tsref-type-Unregistration> #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Unregistration { pub timestamp: CompactString, diff --git a/common/taler-common/src/types/amount.rs b/common/taler-common/src/types/amount.rs @@ -291,6 +291,10 @@ impl Amount { Self::new_decimal(currency, Decimal::zero()) } + pub fn is_zero(&self) -> bool { + self.decimal() == Decimal::zero() + } + pub const fn decimal(&self) -> Decimal { Decimal { val: self.val, diff --git a/common/taler-common/src/types/payto.rs b/common/taler-common/src/types/payto.rs @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2024-2025 Taler Systems SA + Copyright (C) 2024, 2025, 2026 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 @@ -80,7 +80,7 @@ impl PaytoURI { .with_query([("message", subject)]) } - fn query<Q: DeserializeOwned>(&self) -> Result<Q, PaytoErr> { + pub fn query<Q: DeserializeOwned>(&self) -> Result<Q, PaytoErr> { let query = self.0.query().unwrap_or_default().as_bytes(); let de = serde_urlencoded::Deserializer::new(url::form_urlencoded::parse(query)); serde_path_to_error::deserialize(de).map_err(PaytoErr::Query) @@ -204,14 +204,14 @@ impl PaytoImpl for IBAN { /// Full payto query #[derive(Debug, Clone, Deserialize)] -struct FullQuery { +pub struct FullQuery { #[serde(rename = "receiver-name")] receiver_name: CompactString, } /// Transfer payto query #[derive(Debug, Clone, Deserialize)] -struct TransferQuery { +pub struct TransferQuery { #[serde(rename = "receiver-name")] receiver_name: CompactString, amount: Option<Amount>, diff --git a/common/taler-test-utils/src/routine.rs b/common/taler-test-utils/src/routine.rs @@ -378,7 +378,7 @@ pub async fn transfer_routine( let default_amount = amount(format!("{currency}:42")); let request_uid = HashCode::rand(); let wtid = ShortHashCode::rand(); - let transfer_request = json!({ + let transfer_req = json!({ "request_uid": request_uid, "amount": default_amount, "exchange_base_url": "http://exchange.taler/", @@ -469,7 +469,7 @@ pub async fn transfer_routine( // Check request uid reuse server .post("/taler-wire-gateway/transfer") - .json(&json!(transfer_request + { + .json(&json!(transfer_req + { "wtid": ShortHashCode::rand() })) .await @@ -477,7 +477,7 @@ pub async fn transfer_routine( // Check wtid reuse server .post("/taler-wire-gateway/transfer") - .json(&json!(transfer_request + { + .json(&json!(transfer_req + { "request_uid": HashCode::rand(), })) .await @@ -486,17 +486,72 @@ pub async fn transfer_routine( // Check currency mismatch server .post("/taler-wire-gateway/transfer") - .json(&json!(transfer_request + { + .json(&json!(transfer_req + { "amount": "BAD:42" })) .await .assert_error(ErrorCode::GENERIC_CURRENCY_MISMATCH); + // Base Base32 + server + .post("/taler-wire-gateway/transfer") + .json(&json!(transfer_req + { + "wtid": "I love chocolate" + })) + .await + .assert_error(ErrorCode::GENERIC_JSON_INVALID); + server + .post("/taler-wire-gateway/transfer") + .json(&json!(transfer_req + { + "wtid": Base32::<31>::rand() + })) + .await + .assert_error(ErrorCode::GENERIC_JSON_INVALID); + server + .post("/taler-wire-gateway/transfer") + .json(&json!(transfer_req + { + "request_uid": "I love chocolate" + })) + .await + .assert_error(ErrorCode::GENERIC_JSON_INVALID); + server + .post("/taler-wire-gateway/transfer") + .json(&json!(transfer_req + { + "request_uid": Base32::<65>::rand() + })) + .await + .assert_error(ErrorCode::GENERIC_JSON_INVALID); + + // Missing receiver-name + server + .post("/taler-wire-gateway/transfer") + .json(&json!(transfer_req + { + "credit_account": credit_account.as_ref().as_str().split_once('?').unwrap().0 + })) + .await + .assert_error(ErrorCode::GENERIC_PAYTO_URI_MALFORMED); + + // TODO check bad payto + // TODO Bad base URL + /**for base_url in [ + "not-a-url", + "file://not.http.com/", + "no.transport.com/", + "https://not.a/base/url", + ] { + server + .post("/taler-wire-gateway/transfer") + .json(&json!(transfer_req + { + "exchange_base_url": base_url + })) + .await + .assert_error(ErrorCode::GENERIC_JSON_INVALID); + }**/ // Malformed metadata for metadata in ["bad_id", "bad id", "bad@id.com", &"A".repeat(41)] { server .post("/taler-wire-gateway/transfer") - .json(&json!(transfer_request + { + .json(&json!(transfer_req + { "metadata": metadata })) .await @@ -518,7 +573,7 @@ pub async fn transfer_routine( for _ in 0..4 { server .post("/taler-wire-gateway/transfer") - .json(&json!(transfer_request + { + .json(&json!(transfer_req + { "request_uid": HashCode::rand(), "wtid": ShortHashCode::rand(), })) @@ -720,7 +775,7 @@ pub async fn admin_add_incoming_routine(server: &Router, debit_acount: &PaytoURI // Get currency from config async fn get_transfer_currency(server: &Router) -> String { let config = server - .get("/taler-wire-transfer-gateway/config") + .get("/taler-prepared-transfer/config") .await .assert_ok_json::<serde_json::Value>(); let currency = config["currency"].as_str().unwrap(); @@ -778,7 +833,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O }); // Valid let res = server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&req) .await .assert_ok_json::<RegistrationResponse>(); @@ -787,7 +842,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O assert_eq!( res, server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&req) .await .assert_ok_json::<RegistrationResponse>() @@ -814,7 +869,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Bad signature server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "authorization_sig": eddsa_sign(&key_pair1, "lol".as_bytes()), })) @@ -823,7 +878,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Reserve pub reuse server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "account_pub": acc_pub1, "authorization_sig": eddsa_sign(&key_pair1, acc_pub1.as_ref()), @@ -834,7 +889,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O let key_pair = Ed25519KeyPair::generate().unwrap(); let auth_pub = EddsaPublicKey::try_from(key_pair.public_key().as_ref()).unwrap(); server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "account_pub": acc_pub1, "authorization_pub": auth_pub, @@ -846,7 +901,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Non recurrent accept one then bounce server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "account_pub": acc_pub1, "authorization_sig": eddsa_sign(&key_pair1, acc_pub1.as_ref()), @@ -861,7 +916,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Again without using mapping let acc_pub2 = EddsaPublicKey::rand(); server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "account_pub": acc_pub2, "authorization_sig": eddsa_sign(&key_pair1, acc_pub2.as_ref()), @@ -889,7 +944,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Recurrent accept one and delay others let acc_pub3 = EddsaPublicKey::rand(); server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "account_pub": acc_pub3, "authorization_sig": eddsa_sign(&key_pair1, acc_pub3.as_ref()), @@ -916,7 +971,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Complete pending on recurrent update let acc_pub4 = EddsaPublicKey::rand(); server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "type": "kyc", "account_pub": acc_pub4, @@ -927,7 +982,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O .assert_ok_json::<RegistrationResponse>(); check_history_in_trigger(server, async || { server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "account_pub": acc_pub4, "authorization_sig": eddsa_sign(&key_pair1, acc_pub4.as_ref()), @@ -978,7 +1033,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O let auth_pair = Ed25519KeyPair::generate().unwrap(); let auth_pub2 = EddsaPublicKey::try_from(auth_pair.public_key().as_ref()).unwrap(); server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "account_pub": auth_pub2, "authorization_pub": auth_pub2, @@ -1007,7 +1062,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O ]) .await; server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "type": "kyc", "account_pub": auth_pub2, @@ -1037,7 +1092,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Recurrent reserve simple subject let acc_pub5 = EddsaPublicKey::rand(); server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "type": "reserve", "account_pub": acc_pub5, @@ -1078,7 +1133,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Recurrent kyc simple subject server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "type": "kyc", "account_pub": acc_pub5, @@ -1089,7 +1144,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O .await .assert_ok_json::<RegistrationResponse>(); server - .post("/taler-wire-transfer-gateway/registration") + .post("/taler-prepared-transfer/registration") .json(&json!(req + { "type": "kyc", "account_pub": acc_pub5, @@ -1142,7 +1197,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Delete server - .delete("/taler-wire-transfer-gateway/registration") + .delete("/taler-prepared-transfer/registration") .json(&un_req) .await .assert_no_content(); @@ -1173,14 +1228,14 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Idempotent server - .delete("/taler-wire-transfer-gateway/registration") + .delete("/taler-prepared-transfer/registration") .json(&un_req) .await .assert_error(ErrorCode::BANK_TRANSACTION_NOT_FOUND); // Bad signature server - .delete("/taler-wire-transfer-gateway/registration") + .delete("/taler-prepared-transfer/registration") .json(&json!(un_req + { "authorization_sig": eddsa_sign(&auth_pair, "lol".as_bytes()), })) @@ -1190,7 +1245,7 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O // Old timestamp let now = (Timestamp::now() - SignedDuration::from_mins(10)).to_string(); server - .delete("/taler-wire-transfer-gateway/registration") + .delete("/taler-prepared-transfer/registration") .json(&json!({ "timestamp": now, "authorization_pub": auth_pub2, diff --git a/taler-cyclos/src/api.rs b/taler-cyclos/src/api.rs @@ -17,12 +17,12 @@ use compact_str::CompactString; use jiff::Timestamp; use taler_api::{ - api::{TalerApi, revenue::Revenue, transfer::WireTransferGateway, wire::WireGateway}, + api::{TalerApi, revenue::Revenue, transfer::PreparedTransfer, wire::WireGateway}, error::{ApiResult, failure, failure_code}, subject::{IncomingSubject, fmt_in_subject}, }; use taler_common::{ - api_common::{SafeU64, safe_u64}, + api_common::safe_u64, api_params::{History, Page}, api_revenue::RevenueIncomingHistory, api_transfer::{ @@ -117,7 +117,7 @@ impl WireGateway for CyclosApi { match result { db::TransferResult::Success { id, initiated_at } => Ok(TransferResponse { timestamp: initiated_at.into(), - row_id: SafeU64::try_from(id).unwrap(), + row_id: safe_u64(id), }), db::TransferResult::RequestUidReuse => { Err(failure_code(ErrorCode::BANK_TRANSFER_REQUEST_UID_REUSED)) @@ -256,7 +256,7 @@ impl Revenue for CyclosApi { } } -impl WireTransferGateway for CyclosApi { +impl PreparedTransfer for CyclosApi { fn supported_formats(&self) -> &[SubjectFormat] { &[SubjectFormat::SIMPLE] } @@ -314,7 +314,7 @@ mod test { use taler_common::{ api_common::EddsaPublicKey, api_revenue::RevenueConfig, - api_transfer::WireTransferConfig, + api_transfer::PreparedTransferConfig, api_wire::{OutgoingHistory, TransferState, WireConfig}, db::IncomingType, types::{ @@ -354,7 +354,7 @@ mod test { ); let server = Router::new() .wire_gateway(api.clone(), AuthMethod::None) - .wire_transfer_gateway(api.clone()) + .prepared_transfer(api.clone()) .revenue(api, AuthMethod::None) .finalize(); @@ -369,9 +369,9 @@ mod test { .await .assert_ok_json::<WireConfig>(); server - .get("/taler-wire-transfer-gateway/config") + .get("/taler-prepared-transfer/config") .await - .assert_ok_json::<WireTransferConfig>(); + .assert_ok_json::<PreparedTransferConfig>(); server .get("/taler-revenue/config") .await diff --git a/taler-magnet-bank/src/api.rs b/taler-magnet-bank/src/api.rs @@ -16,12 +16,12 @@ use jiff::Timestamp; use taler_api::{ - api::{TalerApi, revenue::Revenue, transfer::WireTransferGateway, wire::WireGateway}, + api::{TalerApi, revenue::Revenue, transfer::PreparedTransfer, wire::WireGateway}, error::{ApiResult, failure, failure_code}, subject::{IncomingSubject, fmt_in_subject}, }; use taler_common::{ - api_common::{SafeU64, safe_u64}, + api_common::safe_u64, api_params::{History, Page}, api_revenue::RevenueIncomingHistory, api_transfer::{ @@ -107,7 +107,7 @@ impl WireGateway for MagnetApi { match result { db::TransferResult::Success { id, initiated_at } => Ok(TransferResponse { timestamp: initiated_at.into(), - row_id: SafeU64::try_from(id).unwrap(), + row_id: safe_u64(id), }), db::TransferResult::RequestUidReuse => { Err(failure_code(ErrorCode::BANK_TRANSFER_REQUEST_UID_REUSED)) @@ -231,7 +231,7 @@ impl Revenue for MagnetApi { } } -impl WireTransferGateway for MagnetApi { +impl PreparedTransfer for MagnetApi { fn supported_formats(&self) -> &[SubjectFormat] { &[SubjectFormat::SIMPLE] } @@ -295,7 +295,7 @@ mod test { use taler_common::{ api_common::EddsaPublicKey, api_revenue::RevenueConfig, - api_transfer::WireTransferConfig, + api_transfer::PreparedTransferConfig, api_wire::{OutgoingHistory, TransferState, WireConfig}, db::IncomingType, types::{ @@ -323,7 +323,7 @@ mod test { let api = Arc::new(MagnetApi::start(pool.clone(), ACCOUNT.clone()).await); let server = Router::new() .wire_gateway(api.clone(), AuthMethod::None) - .wire_transfer_gateway(api.clone()) + .prepared_transfer(api.clone()) .revenue(api, AuthMethod::None) .finalize(); @@ -338,9 +338,9 @@ mod test { .await .assert_ok_json::<WireConfig>(); server - .get("/taler-wire-transfer-gateway/config") + .get("/taler-prepared-transfer/config") .await - .assert_ok_json::<WireTransferConfig>(); + .assert_ok_json::<PreparedTransferConfig>(); server .get("/taler-revenue/config") .await