handle global_fees; add do_management.sh
This commit is contained in:
parent
67bd144bb0
commit
ac4058df7e
11 changed files with 226 additions and 40 deletions
1
global_fees.json
Normal file
1
global_fees.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"start_date":{"t_s":0},"end_date":{"t_s":99999999.900000006},"history_fee":"EUR:0.00","account_fee":"EUR:0.00","purse_fee":"EUR:0.00","history_expiration":{"t_s":9999999000000},"purse_account_limit":1,"purse_timeout":{"t_s":9999999000000},"master_sig":"EHBTKAC30EYD2NGYB76B7JPG1VREYP4W3EQB6YQJJ41NHFWQSX9HQJXTZR9N65V6HAJB5KKHXAYTNBWBDJBE4YV38W6FGZYG6595E00="}
|
||||||
|
|
@ -117,3 +117,5 @@ let bin_nbo =
|
||||||
|+ field beint32 (fun t -> t.fraction)
|
|+ field beint32 (fun t -> t.fraction)
|
||||||
|+ field (bytes currency_len) (fun t -> pad_currency t.currency)
|
|+ field (bytes currency_len) (fun t -> pad_currency t.currency)
|
||||||
|> sealr
|
|> sealr
|
||||||
|
|
||||||
|
let dummy_value = "DUMMY:0.0" |> of_string |> Result.get_ok
|
||||||
|
|
|
||||||
|
|
@ -25,3 +25,7 @@ val jsont : t Jsont.t
|
||||||
(* only for encoding *)
|
(* only for encoding *)
|
||||||
val bin : t Bin.t
|
val bin : t Bin.t
|
||||||
val bin_nbo : t Bin.t
|
val bin_nbo : t Bin.t
|
||||||
|
|
||||||
|
(* TODO
|
||||||
|
dummy value to use as placeholder for WIP *)
|
||||||
|
val dummy_value : t
|
||||||
|
|
|
||||||
|
|
@ -190,8 +190,10 @@ let mk_keys ~db_conn (module Sm : Secmod.S) ~last_issue_date =
|
||||||
sign_f ~f:(Sm.sign_with_signkey ~pub:exchange_pub) R.{ list_issue_date; hc }
|
sign_f ~f:(Sm.sign_with_signkey ~pub:exchange_pub) R.{ list_issue_date; hc }
|
||||||
in
|
in
|
||||||
|
|
||||||
let recoup = [] in
|
let recoup = (* TODO /recoup *) [] in
|
||||||
let global_fees = (* TODO *) [] in
|
let* global_fees =
|
||||||
|
Pg.get_global_fees db_conn ~start_date:Timestamp.epoch |> unwrap_err_caqti
|
||||||
|
in
|
||||||
let auditors = (* TODO *) [] in
|
let auditors = (* TODO *) [] in
|
||||||
let extensions = None in
|
let extensions = None in
|
||||||
let extensions_sig = None in
|
let extensions_sig = None in
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ module Auditors = struct
|
||||||
let auditor_pub = v.AuditorSetupMessage.auditor_pub in
|
let auditor_pub = v.AuditorSetupMessage.auditor_pub in
|
||||||
let validity_start = v.AuditorSetupMessage.validity_start in
|
let validity_start = v.AuditorSetupMessage.validity_start in
|
||||||
let* last_date_opt =
|
let* last_date_opt =
|
||||||
Pg.lookup_auditor_timestamp db_conn auditor_pub |> unwrap_err_caqti
|
Pg.get_auditor_timestamp db_conn auditor_pub |> unwrap_err_caqti
|
||||||
in
|
in
|
||||||
match last_date_opt with
|
match last_date_opt with
|
||||||
| None ->
|
| None ->
|
||||||
|
|
@ -341,7 +341,7 @@ module Auditors_disable = struct
|
||||||
let do_ ~db_conn auditor_pub
|
let do_ ~db_conn auditor_pub
|
||||||
AuditorTeardownMessage.{ master_sig= _; validity_end } =
|
AuditorTeardownMessage.{ master_sig= _; validity_end } =
|
||||||
let* last_date_opt =
|
let* last_date_opt =
|
||||||
Pg.lookup_auditor_timestamp db_conn auditor_pub |> unwrap_err_caqti
|
Pg.get_auditor_timestamp db_conn auditor_pub |> unwrap_err_caqti
|
||||||
in
|
in
|
||||||
match last_date_opt with
|
match last_date_opt with
|
||||||
| None -> Error "auditor not found"
|
| None -> Error "auditor not found"
|
||||||
|
|
@ -433,13 +433,10 @@ module Global_fees = struct
|
||||||
purse_timeout;
|
purse_timeout;
|
||||||
master_sig;
|
master_sig;
|
||||||
} =
|
} =
|
||||||
(* TODO what is kyc_timeout, kyc_fee ? *)
|
(* TODO KYC
|
||||||
let dummy_amount =
|
what is kyc_timeout, kyc_fee ? *)
|
||||||
Amount.make ~sign:None ~currency:"EUR" ~value:0_L ~fraction:0_l
|
|
||||||
|> Result.get_ok
|
|
||||||
in
|
|
||||||
let kyc_timeout = None in
|
let kyc_timeout = None in
|
||||||
let kyc_fee = dummy_amount in
|
let kyc_fee = Amount.dummy_value in
|
||||||
(* * *)
|
(* * *)
|
||||||
let open Bin_sig.GlobalFees in
|
let open Bin_sig.GlobalFees in
|
||||||
verify_f ~f:Sm.verify_with_master_key master_sig
|
verify_f ~f:Sm.verify_with_master_key master_sig
|
||||||
|
|
@ -460,17 +457,33 @@ module Global_fees = struct
|
||||||
let* global_fees =
|
let* global_fees =
|
||||||
let start_date = v.GlobalFees.start_date in
|
let start_date = v.GlobalFees.start_date in
|
||||||
let end_date = v.GlobalFees.end_date in
|
let end_date = v.GlobalFees.end_date in
|
||||||
Pg.lookup_global_fees_by_time db_conn ~start_date ~end_date
|
Pg.get_global_fees_by_time db_conn ~start_date ~end_date
|
||||||
|> unwrap_err_caqti
|
|> unwrap_err_caqti
|
||||||
in
|
in
|
||||||
match global_fees with
|
match global_fees with
|
||||||
| [] ->
|
| [] ->
|
||||||
let+ () = Pg.insert_global_fee db_conn v |> unwrap_err_caqti in
|
let+ () = Pg.insert_global_fees db_conn v |> unwrap_err_caqti in
|
||||||
|
Logs.info (fun m -> m "added global fees");
|
||||||
()
|
()
|
||||||
| _l -> Error "global-fees already setup"
|
| [ vv ] -> (
|
||||||
|
match v.master_sig = vv.master_sig with
|
||||||
|
| false ->
|
||||||
|
Error
|
||||||
|
"a different global-fees was already setup for this time frame"
|
||||||
|
| true ->
|
||||||
|
Logs.info (fun m -> m "an identical global-fees was already setup");
|
||||||
|
Ok ())
|
||||||
|
| _ ->
|
||||||
|
Error
|
||||||
|
"invalid database state, multiple global-fees found in database for \
|
||||||
|
this time frame"
|
||||||
|
|
||||||
let jsont = GlobalFees.jsont
|
let jsont = GlobalFees.jsont
|
||||||
|
|
||||||
|
(* TODO global_fees
|
||||||
|
ensure it is defined for the current time.
|
||||||
|
there should be only one global_fees for each moment in time
|
||||||
|
and once set for a timeframe, it should not change. *)
|
||||||
let f req server _env =
|
let f req server _env =
|
||||||
Logs.info (fun m -> m "POST /management/global-fees/");
|
Logs.info (fun m -> m "POST /management/global-fees/");
|
||||||
let sm = Vif.Server.device Devices.secmod server in
|
let sm = Vif.Server.device Devices.secmod server in
|
||||||
|
|
@ -526,7 +539,7 @@ module Wire = struct
|
||||||
let do_ ~db_conn v =
|
let do_ ~db_conn v =
|
||||||
let* last_change_opt =
|
let* last_change_opt =
|
||||||
let payto_uri = v.WireSetupMessage.payto_uri in
|
let payto_uri = v.WireSetupMessage.payto_uri in
|
||||||
Pg.lookup_wire_timestamp db_conn ~payto_uri |> unwrap_err_caqti
|
Pg.get_wire_timestamp db_conn ~payto_uri |> unwrap_err_caqti
|
||||||
in
|
in
|
||||||
match last_change_opt with
|
match last_change_opt with
|
||||||
| Some _ -> Error "wire already setup"
|
| Some _ -> Error "wire already setup"
|
||||||
|
|
@ -573,7 +586,7 @@ module Wire_disable = struct
|
||||||
let do_ ~db_conn
|
let do_ ~db_conn
|
||||||
WireTeardownMessage.{ payto_uri; master_sig_del= _; validity_end } =
|
WireTeardownMessage.{ payto_uri; master_sig_del= _; validity_end } =
|
||||||
let* last_change_opt =
|
let* last_change_opt =
|
||||||
Pg.lookup_wire_timestamp db_conn ~payto_uri |> unwrap_err_caqti
|
Pg.get_wire_timestamp db_conn ~payto_uri |> unwrap_err_caqti
|
||||||
in
|
in
|
||||||
match last_change_opt with
|
match last_change_opt with
|
||||||
| None -> Error "wire not found"
|
| None -> Error "wire not found"
|
||||||
|
|
|
||||||
36
src/pg.ml
36
src/pg.ml
|
|
@ -12,6 +12,8 @@
|
||||||
transaction
|
transaction
|
||||||
|
|
||||||
should check validity of signatures got from db, for /management at least *)
|
should check validity of signatures got from db, for /management at least *)
|
||||||
|
(* TODO time
|
||||||
|
fix comparison with timestamp footgun *)
|
||||||
|
|
||||||
module type CONN = Caqti_miou.CONNECTION
|
module type CONN = Caqti_miou.CONNECTION
|
||||||
|
|
||||||
|
|
@ -128,13 +130,13 @@ let insert_signkey_revocation =
|
||||||
fun (module Conn : CONN) exchange_pub master_sig ->
|
fun (module Conn : CONN) exchange_pub master_sig ->
|
||||||
Conn.exec signkey_revocation_insert (exchange_pub, master_sig)
|
Conn.exec signkey_revocation_insert (exchange_pub, master_sig)
|
||||||
|
|
||||||
let lookup_auditor_timestamp =
|
let get_auditor_timestamp =
|
||||||
let lookup_auditor_timestamp =
|
let get_auditor_timestamp =
|
||||||
Caqti_type.(eddsa_pub ->? time)
|
Caqti_type.(eddsa_pub ->? time)
|
||||||
"SELECT last_change FROM auditors WHERE auditor_pub=$1"
|
"SELECT last_change FROM auditors WHERE auditor_pub=$1"
|
||||||
in
|
in
|
||||||
fun (module Conn : CONN) auditor_pub ->
|
fun (module Conn : CONN) auditor_pub ->
|
||||||
Conn.find_opt lookup_auditor_timestamp auditor_pub
|
Conn.find_opt get_auditor_timestamp auditor_pub
|
||||||
|
|
||||||
let insert_auditor =
|
let insert_auditor =
|
||||||
let insert_auditor =
|
let insert_auditor =
|
||||||
|
|
@ -265,14 +267,14 @@ let insert_wire_fee =
|
||||||
(wire_method, fee_start, fee_end, wire_fee, closing_fee, master_sig_wire)
|
(wire_method, fee_start, fee_end, wire_fee, closing_fee, master_sig_wire)
|
||||||
|
|
||||||
let get_wire_fees_by_time =
|
let get_wire_fees_by_time =
|
||||||
let lookup_wire_fee_by_time =
|
let get_wire_fee_by_time =
|
||||||
Caqti_type.(t3 wire_method time time ->* aggregate_transfer_fee)
|
Caqti_type.(t3 wire_method time time ->* aggregate_transfer_fee)
|
||||||
"SELECT (wire_fee).*, (closing_fee).*, start_date, end_date, master_sig \
|
"SELECT (wire_fee).*, (closing_fee).*, start_date, end_date, master_sig \
|
||||||
FROM wire_fee WHERE wire_method=$1 AND end_date > $2 AND start_date < \
|
FROM wire_fee WHERE wire_method=$1 AND end_date > $2 AND start_date < \
|
||||||
$3"
|
$3"
|
||||||
in
|
in
|
||||||
fun (module Conn : CONN) ~wire_method ~start_date ~end_date ->
|
fun (module Conn : CONN) ~wire_method ~start_date ~end_date ->
|
||||||
Conn.collect_list lookup_wire_fee_by_time (wire_method, start_date, end_date)
|
Conn.collect_list get_wire_fee_by_time (wire_method, start_date, end_date)
|
||||||
|
|
||||||
let get_wire_fees =
|
let get_wire_fees =
|
||||||
let get_wire_fees =
|
let get_wire_fees =
|
||||||
|
|
@ -293,33 +295,33 @@ let get_global_fees =
|
||||||
fun (module Conn : CONN) ~start_date ->
|
fun (module Conn : CONN) ~start_date ->
|
||||||
Conn.collect_list get_global_fees start_date
|
Conn.collect_list get_global_fees start_date
|
||||||
|
|
||||||
let lookup_global_fees_by_time =
|
let get_global_fees_by_time =
|
||||||
let lookup_global_fees_by_time =
|
let get_global_fees_by_time =
|
||||||
Caqti_type.(t2 time time ->* global_fee)
|
Caqti_type.(t2 time time ->* global_fee)
|
||||||
"SELECT start_date, end_date, (history_fee).*, (account_fee).*, \
|
"SELECT start_date, end_date, (history_fee).*, (account_fee).*, \
|
||||||
(purse_fee).*, history_expiration, purse_account_limit, purse_timeout, \
|
(purse_fee).*, history_expiration, purse_account_limit, purse_timeout, \
|
||||||
master_sig FROM global_fee WHERE end_date > $1 AND start_date < $2"
|
master_sig FROM global_fee WHERE start_date >= $1 AND end_date <= $2"
|
||||||
in
|
in
|
||||||
fun (module Conn : CONN) ~start_date ~end_date ->
|
fun (module Conn : CONN) ~start_date ~end_date ->
|
||||||
Conn.collect_list lookup_global_fees_by_time (start_date, end_date)
|
Conn.collect_list get_global_fees_by_time (start_date, end_date)
|
||||||
|
|
||||||
let insert_global_fee =
|
let insert_global_fees =
|
||||||
let insert_global_fee =
|
let insert_global_fees =
|
||||||
Caqti_type.(global_fee ->. unit)
|
Caqti_type.(global_fee ->. unit)
|
||||||
"INSERT INTO global_fee (start_date, end_date, history_fee, account_fee, \
|
"INSERT INTO global_fee (start_date, end_date, history_fee, account_fee, \
|
||||||
purse_fee, history_expiration, purse_account_limit, purse_timeout, \
|
purse_fee, history_expiration, purse_account_limit, purse_timeout, \
|
||||||
master_sig) VALUES ($1, $2, ($3,$4), ($5,$6), ($7,$8), $9, $10, $11, \
|
master_sig) VALUES ($1, $2, ($3,$4), ($5,$6), ($7,$8), $9, $10, $11, \
|
||||||
$12)"
|
$12)"
|
||||||
in
|
in
|
||||||
fun (module Conn : CONN) v -> Conn.exec insert_global_fee v
|
fun (module Conn : CONN) v -> Conn.exec insert_global_fees v
|
||||||
|
|
||||||
let lookup_wire_timestamp =
|
let get_wire_timestamp =
|
||||||
let lookup_wire_timestamp =
|
let get_wire_timestamp =
|
||||||
Caqti_type.(payto_uri ->? time)
|
Caqti_type.(payto_uri ->? time)
|
||||||
"SELECT last_change FROM wire_accounts WHERE payto_uri=$1"
|
"SELECT last_change FROM wire_accounts WHERE payto_uri=$1"
|
||||||
in
|
in
|
||||||
fun (module Conn : CONN) ~payto_uri ->
|
fun (module Conn : CONN) ~payto_uri ->
|
||||||
Conn.find_opt lookup_wire_timestamp payto_uri
|
Conn.find_opt get_wire_timestamp payto_uri
|
||||||
|
|
||||||
let insert_wire =
|
let insert_wire =
|
||||||
let insert_wire =
|
let insert_wire =
|
||||||
|
|
@ -388,7 +390,3 @@ let insert_partner =
|
||||||
$3, $4, ($5,$6), $7, $8) ON CONFLICT DO NOTHING"
|
$3, $4, ($5,$6), $7, $8) ON CONFLICT DO NOTHING"
|
||||||
in
|
in
|
||||||
fun (module Conn : CONN) v -> Conn.exec insert_partner v
|
fun (module Conn : CONN) v -> Conn.exec insert_partner v
|
||||||
|
|
||||||
(* TODO
|
|
||||||
get_recoup_denoms
|
|
||||||
*)
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
type t = Ptime.t option
|
type t = Ptime.t option
|
||||||
type span = Ptime.Span.t option
|
type span = Ptime.Span.t option
|
||||||
|
|
||||||
|
let epoch = Some Ptime.epoch
|
||||||
|
|
||||||
let diff a b =
|
let diff a b =
|
||||||
match (a, b) with
|
match (a, b) with
|
||||||
| None, _ | _, None -> None
|
| None, _ | _, None -> None
|
||||||
|
|
@ -23,6 +25,23 @@ let of_span_exn = function
|
||||||
|
|
||||||
(* -- *)
|
(* -- *)
|
||||||
|
|
||||||
|
(* TODO
|
||||||
|
this doesn't handle "never" value, and truncate time *)
|
||||||
|
let of_string s =
|
||||||
|
match Float.of_string_opt s with
|
||||||
|
| None -> Error "Timestamp.of_string failure: not a float"
|
||||||
|
| Some v -> (
|
||||||
|
match Ptime.of_float_s v with
|
||||||
|
| None -> Error "Timestamp.of_string failure"
|
||||||
|
| Some v -> Ok (Some v))
|
||||||
|
|
||||||
|
let pp fmt t =
|
||||||
|
match t with
|
||||||
|
| None -> Fmt.pf fmt {|"never"|}
|
||||||
|
| Some v ->
|
||||||
|
let v = Ptime.to_float_s v in
|
||||||
|
Fmt.pf fmt {|%f|} v
|
||||||
|
|
||||||
(* microseconds since the UNIX Epoch, or "never" if None *)
|
(* microseconds since the UNIX Epoch, or "never" if None *)
|
||||||
let jsont =
|
let jsont =
|
||||||
let number_or_never_jsont =
|
let number_or_never_jsont =
|
||||||
|
|
@ -62,7 +81,7 @@ let decode_int64 i = if i = Int64.max_int then None else Some (ptime_of_int64 i)
|
||||||
let bin = Bin.map Bin.neint64 decode_int64 encode_int64
|
let bin = Bin.map Bin.neint64 decode_int64 encode_int64
|
||||||
let bin_nbo = Bin.map Bin.beint64 decode_int64 encode_int64
|
let bin_nbo = Bin.map Bin.beint64 decode_int64 encode_int64
|
||||||
|
|
||||||
let caqti : Ptime.t option Caqti_type.t =
|
let caqti : t Caqti_type.t =
|
||||||
let encode v = Ok (encode_int64 v) in
|
let encode v = Ok (encode_int64 v) in
|
||||||
let decode v = Ok (decode_int64 v) in
|
let decode v = Ok (decode_int64 v) in
|
||||||
Caqti_type.custom ~encode ~decode Caqti_type.int64
|
Caqti_type.custom ~encode ~decode Caqti_type.int64
|
||||||
|
|
@ -80,6 +99,23 @@ let compare a b =
|
||||||
module Span = struct
|
module Span = struct
|
||||||
type t = span
|
type t = span
|
||||||
|
|
||||||
|
(* TODO
|
||||||
|
this doesn't handle "never" value, and truncate time *)
|
||||||
|
let of_string s =
|
||||||
|
match Float.of_string_opt s with
|
||||||
|
| None -> Error "Timestamp.Span.of_string failure: not a float"
|
||||||
|
| Some v -> (
|
||||||
|
match Ptime.Span.of_float_s v with
|
||||||
|
| None -> Error "Timestamp.Span.of_string failure"
|
||||||
|
| Some v -> Ok (Some v))
|
||||||
|
|
||||||
|
let pp fmt t =
|
||||||
|
match t with
|
||||||
|
| None -> Fmt.pf fmt {|"forever"|}
|
||||||
|
| Some v ->
|
||||||
|
let v = Ptime.Span.to_float_s v in
|
||||||
|
Fmt.pf fmt {|%f|} v
|
||||||
|
|
||||||
let to_int64 ptime = ptime |> Ptime.Span.to_float_s |> Int64.of_float
|
let to_int64 ptime = ptime |> Ptime.Span.to_float_s |> Int64.of_float
|
||||||
|
|
||||||
let of_int64 i =
|
let of_int64 i =
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
(* TODO time
|
(* TODO time
|
||||||
uhuh!
|
uhuh!
|
||||||
need to be int64 for binary/pg round trip
|
need to be int64 for binary/pg round trip
|
||||||
|
really need to fix this module
|
||||||
really need to fix this module *)
|
don't use option for never/forever *)
|
||||||
|
|
||||||
type t = Ptime.t option
|
type t = Ptime.t option
|
||||||
type span = Ptime.Span.t option
|
type span = Ptime.Span.t option
|
||||||
|
|
@ -10,17 +10,27 @@ type span = Ptime.Span.t option
|
||||||
module Span : sig
|
module Span : sig
|
||||||
type t = span
|
type t = span
|
||||||
|
|
||||||
|
val of_string : string -> (t, string) result
|
||||||
|
val pp : Stdlib.Format.formatter -> t -> unit
|
||||||
|
|
||||||
|
(* - *)
|
||||||
|
|
||||||
val jsont : t Jsont.t
|
val jsont : t Jsont.t
|
||||||
val bin : t Bin.t
|
val bin : t Bin.t
|
||||||
val bin_nbo : t Bin.t
|
val bin_nbo : t Bin.t
|
||||||
val caqti : t Caqti_type.t
|
val caqti : t Caqti_type.t
|
||||||
end
|
end
|
||||||
|
|
||||||
|
val epoch : t
|
||||||
val diff : t -> t -> span
|
val diff : t -> t -> span
|
||||||
val add_span_exn : t -> span -> t
|
val add_span_exn : t -> span -> t
|
||||||
val of_span_exn : span -> t
|
val of_span_exn : span -> t
|
||||||
val compare : t -> t -> int option
|
val compare : t -> t -> int option
|
||||||
|
|
||||||
|
(* used for offline tool argument conversion *)
|
||||||
|
val of_string : string -> (t, string) result
|
||||||
|
val pp : Stdlib.Format.formatter -> t -> unit
|
||||||
|
|
||||||
(* - *)
|
(* - *)
|
||||||
val jsont : t Jsont.t
|
val jsont : t Jsont.t
|
||||||
val bin : t Bin.t
|
val bin : t Bin.t
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,17 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
dune exec offline -- download && \
|
set -e
|
||||||
dune exec offline -- sign && \
|
|
||||||
dune exec offline -- upload
|
file1="tmp_file1.json"
|
||||||
|
file2="tmp_file2.json"
|
||||||
|
file3="tmp_file3.json"
|
||||||
|
|
||||||
|
dune exec offline -- download --output $file1
|
||||||
|
dune exec offline -- sign --input $file1 --output $file2
|
||||||
|
dune exec offline -- upload --input $file2 --url "/management/keys"
|
||||||
|
dune exec offline -- global-fees --output $file3 --start_date "0.0" --end_date "99999999.9" --history_fee "EUR:0.0" --account_fee "EUR:0.0" --purse_fee "EUR:0.0" --history_expiration "9999999.0" --purse_account_limit 1 --purse_timeout "9999999.0"
|
||||||
|
dune exec offline -- upload --input $file3 --url "/management/global-fees"
|
||||||
|
|
||||||
|
rm $file1
|
||||||
|
rm $file2
|
||||||
|
rm $file3
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,18 @@ let default_request_file = "request.json"
|
||||||
(*let to_term_ret = function Error e -> `Error (false, e) | Ok () -> `Ok ()*)
|
(*let to_term_ret = function Error e -> `Error (false, e) | Ok () -> `Ok ()*)
|
||||||
let to_term_ret = Fun.id
|
let to_term_ret = Fun.id
|
||||||
|
|
||||||
|
let timestamp =
|
||||||
|
Arg.Conv.make ~docv:"timestamp argument" ~parser:Timestamp.of_string
|
||||||
|
~pp:Timestamp.pp ()
|
||||||
|
|
||||||
|
let relative_time =
|
||||||
|
Arg.Conv.make ~docv:"relative time argument" ~parser:Timestamp.Span.of_string
|
||||||
|
~pp:Timestamp.Span.pp ()
|
||||||
|
|
||||||
|
let amount =
|
||||||
|
Arg.Conv.make ~docv:"amount argument" ~parser:Amount.of_string ~pp:Amount.pp
|
||||||
|
()
|
||||||
|
|
||||||
let setup_cmd =
|
let setup_cmd =
|
||||||
let doc = "Generate offline master keys" in
|
let doc = "Generate offline master keys" in
|
||||||
let output =
|
let output =
|
||||||
|
|
@ -94,6 +106,50 @@ let revoke_signkey_cmd =
|
||||||
let+ output = output and+ master_key = master_key and+ signkey = signkey in
|
let+ output = output and+ master_key = master_key and+ signkey = signkey in
|
||||||
revoke_signkey ~output ~master_key ~signkey |> to_term_ret
|
revoke_signkey ~output ~master_key ~signkey |> to_term_ret
|
||||||
|
|
||||||
|
let global_fees_cmd =
|
||||||
|
let doc = "Provides global fee configuration." in
|
||||||
|
let start_date =
|
||||||
|
Arg.(required & opt (some timestamp) None & info [ "start_date" ])
|
||||||
|
in
|
||||||
|
let end_date =
|
||||||
|
Arg.(required & opt (some timestamp) None & info [ "end_date" ])
|
||||||
|
in
|
||||||
|
let history_fee =
|
||||||
|
Arg.(required & opt (some amount) None & info [ "history_fee" ])
|
||||||
|
in
|
||||||
|
let account_fee =
|
||||||
|
Arg.(required & opt (some amount) None & info [ "account_fee" ])
|
||||||
|
in
|
||||||
|
let purse_fee =
|
||||||
|
Arg.(required & opt (some amount) None & info [ "purse_fee" ])
|
||||||
|
in
|
||||||
|
let history_expiration =
|
||||||
|
Arg.(
|
||||||
|
required & opt (some relative_time) None & info [ "history_expiration" ])
|
||||||
|
in
|
||||||
|
let purse_account_limit =
|
||||||
|
Arg.(required & opt (some int) None & info [ "purse_account_limit" ])
|
||||||
|
in
|
||||||
|
let purse_timeout =
|
||||||
|
Arg.(required & opt (some relative_time) None & info [ "purse_timeout" ])
|
||||||
|
in
|
||||||
|
Cmd.make (Cmd.info "global-fees" ~doc)
|
||||||
|
@@
|
||||||
|
let+ output = output
|
||||||
|
and+ master_key = master_key
|
||||||
|
and+ start_date = start_date
|
||||||
|
and+ end_date = end_date
|
||||||
|
and+ history_fee = history_fee
|
||||||
|
and+ account_fee = account_fee
|
||||||
|
and+ purse_fee = purse_fee
|
||||||
|
and+ history_expiration = history_expiration
|
||||||
|
and+ purse_account_limit = purse_account_limit
|
||||||
|
and+ purse_timeout = purse_timeout in
|
||||||
|
global_fees ~output ~master_key ~start_date ~end_date ~history_fee
|
||||||
|
~account_fee ~purse_fee ~history_expiration ~purse_account_limit
|
||||||
|
~purse_timeout
|
||||||
|
|> to_term_ret
|
||||||
|
|
||||||
let cli =
|
let cli =
|
||||||
let info =
|
let info =
|
||||||
let doc = "MTE Offline CLI tool" in
|
let doc = "MTE Offline CLI tool" in
|
||||||
|
|
@ -107,6 +163,7 @@ let cli =
|
||||||
upload_cmd;
|
upload_cmd;
|
||||||
revoke_denom_cmd;
|
revoke_denom_cmd;
|
||||||
revoke_signkey_cmd;
|
revoke_signkey_cmd;
|
||||||
|
global_fees_cmd;
|
||||||
]
|
]
|
||||||
|
|
||||||
let main () = Cmd.eval_result cli
|
let main () = Cmd.eval_result cli
|
||||||
|
|
|
||||||
|
|
@ -75,3 +75,54 @@ let revoke_signkey ~output ~master_key ~signkey =
|
||||||
let* s = Api.encode Api.SignkeyRevocationSignature.jsont v in
|
let* s = Api.encode Api.SignkeyRevocationSignature.jsont v in
|
||||||
let* () = write_file output s in
|
let* () = write_file output s in
|
||||||
Ok ()
|
Ok ()
|
||||||
|
|
||||||
|
let global_fees ~output ~master_key ~start_date ~end_date ~history_fee
|
||||||
|
~account_fee ~purse_fee ~history_expiration ~purse_account_limit
|
||||||
|
~purse_timeout =
|
||||||
|
let open Crypto in
|
||||||
|
let* key = read_file master_key in
|
||||||
|
let* key = EddsaPrivateKey.of_octets key in
|
||||||
|
let* purse_account_limit =
|
||||||
|
match
|
||||||
|
purse_account_limit >= 0
|
||||||
|
&& purse_account_limit <= Int32.to_int Int32.max_int
|
||||||
|
with
|
||||||
|
| false -> Error "invalid purse_account_limit value"
|
||||||
|
| true -> Ok (Int32.of_int purse_account_limit)
|
||||||
|
in
|
||||||
|
let master_sig =
|
||||||
|
let open Bin_sig.GlobalFees in
|
||||||
|
(* TODO KYC *)
|
||||||
|
let kyc_timeout = None in
|
||||||
|
let kyc_fee = Amount.dummy_value in
|
||||||
|
sign_f ~f:(EddsaSignature.sign ~key)
|
||||||
|
{
|
||||||
|
start_date;
|
||||||
|
end_date;
|
||||||
|
purse_timeout;
|
||||||
|
kyc_timeout;
|
||||||
|
history_expiration;
|
||||||
|
history_fee;
|
||||||
|
kyc_fee;
|
||||||
|
account_fee;
|
||||||
|
purse_fee;
|
||||||
|
purse_account_limit;
|
||||||
|
}
|
||||||
|
in
|
||||||
|
let global_fees =
|
||||||
|
Api.GlobalFees.
|
||||||
|
{
|
||||||
|
start_date;
|
||||||
|
end_date;
|
||||||
|
purse_timeout;
|
||||||
|
history_expiration;
|
||||||
|
history_fee;
|
||||||
|
account_fee;
|
||||||
|
purse_fee;
|
||||||
|
purse_account_limit;
|
||||||
|
master_sig;
|
||||||
|
}
|
||||||
|
in
|
||||||
|
let* s = Api.encode Api.GlobalFees.jsont global_fees in
|
||||||
|
let* () = write_file output s in
|
||||||
|
Ok ()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue