open Cmdliner open Cmdliner.Term.Syntax open Offline_impl module Arg = struct include Arg 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 b32 = let pp fmt v = Fmt.pf fmt "%s" (B32.encode v) in Arg.Conv.make ~docv:"Crockford's Base32 encoded argument" ~parser:B32.decode ~pp () let amount = Arg.Conv.make ~docv:"amount argument" ~parser:Amount.of_string ~pp:Amount.pp () let eddsa_pub = let parser s = Crypto.EddsaPublicKey.of_b32 s in let pp fmt key = let s = Crypto.EddsaPublicKey.to_b32 key in Fmt.pf fmt "%s" s in Arg.Conv.make ~docv:"eddsa public key argument" ~parser ~pp () end let default_master_offline_key_file = "data/master_offline_private_key" (* let default_response_file = "response.json" let default_request_file = "request.json" *) let master_key = let doc = "Master offline Eddsa private key file." in Arg.( value & opt file default_master_offline_key_file & info [ "master_key_file" ] ~doc) let input = let doc = "input file" in Arg.(required & opt (some file) None & info [ "i"; "input" ] ~doc) let output = let doc = "output file" in Arg.(required & opt (some filepath) None & info [ "o"; "output" ] ~doc) let url = let doc = "url" in Arg.(required & opt (some string) None & info [ "url" ] ~doc) let setup_cmd = let doc = "Generate offline master keys" in let output = let doc = "output file" in Arg.( value & opt filepath default_master_offline_key_file & info [ "o"; "output" ] ~doc) in Cmd.make (Cmd.info "setup" ~doc) @@ let+ output = output in setup ~output let download_cmd = let doc = "GET /management/keys/" in let man = [ `S Manpage.s_description; `P "$(cmd) download /management/keys." ] in Cmd.make (Cmd.info "download" ~doc ~man) @@ let+ output = output in download ~output let upload_cmd = let doc = "POST input.json data to url (default /management/keys)" in Cmd.make (Cmd.info "upload" ~doc) @@ let+ input = input and+ url = url in upload ~input ~url let sign_cmd = let doc = "Sign FutureKeysResponse." in Cmd.make (Cmd.info "sign" ~doc) @@ let+ input = input and+ output = output and+ master_key = master_key in sign ~input ~output ~master_key let revoke_denom_cmd = let doc = "Revoke denomination." in let h_denom = let doc = "hash of denomination public key" in Arg.(required & pos 0 (some string) None & info [] ~doc) in Cmd.make (Cmd.info "revoke-denom" ~doc) @@ let+ output = output and+ master_key = master_key and+ h_denom = h_denom in revoke_denom ~output ~master_key ~h_denom let revoke_signkey_cmd = let doc = "Revoke signkey." in let signkey = let doc = "public signing key" in Arg.(required & pos 0 (some eddsa_pub) None & info [] ~doc) in Cmd.make (Cmd.info "revoke-signkey" ~doc) @@ let+ output = output and+ master_key = master_key and+ signkey = signkey in revoke_signkey ~output ~master_key ~signkey let enable_auditor_cmd = let doc = "Enable auditor." in let auditor_url = Arg.(required & opt (some string) None & info [ "auditor_url" ]) in let auditor_name = Arg.(required & opt (some string) None & info [ "auditor_name" ]) in let auditor_pub = Arg.(required & opt (some eddsa_pub) None & info [ "auditor_pub" ]) in let validity_start = Arg.(required & opt (some timestamp) None & info [ "validity_start" ]) in Cmd.make (Cmd.info "enable-auditor" ~doc) @@ let+ output = output and+ master_key = master_key and+ auditor_url = auditor_url and+ auditor_name = auditor_name and+ auditor_pub = auditor_pub and+ validity_start = validity_start in enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub ~validity_start let disable_auditor_cmd = let doc = "Disable auditor." in let auditor_pub = Arg.(required & opt (some eddsa_pub) None & info [ "auditor_pub" ]) in let validity_end = Arg.(required & opt (some timestamp) None & info [ "validity_end" ]) in Cmd.make (Cmd.info "disable-auditor" ~doc) @@ let+ output = output and+ master_key = master_key and+ auditor_pub = auditor_pub and+ validity_end = validity_end in disable_auditor ~output ~master_key ~auditor_pub ~validity_end let wire_fee_cmd = let doc = "Provides wire fee configuration." in let wire_method = Arg.(required & opt (some string) None & info [ "wire_method" ]) in let fee_start = Arg.(required & opt (some timestamp) None & info [ "fee_start" ]) in let fee_end = Arg.(required & opt (some timestamp) None & info [ "fee_end" ]) in let closing_fee = Arg.(required & opt (some amount) None & info [ "closing_fee" ]) in let wire_fee = Arg.(required & opt (some amount) None & info [ "wire_fee" ]) in Cmd.make (Cmd.info "wire-fee" ~doc) @@ let+ output = output and+ master_key = master_key and+ wire_method = wire_method and+ fee_start = fee_start and+ fee_end = fee_end and+ closing_fee = closing_fee and+ wire_fee = wire_fee in Offline_impl.wire_fee ~output ~master_key ~wire_method ~fee_start ~fee_end ~closing_fee ~wire_fee 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 let drain_cmd = let doc = "Drain profits from the exchange. The actual drain requires running the \ taler-exchange-drain tool." in let debit_account_section = Arg.(required & opt (some string) None & info [ "debit_account_section" ]) in let credit_payto_uri = Arg.(required & opt (some string) None & info [ "credit_payto_uri" ]) in let wtid = Arg.(required & opt (some b32) None & info [ "wtid" ]) in let date = Arg.(required & opt (some timestamp) None & info [ "date" ]) in let amount = Arg.(required & opt (some amount) None & info [ "amount" ]) in Cmd.make (Cmd.info "drain" ~doc) @@ let+ output = output and+ master_key = master_key and+ debit_account_section = debit_account_section and+ credit_payto_uri = credit_payto_uri and+ wtid = wtid and+ date = date and+ amount = amount in drain ~output ~master_key ~debit_account_section ~credit_payto_uri ~wtid ~date ~amount let cli = let info = let doc = "MTE Offline CLI tool" in Cmd.info "mte-offline" ~doc in Cmd.group info [ setup_cmd; download_cmd; sign_cmd; upload_cmd; revoke_denom_cmd; revoke_signkey_cmd; enable_auditor_cmd; disable_auditor_cmd; wire_fee_cmd; global_fees_cmd; drain_cmd; ] let main () = Cmd.eval_result cli let () = if !Sys.interactive then () else exit (main ()) (* TODO all management operations: /management/wire /management/wire/disable -> how to build WireSetupMessage? we need additional data to craft master_sig maybe supposed to be found in the full payto-uri? /management/aml-officers -> /aml /management/partners -> /wads *)