open Parse_config let config_filename = "mte.conf" (* TODO config read Fpath.t *) let config_data = match Assets_crunch.read config_filename with | None -> fail "static file not found: `%s`" config_filename | Some data -> let v = Config_section.parse data in v module Exchange = struct let get_opt field = get_opt config_data ~section:"exchange" ~field let get field = get config_data ~section:"exchange" ~field (* - *) let currency = (* todo: constraint on currency string *) get "currency" let currency_round_unit = get "currency_round_unit" |> amount let db = get "db" |> const_value "postgres" let attribute_encryption_key = get "attribute_encryption_key" let port = get "port" |> int let bind_to = get "bind_to" let master_public_key = get "master_public_key" |> ed25519 (* TODO Defaults to 0.0 if not specified. *) let stefan_abs = get "stefan_abs" |> amount let stefan_log = get "stefan_log" |> amount let stefan_lin = get_opt "stefan_lin" |> Option.map float |> Option.value ~default:0.0 let aggregator_idle_sleep_interval = get "aggregator_idle_sleep_interval" |> duration let closer_idle_sleep_interval = get "closer_idle_sleep_interval" |> duration let transfer_idle_sleep_interval = get "transfer_idle_sleep_interval" |> duration let wirewatch_idle_sleep_interval = get "wirewatch_idle_sleep_interval" |> duration let signkey_legal_duration = get "signkey_legal_duration" |> duration let max_keys_caching = get "max_keys_caching" |> duration let enable_kyc = get "enable_kyc" |> yes_no let terms_etag = get "terms_etag" |> etag let privacy_etag = get "privacy_etag" |> etag let base_url = get "base_url" let shopping_url = get_opt "shopping_url" let open_banking_gateway_url = get_opt "open_banking_gateway_url" let bank_compliance_language = get_opt "bank_compliance_language" let aml_spa_dialect = get_opt "aml_spa_dialect" let toplevel_redirect_url = get_opt "toplevel_redirect_url" let tiny_amount = get_opt "tiny_amount" |> Option.map amount (* not implemented or not relevant to MTE: let max_requests = get "max_requests" |> int aggregator_shard_size serve unixpath unixpath_mode terms_dir privacy_dir *) end module Exchangedb = struct let get field = get config_data ~section:"exchangedb" ~field (* - *) let idle_reserve_expiration_time = get "idle_reserve_expiration_time" |> duration let legal_reserve_expiration_time = get "legal_reserve_expiration_time" |> duration let aggregator_shift = get "aggregator_shift" |> duration let max_aml_program_runtime = get "max_aml_program_runtime" |> duration let default_purse_limit = get "default_purse_limit" |> int end module Exchangedb_postgres = struct let config = get config_data ~section:"exchangedb-postgres" ~field:"config" |> uri end module Currency = struct module Alt_unit_names = struct open Syntax module Int_map = Map.Make (Int) module String_map = Map.Make (String) type t = string Int_map.t let jsont = let of_string_map str_map = str_map |> String_map.to_list |> list_map (fun (k, v) -> match int_of_string_opt k with | None -> Error "not an integer" | Some k -> Ok (k, v)) |> function | Error e -> Jsont.Error.msg Jsont.Meta.none e | Ok l -> Int_map.of_list l in let to_string_map int_map = int_map |> Int_map.to_list |> List.map (fun (k, v) -> (string_of_int k, v)) |> String_map.of_list in let string_map_jsont = Jsont.Object.as_string_map Jsont.string in Jsont.map ~dec:of_string_map ~enc:to_string_map string_map_jsont end type t = { enabled: [ `YES | `NO ]; code: string; name: string; fractional_input_digits: int; fractional_normal_digits: int; fractional_trailing_zero_digits: int; alt_unit_names: Alt_unit_names.t; } let currency_sections = List.filter (fun v -> String.starts_with ~prefix:"currency-" v.header) config_data let parse_currency section = let get field = get config_data ~section:section.header ~field in { enabled= get "enabled" |> yes_no; code= get "code"; name= get "name"; fractional_input_digits= get "fractional_input_digits" |> int; fractional_normal_digits= get "fractional_normal_digits" |> int; fractional_trailing_zero_digits= get "fractional_trailing_zero_digits" |> int; alt_unit_names= get "alt_unit_names" |> Jsont_bytesrw.decode_string Alt_unit_names.jsont |> Parse_config.unwrap; } let all_currencies = List.map parse_currency currency_sections let v = match List.find_opt (fun v -> v.code = Exchange.currency) all_currencies with | None -> fail "section `[currency-%s]` not found, currency `%s` is not defined" Exchange.currency Exchange.currency | Some v -> ( match v.enabled = `YES with | false -> fail "currency `%s` is not enabled" Exchange.currency | true -> v) end module Coin = struct type t = { section_name: string; value: Amount.t; duration_withdraw: Time.TimeRelative.t; duration_spend: Time.TimeRelative.t; duration_legal: Time.TimeRelative.t; fee_withdraw: Amount.t; fee_deposit: Amount.t; fee_refresh: Amount.t; fee_refund: Amount.t; cipher: [ (* `CS |*) `RSA ]; rsa_keysize: int; (* : int option (only if `RSA) *) age_restricted: [ (*`YES|*) `NO ]; } let coin_sections = List.filter (fun v -> (* note: here its a '_' not '-' *) String.starts_with ~prefix:"coin_" v.header) config_data let parse_coin section = let get field = get config_data ~section:section.header ~field in let section_name = String.sub section.header 5 (String.length section.header - 5) in { section_name; value= get "value" |> amount; duration_withdraw= get "duration_withdraw" |> duration; duration_spend= get "duration_spend" |> duration; duration_legal= get "duration_legal" |> duration; fee_withdraw= get "fee_withdraw" |> amount; fee_deposit= get "fee_deposit" |> amount; fee_refresh= get "fee_refresh" |> amount; fee_refund= get "fee_refund" |> amount; cipher= (get "cipher" |> const_value "RSA" |> fun _s -> `RSA); rsa_keysize= get "rsa_keysize" |> int; age_restricted= ( get "age_restricted" |> yes_no |> function | `NO -> `NO | `YES -> fail "`age_restricted = YES` is not supported" ); } let all_coins = List.map parse_coin coin_sections end module Exchange_secmod_rsa = struct let get field = let section = "taler-exchange-secmod-" ^ "rsa" in get config_data ~section ~field let lookahead_sign = get "lookahead_sign" |> duration let overlap_duration = get "overlap_duration" |> duration let key_dir = get "key_dir" let sm_priv_key = get "sm_priv_key" end module Exchange_secmod_eddsa = struct let get field = let section = "taler-exchange-secmod-" ^ "eddsa" in get config_data ~section ~field let lookahead_sign = get "lookahead_sign" |> duration let overlap_duration = get "overlap_duration" |> duration let duration = get "duration" |> duration let key_dir = get "key_dir" let sm_priv_key = get "sm_priv_key" end (* -- *) include Exchange