From 0e46ea162a5176efaa00746218d575fb59bb5f81 Mon Sep 17 00:00:00 2001 From: swrup Date: Thu, 11 Dec 2025 05:41:32 +0100 Subject: [PATCH] wip wire-fee & global-fees --- src/api.ml | 13 +++---- src/handler.ml | 26 +++++++++++++ src/management.ml | 96 +++++++++++++++++++++++++++++++++++++++++++++++ src/mte.ml | 4 ++ src/pg.ml | 82 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 212 insertions(+), 9 deletions(-) diff --git a/src/api.ml b/src/api.ml index c3377f43..a47b08cc 100644 --- a/src/api.ml +++ b/src/api.ml @@ -572,8 +572,8 @@ module WireFeeSetupMessage = struct Signature using the exchange's offline key with purpose TALER_SIGNATURE_MASTER_WIRE_FEES *) master_sig_wire: MasterWireFee.t; - fee_start: Amount.t; - fee_end: Amount.t; + fee_start: Timestamp.t; + fee_end: Timestamp.t; closing_fee: Amount.t; wire_fee: Amount.t; } @@ -599,8 +599,8 @@ module WireFeeSetupMessage = struct map ~kind:"WireFeeSetupMessage" make |> mem "wire_method" Jsont.string ~enc:wire_method |> mem "master_sig_wire" MasterWireFee.jsont ~enc:master_sig_wire - |> mem "fee_start" Amount.jsont ~enc:fee_start - |> mem "fee_end" Amount.jsont ~enc:fee_end + |> mem "fee_start" Timestamp.jsont ~enc:fee_start + |> mem "fee_end" Timestamp.jsont ~enc:fee_end |> mem "closing_fee" Amount.jsont ~enc:closing_fee |> mem "wire_fee" Amount.jsont ~enc:wire_fee |> finish @@ -614,9 +614,8 @@ module GlobalFees = struct account_fee: Amount.t; purse_fee: Amount.t; history_expiration: RelativeTime.t; - purse_account_limit: int; + purse_account_limit: int32; purse_timeout: RelativeTime.t; - (* Signature of TALER_GlobalFeesPS. *) master_sig: GlobalFees.t; } @@ -651,7 +650,7 @@ module GlobalFees = struct |> mem "account_fee" Amount.jsont ~enc:account_fee |> mem "purse_fee" Amount.jsont ~enc:purse_fee |> mem "history_expiration" RelativeTime.jsont ~enc:history_expiration - |> mem "purse_account_limit" Jsont.int ~enc:purse_account_limit + |> mem "purse_account_limit" Jsont.int32 ~enc:purse_account_limit |> mem "purse_timeout" RelativeTime.jsont ~enc:purse_timeout |> mem "master_sig" GlobalFees.jsont ~enc:master_sig |> finish diff --git a/src/handler.ml b/src/handler.ml index 091a33fc..c18eac14 100644 --- a/src/handler.ml +++ b/src/handler.ml @@ -113,3 +113,29 @@ let management_auditors_disable req auditor_pub server _env = Ok "" in respond_with_res res req + +let management_wire_fee_jsont = WireFeeSetupMessage.jsont + +let management_wire_fee req server _env = + let open Management in + let db_conn = Vif.Server.device Devices.db_connection server in + let res = + let* v = Vif.Request.of_json req |> unwrap_err_msg in + let* () = verify_wire_fee_setup_sig v in + let* () = update_wire_fee_setup ~db_conn v in + Ok "" + in + respond_with_res res req + +let management_global_fees_jsont = GlobalFees.jsont + +let management_global_fees req server _env = + let open Management in + let db_conn = Vif.Server.device Devices.db_connection server in + let res = + let* v = Vif.Request.of_json req |> unwrap_err_msg in + let* () = verify_global_fees v in + let* () = update_global_fees ~db_conn v in + Ok "" + in + respond_with_res res req diff --git a/src/management.ml b/src/management.ml index e44c1943..3ae7c7d8 100644 --- a/src/management.ml +++ b/src/management.ml @@ -296,3 +296,99 @@ let auditor_disable ~db_conn auditor_pub |> unwrap_err_caqti in () + +let verify_wire_fee_setup_sig + WireFeeSetupMessage. + { + wire_method; + master_sig_wire; + fee_start; + fee_end; + closing_fee; + wire_fee; + } = + let open Bin_sig.MasterWireFee in + verify ~key:Config.Exchange.master_public_key master_sig_wire + { + h_wire_method= Bin_type.Hash_64_cstr.hash wire_method; + start_date= fee_start; + end_date= fee_end; + wire_fee; + closing_fee; + } + +let update_wire_fee_setup ~db_conn + WireFeeSetupMessage. + { + wire_method; + master_sig_wire; + fee_start; + fee_end; + closing_fee; + wire_fee; + } = + let* wire_fee_opt = + Pg.lookup_wire_fee_by_time db_conn ~wire_method ~start_date:fee_start + ~end_date:fee_end + |> unwrap_err_caqti + in + match wire_fee_opt with + | Some (_wire_fee, _closing_fee) -> Error "wire-fee already setup" + | None -> + let+ () = + Pg.insert_wire_fee db_conn ~wire_method ~start_date:fee_start + ~end_date:fee_end ~wire_fee ~closing_fee ~master_sig:master_sig_wire + |> unwrap_err_caqti + in + () + +let verify_global_fees + GlobalFees. + { + start_date; + end_date; + history_fee; + account_fee; + purse_fee; + history_expiration= _; + purse_account_limit; + purse_timeout= _; + master_sig; + } = + (* TODO time..... *) + let dummy_relative_time = None in + let dummy_amount = + Amount.make ~sign:None ~currency:"EUR" ~value:0_L ~fraction:0_l + |> Result.get_ok + in + (* TODO what is kyc_timeout, kyc_fee ? *) + let kyc_timeout = dummy_relative_time in + let kyc_fee = dummy_amount in + (* * *) + let open Bin_sig.GlobalFees in + verify ~key:Config.Exchange.master_public_key master_sig + { + start_date; + end_date; + purse_timeout= dummy_relative_time; + kyc_timeout; + history_expiration= dummy_relative_time; + history_fee; + kyc_fee; + account_fee; + purse_fee; + purse_account_limit; + } + +let update_global_fees ~db_conn v = + let* global_fees_opt = + let start_date = v.GlobalFees.start_date in + let end_date = v.GlobalFees.end_date in + Pg.lookup_global_fee_by_time db_conn ~start_date ~end_date + |> unwrap_err_caqti + in + match global_fees_opt with + | Some _ -> Error "global-fees already setup" + | None -> + let+ () = Pg.insert_global_fee db_conn v |> unwrap_err_caqti in + () diff --git a/src/mte.ml b/src/mte.ml index b330574c..b15f8636 100644 --- a/src/mte.ml +++ b/src/mte.ml @@ -49,6 +49,10 @@ let routes = (v "management" / "auditors" /% string `Path / "disable") management_auditors_disable_jsont --> management_auditors_disable; + post (v "management" / "wire-fee") management_wire_fee_jsont + --> management_wire_fee; + post (v "management" / "global-fees") management_global_fees_jsont + --> management_global_fees; ] let () = diff --git a/src/pg.ml b/src/pg.ml index a02efab9..aa913e5c 100644 --- a/src/pg.ml +++ b/src/pg.ml @@ -32,6 +32,9 @@ module Caqti_type = struct let eddsa_pub = EddsaPublicKey.caqti let eddsa_sig = EddsaSignature.caqti + (* todo: enum type for wire_method? *) + let wire_method = Caqti_type.string + include struct (* alias for hash *) @@ -183,8 +186,7 @@ let insert_signkey_revocation = let lookup_auditor_timestamp = let lookup_auditor_timestamp = Caqti_type.(eddsa_pub ->? time) - "lookup_auditor_timestamp SELECT last_change FROM auditors WHERE \ - auditor_pub=$1" + "SELECT last_change FROM auditors WHERE auditor_pub=$1" in fun (module Conn : CONN) auditor_pub -> Conn.find_opt lookup_auditor_timestamp auditor_pub @@ -218,3 +220,79 @@ let update_auditor = -> Conn.exec update_auditor (auditor_pub, auditor_url, auditor_name, enabled, change_date) + +let lookup_wire_fee_by_time = + let lookup_wire_fee_by_time = + Caqti_type.(t3 wire_method time time ->? t2 amount amount) + "SELECT (wire_fee).*, (closing_fee).* FROM wire_fee WHERE wire_method=$1 \ + AND end_date > $2 AND start_date < $3" + in + fun (module Conn : CONN) ~wire_method ~start_date ~end_date -> + Conn.find_opt lookup_wire_fee_by_time (wire_method, start_date, end_date) + +let insert_wire_fee = + let insert_wire_fee = + let master_sig = Bin_sig.MasterWireFee.caqti in + Caqti_type.(t6 wire_method time time amount amount master_sig ->. unit) + "INSERT INTO wire_fee (wire_method, start_date, end_date, wire_fee, \ + closing_fee, master_sig) VALUES ($1, $2, $3, ($4,$5), ($6,$7), $8)" + in + fun (module Conn : CONN) + ~wire_method + ~start_date + ~end_date + ~wire_fee + ~closing_fee + ~master_sig + -> + Conn.exec insert_wire_fee + (wire_method, start_date, end_date, wire_fee, closing_fee, master_sig) + +let lookup_global_fee_by_time = + let lookup_global_fee_by_time = + let global_fee = Caqti_type.(t6 amount amount amount time time int32) in + Caqti_type.(t2 time time ->? global_fee) + "SELECT (history_fee).*, (account_fee).*, (purse_fee).*, purse_timeout, \ + history_expiration, purse_account_limit FROM global_fee WHERE end_date \ + > $1 AND start_date < $2;" + in + fun (module Conn : CONN) ~start_date ~end_date -> + Conn.find_opt lookup_global_fee_by_time (start_date, end_date) + +let insert_global_fee = + let insert_global_fee = + let master_sig = Bin_sig.GlobalFees.caqti in + Caqti_type.( + t9 time time amount amount amount time time int32 master_sig ->. unit) + "INSERT INTO global_fee (start_date, end_date, history_fee, account_fee, \ + purse_fee, purse_timeout, history_expiration, purse_account_limit, \ + master_sig) VALUES ($1, $2, ($3,$4), ($5,$6), ($7,$8), $9, $10, $11, \ + $12)" + in + fun (module Conn : CONN) + Api.GlobalFees. + { + start_date; + end_date; + history_fee; + account_fee; + purse_fee; + history_expiration= _; + purse_account_limit; + purse_timeout= _; + master_sig; + } + -> + (* TODO time *) + let purse_timeout = None in + let history_expiration = None in + Conn.exec insert_global_fee + ( start_date, + end_date, + history_fee, + account_fee, + purse_fee, + purse_timeout, + history_expiration, + purse_account_limit, + master_sig )