/* This file is part of TALER Copyright (C) 2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ /** * @file backenddb/pg_lookup_pending_deposits.c * @brief Implementation of the lookup_pending_deposits function for Postgres * @author Christian Grothoff */ #include "platform.h" #include #include #include #include "pg_lookup_pending_deposits.h" #include "pg_helper.h" /** * Context for lookup_pending_deposits(). */ struct LookupDepositsContext { /** * Function to call with the results. */ TALER_MERCHANTDB_PendingDepositsCallback cb; /** * Closure for @e cb. */ void *cb_cls; /** * Database context. */ struct PostgresClosure *pg; /** * Set to the return value on errors. */ enum GNUNET_DB_QueryStatus qs; }; /** * Function to be called with the results of a SELECT statement * that has returned @a num_results results about instances. * * @param cls of type `struct LookupDepositsContext *` * @param result the postgres result * @param num_results the number of results in @a result */ static void lookup_deposits_cb (void *cls, PGresult *result, unsigned int num_results) { struct LookupDepositsContext *ldc = cls; for (unsigned int i = 0; i < num_results; i++) { uint64_t deposit_serial; struct GNUNET_TIME_Absolute wire_deadline; struct GNUNET_TIME_Relative retry_backoff; struct TALER_PrivateContractHashP h_contract_terms; struct TALER_MerchantPrivateKeyP merchant_priv; char *instance_id; struct TALER_MerchantWireHashP h_wire; struct TALER_Amount amount_with_fee; struct TALER_Amount deposit_fee; struct TALER_CoinSpendPublicKeyP coin_pub; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_uint64 ("deposit_serial", &deposit_serial), GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", &h_contract_terms), GNUNET_PQ_result_spec_auto_from_type ("merchant_priv", &merchant_priv), GNUNET_PQ_result_spec_string ("merchant_id", &instance_id), GNUNET_PQ_result_spec_absolute_time ("wire_transfer_deadline", &wire_deadline), GNUNET_PQ_result_spec_relative_time ("retry_backoff", &retry_backoff), GNUNET_PQ_result_spec_auto_from_type ("h_wire", &h_wire), TALER_PQ_result_spec_amount_with_currency ("amount_with_fee", &amount_with_fee), TALER_PQ_result_spec_amount_with_currency ("deposit_fee", &deposit_fee), GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &coin_pub), GNUNET_PQ_result_spec_end }; if (GNUNET_OK != GNUNET_PQ_extract_result (result, rs, i)) { GNUNET_break (0); ldc->qs = GNUNET_DB_STATUS_HARD_ERROR; return; } ldc->cb (ldc->cb_cls, deposit_serial, wire_deadline, retry_backoff, &h_contract_terms, &merchant_priv, instance_id, &h_wire, &amount_with_fee, &deposit_fee, &coin_pub); GNUNET_PQ_cleanup_result (rs); } } enum GNUNET_DB_QueryStatus TMH_PG_lookup_pending_deposits ( void *cls, const char *exchange_url, uint64_t limit, bool allow_future, TALER_MERCHANTDB_PendingDepositsCallback cb, void *cb_cls) { struct PostgresClosure *pg = cls; struct LookupDepositsContext ldc = { .cb = cb, .cb_cls = cb_cls, .pg = pg }; struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (exchange_url), GNUNET_PQ_query_param_absolute_time (&now), GNUNET_PQ_query_param_uint64 (&limit), GNUNET_PQ_query_param_bool (allow_future), GNUNET_PQ_query_param_end }; enum GNUNET_DB_QueryStatus qs; check_connection (pg); PREPARE (pg, "lookup_pending_deposits", "SELECT" " md.deposit_serial" ",mct.h_contract_terms" ",mk.merchant_priv" ",mi.merchant_id" ",mdc.wire_transfer_deadline" ",ma.h_wire" ",md.amount_with_fee" ",md.deposit_fee" ",md.coin_pub" ",mdc.retry_backoff" " FROM merchant_deposit_confirmations mdc" " JOIN merchant_contract_terms mct" " USING (order_serial)" " JOIN merchant_accounts ma" " USING (account_serial)" " LEFT JOIN merchant_kyc kyc" " ON (ma.account_serial=kyc.account_serial)" " JOIN merchant_instances mi" " ON (mct.merchant_serial=mi.merchant_serial)" " JOIN merchant_keys mk" " ON (mi.merchant_serial=mk.merchant_serial)" " JOIN merchant_deposits md" " USING (deposit_confirmation_serial)" " WHERE mdc.wire_pending" " AND (mdc.exchange_url=$1)" " AND ($4 OR (mdc.wire_transfer_deadline < $2))" " AND ( (kyc.kyc_ok IS NULL) OR kyc.kyc_ok)" " AND ( (kyc.aml_decision IS NULL) OR (0=kyc.aml_decision) )" " ORDER BY mdc.wire_transfer_deadline ASC" " LIMIT $3"); qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, "lookup_pending_deposits", params, &lookup_deposits_cb, &ldc); if (0 > ldc.qs) return ldc.qs; return qs; }