prepared.rs (3082B)
1 /* 2 * This file is part of LibEuFin. 3 * Copyright (C) 2026 Taler Systems S.A. 4 5 * LibEuFin is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Affero General Public License as 7 * published by the Free Software Foundation; either version 3, or 8 * (at your option) any later version. 9 10 * LibEuFin is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General 13 * Public License for more details. 14 15 * You should have received a copy of the GNU Affero General Public 16 * License along with LibEuFin; see the file COPYING. If not, see 17 * <http://www.gnu.org/licenses/> 18 */ 19 20 //! Data access logic for prepared transfer specific logic 21 22 use jiff::Timestamp; 23 use sqlx::{PgPool, Row, postgres::PgRow}; 24 use taler_api::{ 25 db::{BindHelper, TypeHelper}, 26 serialized, 27 }; 28 use taler_common::{ 29 api::{EddsaPublicKey, EddsaSignature, prepared::TransferType}, 30 db::IncomingType, 31 types::amount::Amount, 32 }; 33 use uuid::Uuid; 34 35 use crate::payto::BankPayto; 36 37 /** Result of prepared transfer registration */ 38 pub enum RegistrationResult { 39 Success(Option<Uuid>), 40 UnknownCreditor, 41 NotExchange, 42 ReservePubReuse, 43 } 44 45 /** Register a prepared transfer */ 46 pub async fn register( 47 db: &PgPool, 48 creditor: &BankPayto, 49 ty: TransferType, 50 account_pub: &EddsaPublicKey, 51 auth_pub: &EddsaPublicKey, 52 auth_sig: &EddsaSignature, 53 recurrent: bool, 54 amount: &Amount, 55 timestamp: &Timestamp, 56 ) -> sqlx::Result<RegistrationResult> { 57 let ty: IncomingType = ty.into(); 58 serialized!( 59 sqlx::query( 60 " 61 SELECT out_unknown_creditor, out_not_exchange, out_reserve_pub_reuse, out_withdrawal_uuid 62 FROM register_prepared_transfers($1,$2::taler_incoming_type,$3,$4,$5,$6,$7,$8,$9) 63 " 64 ) 65 .bind(creditor.canonical()) 66 .bind(ty.as_ref()) 67 .bind(account_pub) 68 .bind(auth_pub) 69 .bind(auth_sig) 70 .bind(recurrent) 71 .bind(amount) 72 .bind_timestamp(timestamp) 73 .bind(format!("Taler prepared MAP:{auth_pub}")) 74 .try_map(|r: PgRow| { 75 Ok(if r.try_get_flag("out_unknown_creditor")? { 76 RegistrationResult::UnknownCreditor 77 } else if r.try_get_flag("out_not_exchange")? { 78 RegistrationResult::NotExchange 79 } else if r.try_get_flag("out_reserve_pub_reuse")? { 80 RegistrationResult::ReservePubReuse 81 } else { 82 RegistrationResult::Success(r.try_get("out_withdrawal_uuid")?) 83 }) 84 }) 85 .fetch_one(db) 86 ) 87 } 88 89 /** Register a prepared transfer */ 90 pub async fn unregister( 91 db: &PgPool, 92 auth_pub: &EddsaPublicKey, 93 timestamp: &Timestamp, 94 ) -> sqlx::Result<bool> { 95 serialized!( 96 sqlx::query_scalar("SELECT out_found FROM delete_prepared_transfers($1,$2)") 97 .bind(auth_pub) 98 .bind_timestamp(timestamp) 99 .fetch_one(db) 100 ) 101 }