Commit 3d06e8c2 authored by Max's avatar Max

Empty account balance with "max" or "maximum" amount

parent 18023982
......@@ -248,6 +248,10 @@ let check_int64 s =
match Int64.of_string_opt s with
| None -> Error ["cannot read int64 " ^ s]
| Some _ -> Ok ()
let check_amount s =
let s2 = String.lowercase_ascii @@ to_string s in
if s2 = "max" || s2 = "maximum" then Ok ()
else check_int64 s
let check_z s =
let s = to_string s in
try ignore @@ Z.of_string s; Ok () with _ -> Error ["cannot read zarith " ^ s]
......@@ -281,7 +285,7 @@ let check_notif_manager_info (o: notif_manager_info_js t) =
let check_transaction_details (o: transaction_details_js t) =
check_list [
check_pkh o##.destination;
check_int64 o##.amount;
check_amount o##.amount;
check_optdef check_parameters o##.parameters ]
let check_origination_details (o: origination_details_js t) =
check_list [
......
......@@ -68,6 +68,11 @@ module ENode = struct
get_node_base_url_lwt state.fo_net >>= fun base ->
Node.forge_manager_operations ~base ~get_pk ~src:state.fo_acc.pkh ops
let forge_empty_account ~state dst =
let get_pk () = Vault.Lwt.pk_of_vault state.fo_acc in
get_node_base_url_lwt state.fo_net >>= fun base ->
Node.forge_empty_account ~base ~get_pk ~src:state.fo_acc.pkh dst
let send_manager_operations ?error ~state op_bytes ops =
async_req ?error (
get_node_base_url_lwt state.fo_net >>= fun base ->
......
......@@ -334,7 +334,7 @@ let make_reveal ?base ~get_pk src =
node_rvl_storage_limit = Z.zero;
node_rvl_metadata = None })
let forge_manager_operations ?base ~get_pk ~src ops =
let forge_manager_operations_base ?base ~get_pk ~src ops =
let limits0 = List.map (fun {Metal_types.mo_info; _} ->
mo_info.Metal_types.not_mi_fee, mo_info.Metal_types.not_mi_gas_limit,
mo_info.Metal_types.not_mi_storage_limit) ops in
......@@ -348,11 +348,42 @@ let forge_manager_operations ?base ~get_pk ~src ops =
get_header ?base () >>=? fun header ->
let head = Misc.unopt_exn header.header_hash in
let chain_id = Misc.unopt_exn header.header_network in
forge_auto_fees ?base ~head ~chain_id ops >>=? fun ops ->
forge_auto_fees ?base ~head ~chain_id ops >>|? fun ops ->
ops, head
let forge_manager_operations ?base ~get_pk ~src ops =
forge_manager_operations_base ?base ~get_pk ~src ops >>=? fun (ops, head) ->
let bytes = Forge.forge_operations_base head (get_ops_bytes_more ops) in
compare_with_remote ?base ~head (get_ops_more ops) bytes >>|? fun bytes ->
bytes, (get_ops_more ops)
let forge_empty_account ?base ~get_pk ~src dst =
if String.length dst < 2 || String.sub dst 0 2 <> "dn" then
return @@ Error (Str_err "Cannot empty an account to a KT1")
else (
get_account_info ?base src >>=? fun info ->
let tr = {
Metal_types.mo_info = {
Metal_types.not_mi_fee = None; not_mi_gas_limit = None;
not_mi_storage_limit = None; not_mi_msg = None};
mo_det = Metal_types.TraDetails {
Metal_types.trd_dst = dst; trd_amount = info.node_ai_balance;
trd_parameters = None}
} in
forge_manager_operations_base ?base ~get_pk ~src [ tr ] >>=? fun (ops, head) ->
let ops = get_ops_more ops in
let fees, _, _ = Dune_utils.limits_of_operations ops in
let fix_amount tr =
{tr with node_tr_amount = Int64.sub tr.node_tr_amount fees} in
let ops = match ops with
| [ rvl; NTransaction tr ] -> [rvl; NTransaction (fix_amount tr)]
| [ NTransaction tr ] -> [ NTransaction (fix_amount tr) ]
| l -> l in
match Forge.forge_operations head ops with
| Error e -> return @@ Error e
| Ok bytes -> return (Ok (bytes, ops))
)
(** Manager KT *)
let manager_kt =
......
......@@ -80,9 +80,13 @@ module Of_js = struct
}
let transaction_details (o: transaction_details_js t) =
let trd_amount =
let x = String.lowercase_ascii @@ to_string o##.amount in
if x = "max" || x = "maximum" then Int64.minus_one
else Int64.of_string x in
TraDetails {
trd_dst = to_string o##.destination ;
trd_amount = Int64.of_string @@ to_string o##.amount ;
trd_amount;
trd_parameters = to_optdef parameters o##.parameters ;
}
......
......@@ -375,14 +375,25 @@ let mk_op_page ~(confirm: ?msg:'a Js.t -> Metal_types.notif_kind -> unit)
trd_dst = acc.pkh;
trd_amount = 0L;
trd_parameters = Some (Some "do", parameters) } } in
Mrequest.Node.forge_manager_operations ~state [ op ]
Mrequest.Node.forge_manager_operations ~state [ op ]
| _ ->
let op = {not_op with mo_det = TraDetails trd} in
Mrequest.Node.forge_manager_operations ~state [ op ]
if trd.trd_amount = Int64.minus_one then (
Mrequest.Node.forge_empty_account ~state trd.trd_dst)
else
let op = {not_op with mo_det = TraDetails trd} in
Mrequest.Node.forge_manager_operations ~state [ op ]
end >>|? fun (op_bytes, ops) ->
let fee, gas_limit, storage_limit = Dune_utils.limits_of_operations ops in
let burn = Int64.mul 1000L @@ Z.to_int64 storage_limit in
let amount = List.fold_left (fun acc op -> match op with
| Dune_types_min.NTransaction {Dune_types_min.node_tr_amount; _} ->
Int64.add acc node_tr_amount
| _ -> acc) 0L ops in
let burn_empty_account = 257_000L in
let amount =
if trd.trd_amount = Int64.minus_one then Int64.sub amount burn_empty_account
else amount in
let burn = Int64.add (Int64.mul 1000L @@ Z.to_int64 storage_limit)
(if trd.trd_amount = Int64.minus_one then burn_empty_account else 0L) in
let tr_dst_div =
div ~a:[ a_class [ Display.d_flex ; Flex.flex_row ;
Flex.align_items_center ; Spacing.mb2 ] ] [
......@@ -396,8 +407,7 @@ let mk_op_page ~(confirm: ?msg:'a Js.t -> Metal_types.notif_kind -> unit)
let detail_divs = add_storage_limit storage_limit detail_divs in
let param_div = add_param trd.trd_parameters [] in
let amount_div = make_amount_div ?manager_kt:acc.manager_kt
trd.trd_amount fee burn in
amount fee burn in
let tr_info = div ~a:[ a_class [ Text.left ] ] [
ul ~a:[ a_class [ Nav.nav ; Nav.nav_tabs ;
Nav.navbar_dark ; Spacing.px1 ];
......
......@@ -137,11 +137,14 @@ let failed_operation ?(classes=[]) ?(kind="operation") ~refresh ~update code msg
update failed_div
let dun_of_str ?(factor=1_000_000.) s =
Int64.of_float @@ (float_of_string s) *. factor
let f = Int64.of_float @@ (float_of_string s) *. factor in
if f < 0L then assert false
else f
let opt_dun_of_str ?(factor=1_000_000.) s =
try Some (Int64.of_float @@ (float_of_string s) *. factor)
with _ -> None
let amount_of_str ?factor s =
let s = String.lowercase_ascii s in
if s = "max" || s = "maximum" then Int64.minus_one
else dun_of_str ?factor s
let fee_with_reveal fee reveal =
if reveal then
......@@ -213,7 +216,7 @@ let get_options_value_origination ?(more=false) () =
let get_transaction_info ?more () =
match check_value check_pkh dest_tr_id,
check_value dun_of_str amount_tr_id,
check_value amount_of_str amount_tr_id,
get_options_value_transaction ?more () with
| Ok trd_dst, Ok trd_amount, Ok (trd_parameters, mo_info) ->
let mo_det = TraDetails {trd_dst; trd_amount; trd_parameters} in
......@@ -221,7 +224,7 @@ let get_transaction_info ?more () =
| _ -> Error ()
let get_origination_info ?more () =
match check_value dun_of_str balance_or_id,
match check_value amount_of_str balance_or_id,
get_options_value_origination ?more () with
| Ok ord_balance, Ok (ord_script, mo_info) ->
let mo_det = OriDetails
......@@ -637,7 +640,7 @@ let handler_transaction_form ?(title="") ~refresh ~update ?(update_anim=update)
short_input ?value:dst_value
~onkeydown:(
onkeydown ~return:send ~clear_invalid dest_tr_id) dest_tr_id "Destination";
short_input ?value:amount_value ~input_type:`Number ~append:dun_str
short_input ?value:amount_value ~append:dun_str
~onkeydown:(onkeydown ~return:send ~clear_invalid amount_tr_id) amount_tr_id "Amount" ]
@ (options_f ~kind ())
@ (contract_call_loading ())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment