mte/src/http_info.ml

196 lines
5.8 KiB
OCaml
Raw Normal View History

2025-12-14 23:34:25 +01:00
open Syntax
2025-12-14 21:34:03 +01:00
open Api
2025-12-14 23:34:25 +01:00
module String_map = Stdlib.Map.Make (Stdlib.String)
2026-02-07 21:25:49 +01:00
(* TODO mirage-crypto
is this ok?
maybe don't use the same RNG-initialization as the one used to generate keys *)
let seed req _server _env =
Logs.info (fun m -> m "GET /seed");
(* RNG is initialized by Vif.run *)
let s = Mirage_crypto_rng.generate 64 in
let open Vif.Response in
let open Syntax in
let* () = add ~field:"content-type" "application/octet-stream" in
let* () = with_string req s in
respond `OK
let config req _server _env =
Logs.info (fun m -> m "GET /config");
2026-02-23 07:24:40 +01:00
let res = Api.encode Api.ExchangeVersionResponse.jsont config in
Respond.result res req
2026-02-07 21:25:49 +01:00
2026-02-17 09:30:20 +01:00
let mk_keys ~db_conn (module Keys : Keys.S) ~last_issue_date =
2026-02-05 21:19:57 +01:00
let version = Api.protocol_version in
2025-12-14 23:34:25 +01:00
let base_url = Config.base_url in
let currency = Config.currency in
let shopping_url = Config.shopping_url in
let open_banking_gateway = Config.open_banking_gateway_url in
let bank_compliance_language = Config.bank_compliance_language in
2026-02-23 07:24:40 +01:00
let currency_specification = Api.currency_specification in
2025-12-14 23:34:25 +01:00
let tiny_amount = Config.tiny_amount in
let stefan_abs = Config.stefan_abs in
let stefan_log = Config.stefan_log in
let stefan_lin = Config.stefan_lin in
(* todo asset_type
Type of the asset. "fiat", "crypto", "regional" or "stock". *)
let asset_type = "xxx" in
2026-02-17 09:30:20 +01:00
let* accounts = Pg.get_wire_accounts db_conn () |> unwrap_err_caqti in
2025-12-14 23:34:25 +01:00
let* wire_fees =
(* todo
where does wire_methods comes from? *)
let wire_method = "xxx" in
let+ wire_fees =
Pg.get_wire_fees db_conn ~wire_method |> unwrap_err_caqti
in
String_map.singleton wire_method wire_fees
in
let wads =
(* TODO wads *)
[]
in
let rewards_allowed = false in
let kyc_enabled = false in
let disable_direct_deposit = (* todo *) false in
let master_public_key = Config.master_public_key in
let reserve_closing_delay = Config.Exchangedb.idle_reserve_expiration_time in
2025-12-14 23:34:25 +01:00
(* todo *)
let wallet_balance_limit_without_kyc = None in
let hard_limits = [] in
let zero_limits = [] in
2026-02-23 09:17:13 +01:00
2026-02-23 09:02:39 +01:00
let* denom_l = Keys.denominations () in
let denom_l =
2026-01-24 02:11:09 +01:00
(* reverse chronological order *)
2026-01-19 20:54:39 +01:00
List.sort
2026-02-17 09:30:20 +01:00
(fun a b -> Stdlib.compare b.Denomination.stamp_start a.stamp_start)
2026-02-23 09:02:39 +01:00
denom_l
2026-01-19 20:54:39 +01:00
in
let list_issue_date =
2026-02-23 09:02:39 +01:00
match denom_l with
2026-02-17 09:30:20 +01:00
| [] -> Timestamp.never
| dn :: _ -> dn.Denomination.stamp_start
2026-01-19 20:54:39 +01:00
in
2026-02-23 09:02:39 +01:00
let denom_l =
2026-01-24 02:16:14 +01:00
(* if `?last_issue_date` query param does not exactly match the `stamp_start`
of one of the denomination keys, all keys are returned *)
2026-02-23 09:02:39 +01:00
let stamp_start_opt =
2026-01-24 02:16:14 +01:00
match last_issue_date with
2026-02-23 09:02:39 +01:00
| None -> None
| Some timestamp ->
List.find_map
(fun v ->
if Timestamp.compare v.Denomination.stamp_start timestamp = 0 then
Some v.stamp_start
else None)
denom_l
2026-01-24 02:16:14 +01:00
in
2026-02-23 09:02:39 +01:00
match stamp_start_opt with
| None -> denom_l
| Some timestamp ->
List.filter
(fun v -> Timestamp.compare v.Denomination.stamp_start timestamp >= 0)
denom_l
2026-01-19 20:54:39 +01:00
in
2026-02-23 09:02:39 +01:00
let* denominations = Denomination.make_denom_group denom_l in
2026-01-19 20:54:39 +01:00
2026-02-23 09:17:13 +01:00
let* signkeys = Keys.signkeys () in
let signkeys =
signkeys
2026-02-17 09:30:20 +01:00
|> List.sort (fun a b ->
let open Signkey in
Stdlib.compare b.stamp_start a.stamp_start)
|> List.map Api.SignKey.of_signkey
2026-01-19 20:54:39 +01:00
in
let exchange_pub =
(* the eddsa pub key used to sign exchange_sig *)
match signkeys with
| [] -> Fmt.failwith "exchange has no active signkey"
2026-02-17 09:30:20 +01:00
| sk :: _ -> sk.SignKey.key
2026-01-19 20:54:39 +01:00
in
let exchange_sig =
2026-02-23 09:02:39 +01:00
(* Compact eddsa signature over the contatentation of all of the master_sigs
(in reverse chronological order by group) in the arrays under "denominations" *)
2026-01-22 04:10:26 +01:00
let hc =
2026-02-23 09:02:39 +01:00
denom_l
2026-02-17 09:30:20 +01:00
|> List.map (fun dn -> dn.Denomination.master_sig)
2026-02-05 19:26:59 +01:00
|> List.map Signatures.DenominationKeyValidity.to_octets
2026-01-22 04:10:26 +01:00
|> String.concat ""
2026-02-05 17:51:24 +01:00
|> Hash.H64.hash
2026-01-19 20:54:39 +01:00
in
2026-02-05 19:26:59 +01:00
let open Signatures.ExchangeKeySet in
2026-02-17 09:30:20 +01:00
signf (Keys.sign exchange_pub) R.{ list_issue_date; hc }
2026-01-19 20:54:39 +01:00
in
let recoup = (* TODO /recoup *) [] in
let* global_fees =
Pg.get_global_fees db_conn ~start_date:Timestamp.zero |> unwrap_err_caqti
in
let* auditors =
(* TODO /auditors/$AUDITOR_PUB/$H_DENOM_PUB *)
(* does not contains auditor_keys with empty denomination_keys *)
Pg.get_auditor_keys db_conn
in
2026-01-19 20:54:39 +01:00
let extensions = None in
let extensions_sig = None in
Ok
ExchangeKeysResponse.
2025-12-14 23:34:25 +01:00
{
version;
base_url;
currency;
shopping_url;
open_banking_gateway;
bank_compliance_language;
currency_specification;
tiny_amount;
stefan_abs;
stefan_log;
stefan_lin;
asset_type;
accounts;
wire_fees;
wads;
rewards_allowed;
kyc_enabled;
disable_direct_deposit;
master_public_key;
reserve_closing_delay;
wallet_balance_limit_without_kyc;
hard_limits;
zero_limits;
denominations;
exchange_sig;
exchange_pub;
recoup;
global_fees;
list_issue_date;
auditors;
signkeys;
extensions;
extensions_sig;
}
2025-12-14 21:34:03 +01:00
let jsont = ExchangeKeysResponse.jsont
2026-02-07 21:25:49 +01:00
let keys req server _env =
2026-02-07 00:11:25 +01:00
Logs.info (fun m -> m "GET /keys");
2025-12-14 23:34:25 +01:00
let db_conn = Vif.Server.device Devices.db_connection server in
2026-02-17 09:30:20 +01:00
let keys = Vif.Server.device Devices.keys server in
2025-12-14 21:34:03 +01:00
let res =
let* last_issue_date =
match Vif.Queries.get req "last_issue_date" with
| [] -> Ok None
2026-02-23 07:24:40 +01:00
| s :: _ -> (
match Int64.of_string_opt s with
| None ->
Error
"invalid `?last_issue_date` query param, int_of_string failure"
2026-02-23 07:24:40 +01:00
| Some n -> Ok (Some (Timestamp.of_s n)))
in
2026-02-17 09:30:20 +01:00
let* v = mk_keys ~db_conn keys ~last_issue_date in
2026-02-23 07:24:40 +01:00
Api.encode jsont v
2025-12-14 21:34:03 +01:00
in
2026-02-12 12:13:30 +01:00
Respond.result res req