From 9cae3bebf94f018541014e73333bc0274e6a8223 Mon Sep 17 00:00:00 2001 From: swrup Date: Tue, 3 Feb 2026 22:29:29 +0100 Subject: [PATCH] offline tool: add drain cmd --- tools/offline.ml | 38 ++++++++++++++++++++++++++++++++++++-- tools/offline_impl.ml | 30 ++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/tools/offline.ml b/tools/offline.ml index c9026624..3f94b4fe 100644 --- a/tools/offline.ml +++ b/tools/offline.ml @@ -13,6 +13,11 @@ module Arg = struct 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 () @@ -224,6 +229,32 @@ let global_fees_cmd = ~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 @@ -241,6 +272,7 @@ let cli = disable_auditor_cmd; wire_fee_cmd; global_fees_cmd; + drain_cmd; ] let main () = Cmd.eval_result cli @@ -253,6 +285,8 @@ let () = if !Sys.interactive then () else exit (main ()) -> how to build WireSetupMessage? we need additional data to craft master_sig maybe supposed to be found in the full payto-uri? - /management/drain + /management/aml-officers - /management/partners *) + -> /aml + /management/partners + -> /wads *) diff --git a/tools/offline_impl.ml b/tools/offline_impl.ml index 63d5b120..0a505f8d 100644 --- a/tools/offline_impl.ml +++ b/tools/offline_impl.ml @@ -197,3 +197,33 @@ let wire_fee ~output ~master_key ~wire_method ~fee_start ~fee_end ~closing_fee let* s = Api.encode Api.WireFeeSetupMessage.jsont v in let* () = write_file output s in Ok () + +let drain ~output ~master_key ~debit_account_section ~credit_payto_uri ~wtid + ~date ~amount = + let open Crypto in + let* key = read_master_key_file master_key in + let master_sig = + let open Bin_sig.MasterDrainProfit in + sign_f ~f:(EddsaSignature.sign ~key) + { + wtid; + date; + amount; + h_section= Bin_type.Hash_64_cstr.hash debit_account_section; + h_payto= Bin_type.FullPaytoHash.hash credit_payto_uri; + } + in + let v = + Api.DrainProfitsMessage. + { + debit_account_section; + credit_payto_uri; + wtid; + master_sig; + date; + amount; + } + in + let* s = Api.encode Api.DrainProfitsMessage.jsont v in + let* () = write_file output s in + Ok ()