Commit e30e8ca0 authored by Michael's avatar Michael

Merge branch 'batch-operations' into 'next'

Background/Ui/Storage/Inpage: handle batch operations

See merge request !45
parents 5aa336cd b1a79ed1
......@@ -4,6 +4,8 @@ open Metal_js
let metal : metal Js.t ref = ref metal
let is_installed = ref false
type operation_type = Transaction | Origination | Delegation
let ready ?not_installed ?timeout f =
ready ?not_installed ?timeout (fun m -> metal := m; is_installed := true; f ())
......@@ -41,8 +43,15 @@ let map_opt f = function
| None -> Js.Optdef.empty
| Some o -> Js.Optdef.return (f o)
let send ~destination ~amount
?fee ?parameter ?entrypoint ?gas_limit ?storage_limit callback =
let send_callback callback res =
match Js.to_bool res##.ok with
| false -> callback Canceled
| true ->
callback
(Ok (Js.to_string (Js.Optdef.get (res##.msg) (fun () -> assert false))))
let make_transaction ~destination ~amount ?fee ?parameter ?entrypoint
?gas_limit ?storage_limit callback =
let destination = Js.string destination in
let amount = Js.string amount in
let fee = map_opt Js.string fee in
......@@ -51,14 +60,8 @@ let send ~destination ~amount
let gas_limit = map_opt (fun x -> Js.string (string_of_int x)) gas_limit in
let storage_limit =
map_opt (fun x -> Js.string (string_of_int x)) storage_limit in
let callback = fun res ->
match Js.to_bool res##.ok with
| false -> callback Canceled
| true ->
callback
(Ok (Js.to_string (Js.Optdef.get (res##.msg) (fun () -> assert false))))
in
!metal##send(object%js
let callback = send_callback callback in
object%js
val mutable dst = destination
val mutable amount = amount
val mutable fee = fee
......@@ -67,10 +70,15 @@ let send ~destination ~amount
val mutable gas_limit_ = gas_limit
val mutable storage_limit_ = storage_limit
method cb res = callback res
end)
end
let send ~destination ~amount
?fee ?parameter ?entrypoint ?gas_limit ?storage_limit callback =
let data = make_transaction ~destination ~amount
?fee ?parameter ?entrypoint ?gas_limit ?storage_limit callback in
!metal##send data
let originate ~balance ?(code=Nocode)
?fee ?gas_limit ?storage_limit callback =
let make_origination ~balance ?(code=Nocode) ?fee ?gas_limit ?storage_limit callback =
let balance = Js.string balance in
let fee = map_opt Js.string fee in
let gas_limit = map_opt (fun x -> Js.string (string_of_int x)) gas_limit in
......@@ -96,7 +104,7 @@ let originate ~balance ?(code=Nocode)
let contract = Js.to_string msg##.contract in
callback (Ok (op_hash, contract))
in
!metal##originate(object%js
(object%js
val mutable balance = balance
val mutable fee = fee
val mutable gas_limit_ = gas_limit
......@@ -107,24 +115,55 @@ let originate ~balance ?(code=Nocode)
method cb res = callback res
end)
let delegate
?fee ?gas_limit ?storage_limit delegate callback =
let originate ~balance ?code ?fee ?gas_limit ?storage_limit callback =
let data =
make_origination ~balance ?code ?fee ?gas_limit ?storage_limit callback in
!metal##originate data
let make_delegation ?fee ?gas_limit ?storage_limit delegate callback =
let delegate = match delegate with None -> Js.undefined | Some d -> Js.def (Js.string d) in
let fee = map_opt Js.string fee in
let gas_limit = map_opt (fun x -> Js.string (string_of_int x)) gas_limit in
let storage_limit =
map_opt (fun x -> Js.string (string_of_int x)) storage_limit in
let callback = fun res ->
match Js.to_bool res##.ok with
| false -> callback Canceled
| true ->
callback
(Ok (Js.to_string (Js.Optdef.get (res##.msg) (fun () -> assert false))))
in
!metal##delegate(object%js
let callback = send_callback callback in
(object%js
val mutable delegate = delegate
val mutable fee = fee
val mutable gas_limit_ = gas_limit
val mutable storage_limit_ = storage_limit
method cb res = callback res
end)
let delegate ?fee ?gas_limit ?storage_limit delegate callback =
let data = make_delegation ?fee ?gas_limit ?storage_limit delegate callback in
!metal##delegate data
let make_batch_operation ?fee ?gas_limit ?storage_limit ?amount
?destination ?parameter ?entrypoint ?balance ?code ?delegate kind =
let o : batch_operation Js.t = Js.Unsafe.obj [||] in
begin match kind, amount, destination, balance, delegate with
| Transaction, Some amount, Some destination, _, _ ->
let tr = make_transaction ~destination ~amount ?fee ?parameter ?entrypoint
?gas_limit ?storage_limit (fun _ -> ()) in
o##.kind := Js.string "transaction";
o##.operation_transaction := Js.def tr
| Origination, _, _, Some balance, _ ->
let ori = make_origination ~balance ?code
?fee ?gas_limit ?storage_limit (fun _ -> ()) in
o##.kind := Js.string "origination";
o##.operation_origination := Js.def ori
| Delegation, _, _, _, Some delegate ->
let del = make_delegation ?fee ?gas_limit ?storage_limit delegate (fun _ -> ()) in
o##.kind := Js.string "delegation";
o##.operation_delegation := Js.def del
| _ -> assert false
end;
o
let batch operations callback =
let callback = send_callback callback in
!metal##batch(object%js
val mutable operations = operations
method cb res = callback res
end)
......@@ -50,6 +50,18 @@ class type delegate_param = object
method cb : send_result Js.t -> unit Js.meth
end
class type batch_operation = object
method kind : Js.js_string Js.t Js.prop
method operation_transaction : send_param Js.t Js.optdef Js.prop
method operation_origination : originate_param Js.t Js.optdef Js.prop
method operation_delegation : delegate_param Js.t Js.optdef Js.prop
end
class type batch_param = object
method operations : batch_operation Js.t Js.js_array Js.t Js.prop
method cb : send_result Js.t -> unit Js.meth
end
class type metal = object
method isEnabled : (bool Js.t -> unit) -> unit Js.meth
method isUnlocked : (bool Js.t -> unit) -> unit Js.meth
......@@ -62,6 +74,7 @@ class type metal = object
method send : send_param Js.t -> unit Js.meth
method originate : originate_param Js.t -> unit Js.meth
method delegate : delegate_param Js.t -> unit Js.meth
method batch : batch_param Js.t -> unit Js.meth
end
let ready ?(not_installed=fun () -> ()) ?(timeout=500.) f =
......
......@@ -24,3 +24,8 @@ let delegate ?fee ?gas_limit ?storage_limit delegate =
Metal.delegate
?fee ?gas_limit ?storage_limit delegate (Lwt.wakeup resolver);
promise
let batch operations =
let (promise, resolver) = Lwt.task () in
Metal.batch operations (Lwt.wakeup resolver);
promise
......@@ -32,9 +32,10 @@ open Storage_types
open Local
open Chrome
type manager_op = notif_manager_info_js t manager_operation_js t
type manager_op = notif_manager_info_js t manager_operation_js
let pending_approved : (string * siteMetadata t) list ref = ref []
let pending_op : (string * manager_op) list ref = ref []
let pending_op : (string * manager_op t) list ref = ref []
let pending_batch : (string * manager_op t js_array t) list ref = ref []
let port_table : (string, Runtime_utils.port t) Hashtbl.t = Hashtbl.create 100
......@@ -235,6 +236,7 @@ let check_list l = List.fold_left (fun acc x -> match acc, x with
| Error e, Ok () | Ok (), Error e -> Error e
| Error e , Error e2 -> Error (e @ e2)
| Ok (), Ok () -> Ok ()) (Ok ()) l
let check_array f a = check_list @@ List.map f @@ Array.to_list @@ to_array a
let check_optdef f x = match Js.Optdef.to_option x with
| None -> Ok ()
| Some x -> f x
......@@ -300,7 +302,7 @@ let check_kind ?kind s =
let unit_optdef x = match Js.Optdef.to_option x with
| None -> undefined
| Some _ -> def ()
let check_manager_operation ?kind (o: manager_op) =
let check_manager_operation ?kind (o: manager_op t) =
check_list [
check_notif_manager_info o##.info;
check_kind ?kind o##.kind;
......@@ -360,7 +362,7 @@ let dispatch (port : Runtime_utils.port t) (msg : message t) =
def_case
(msg##.req##.data)
(fun () -> send port req @@ string "EMPTY DATA")
(fun (data : manager_op) ->
(fun (data : manager_op t) ->
match List.assoc_opt id !pending_op with
| Some _ -> send port req @@ string "ID already used"
| None ->
......@@ -374,6 +376,26 @@ let dispatch (port : Runtime_utils.port t) (msg : message t) =
Hashtbl.add port_table id port;
wrap_handler port req f
)
| "batch" ->
def_case
(msg##.req##.data)
(fun () -> send port req @@ string "EMPTY DATA")
(fun (data : manager_op t js_array t) ->
match List.assoc_opt id !pending_batch with
| Some _ -> send port req @@ string "ID already used"
| None ->
let f () =
match check_array check_manager_operation data with
| Ok () ->
pending_batch := (id, data) :: !pending_batch;
Notification.show_popup_action ~id port (fun () -> ()) meth
| Error errs ->
send_error port req errs
in
Hashtbl.add port_table id port;
wrap_handler port req f
)
| _ -> failwith ("[Background|dispatch] Don't know what to do with : " ^ meth)
else
Js.raise_js_error @@
......@@ -395,13 +417,20 @@ let dispatch_popup port (msg : message t) =
let err = new%js Js.error_constr (string "Can't find origin request") in
send port req err
end
| "get_trdata" | "get_oridata" | "get_dlgdata" ->
| "get_opdata" ->
begin match List.assoc_opt id !pending_op with
| Some opdata -> send port req opdata
| _ ->
let err = new%js Js.error_constr (string "Can't find origin request") in
send port req err
end
| "get_batchdata" ->
begin match List.assoc_opt id !pending_batch with
| Some opdata -> send port req opdata
| _ ->
let err = new%js Js.error_constr (string "Can't find origin request") in
send port req err
end
| "state_changed" -> state_changed ()
| "callback_error_notif" ->
begin match to_def_option req##.data with
......@@ -416,8 +445,8 @@ let dispatch_popup port (msg : message t) =
pending_approved := List.remove_assoc id !pending_approved)
data
notif
| OpNot n as notif ->
if n.not_id = to_string req##.id then
| notif ->
if Mhelpers.notif_id_of_not notif = to_string req##.id then
callback_handler ~callback:(fun _ ->
let obj =
Metal_message.mk_answer
......@@ -452,8 +481,8 @@ let dispatch_popup port (msg : message t) =
remove_window n.not_approv_wid)
data
notif
| OpNot n as notif ->
if n.not_id = to_string req##.id then
| notif ->
if Mhelpers.notif_id_of_not notif = to_string req##.id then
callback_handler
~callback:(fun _ ->
let obj = Metal_message.mk_answer ~src:"background" req##.id data in
......@@ -463,7 +492,7 @@ let dispatch_popup port (msg : message t) =
remove_port port ;
port##postMessage (obj)
end ;
remove_window n.not_wid)
remove_window @@ Mhelpers.notif_wid_of_not notif)
data
notif)
notifs)
......
......@@ -45,18 +45,15 @@ let mk_message ?data ~name ~src id =
let mk_metadata_req src rid =
mk_message ~name:"get_metadata" ~src rid
let mk_tr_req src rid =
mk_message ~name:"get_trdata" ~src rid
let mk_ori_req src rid =
mk_message ~name:"get_oridata" ~src rid
let mk_dlg_req src rid =
mk_message ~name:"get_dlgdata" ~src rid
let mk_op_req src rid =
mk_message ~name:"get_opdata" ~src rid
let mk_state_changed_notif () =
mk_message ~name:"state_changed" ~src:"popup" "-1"
let mk_batch_req src rid =
mk_message ~name:"get_batchdata" ~src rid
let mk_answer ~src id res =
let res =
let obj : response t = Unsafe.obj [||] in
......
......@@ -121,14 +121,20 @@ type notif_manager_info = {
not_mi_msg : string option
}
type notif_op = {
type 'a notif_generic = {
not_origin : string;
not_tsp : string;
not_id : string;
not_wid : int;
not_op : (notif_manager_info, string option manager_details) manager_operation;
not_op : 'a
}
type notif_op =
(notif_manager_info, string option manager_details) manager_operation notif_generic
type notif_batch =
(notif_manager_info, string option manager_details) manager_operation list notif_generic
type notif_app = {
not_approv_id : string ;
not_approv_wid : int ;
......@@ -140,6 +146,7 @@ type notif_app = {
type notif_kind =
| OpNot of notif_op
| BatchNot of notif_batch
| ApprovNot of notif_app
type vault =
......
......@@ -105,10 +105,17 @@ let flatten_block_operations f bos =
let notif_id_of_not = function
| OpNot n -> n.not_id
| BatchNot n -> n.not_id
| ApprovNot n -> n.not_approv_id
let notif_wid_of_not = function
| OpNot n -> n.not_wid
| BatchNot n -> n.not_wid
| ApprovNot n -> n.not_approv_wid
let notif_tsp_of_not = function
| OpNot n -> n.not_tsp
| BatchNot n -> n.not_tsp
| ApprovNot n -> n.not_approv_tsp
let parse_script = function
......@@ -122,6 +129,11 @@ let make_notif_op ~id ~wid ~tsp ~origin not_op =
not_origin = origin; not_tsp = tsp;
not_id = id; not_wid = wid ; not_op }
let make_notif_batch ~id ~wid ~tsp ~origin not_op =
BatchNot {
not_origin = origin; not_tsp = tsp;
not_id = id; not_wid = wid ; not_op }
let make_notif_approv ~id ~wid ~tsp ~icon ~name ~url =
ApprovNot {
not_approv_id = id ;
......
......@@ -277,7 +277,6 @@ module Local = struct
method msg : js_string t optdef prop
end
class type notif_js = object
method kind : js_string t prop
method id : js_string t prop
......@@ -287,6 +286,8 @@ module Local = struct
method msg : js_string t optdef prop
(* Operation *)
method op : notif_manager_info_js t manager_operation_js t prop
(* Batch *)
method batch : notif_manager_info_js t manager_operation_js t js_array t prop
(* Approv *)
method icon : js_string t optdef prop
method name : js_string t prop
......
......@@ -182,6 +182,15 @@ module Of_js = struct
not_op = manager_operation notif_manager_info o##.op
}
let notif_batch (o: notif_js t) =
BatchNot {
not_origin = to_string o##.origin;
not_tsp = to_string o##.tsp;
not_id = to_string o##.id;
not_wid = o##.wid;
not_op = to_list (manager_operation notif_manager_info) o##.batch
}
let notif_app (o: notif_js t) =
let not_approv_id = to_string o##.id in
let not_approv_wid = o##.wid in
......@@ -201,7 +210,10 @@ module Of_js = struct
let notif (o: notif_js t) =
match (to_string o##.kind) with
| "approval" -> notif_app o
| _ -> notif_op o
| "operation" -> notif_op o
| "batch" -> notif_batch o
| _ -> Js_utils.log "storage_reader: type of notification not recognised";
assert false
let acc_notif (o: notif_acc t) =
let notif_acc = to_string o##.acc in
......@@ -417,6 +429,13 @@ module To_js = struct
notif##.id := string n.not_id;
notif##.wid := n.not_wid;
notif##.op := manager_operation notif_manager_info n.not_op;
| BatchNot n ->
notif##.kind := string "batch";
notif##.origin := string n.not_origin;
notif##.tsp := string n.not_tsp;
notif##.id := string n.not_id;
notif##.wid := n.not_wid;
notif##.batch := of_list (manager_operation notif_manager_info) n.not_op;
| ApprovNot n ->
notif##.kind := string "approval";
notif##.id := string n.not_approv_id;
......
......@@ -44,6 +44,8 @@ open Mhelpers
open Async
module Dune = Dune_types_min
let error_callback n code err =
let id = notif_id_of_not n in
let data = object%js
......@@ -282,6 +284,84 @@ let mk_op_page ~(confirm: ?msg:'a Js.t -> Metal_types.notif_kind -> unit)
Js.raise_js_error @@
(new%js Js.error_constr
(Js.string @@ "[Core] TODO op page"))
| BatchNot {not_op; _} ->
let ops = List.fold_left (fun acc -> function
| {mo_det = TraDetails trd; mo_info} -> {mo_det = TraDetails trd; mo_info} :: acc
| {mo_det = OriDetails ord; mo_info} -> {mo_det = OriDetails ord; mo_info} :: acc
| {mo_det = DelDetails del; mo_info} -> {mo_det = DelDetails del; mo_info} :: acc
| {mo_det = RvlDetails rvl; mo_info} -> {mo_det = RvlDetails rvl; mo_info} :: acc
| _ -> acc) [] not_op in
Mrequest.Node.forge_manager_operations ~state ops >>|? 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.NTransaction tr -> Int64.add acc tr.Dune.node_tr_amount
| Dune.NOrigination ori -> Int64.add acc ori.Dune.node_or_balance
| _ -> acc) 0L ops in
let amount_div = make_amount_div amount fee burn in
let tr_src_div = make_tr_div (div []) in
let n, pane_ids, op_panes = List.fold_left (fun (i, ids, panes) op ->
let fee, _gas_limit, storage_limit = Dune_utils.limits_of_operations [ op ] in
let burn = Int64.mul 1000L @@ Z.to_int64 storage_limit in
let amount_div, dst_div = match op with
| Dune.NTransaction tr ->
let dst = tr.Dune.node_tr_dst in
Some (make_amount_div tr.Dune.node_tr_amount fee burn),
Some (div ~a:[ a_class [ Display.d_flex ; Flex.flex_row ;
Flex.align_items_center ; Spacing.mxa;
Spacing.mb2] ] [
blockies ~classes:["account-blockies" ; Spacing.mr3] dst;
span [ txt dst ] ])
| Dune.NOrigination ori ->
Some (make_amount_div ori.Dune.node_or_balance fee burn),
Some (span ~a:[ a_class [ Text.center; Spacing.mb2 ] ] [ txt "New contract" ])
| Dune.NDelegation del ->
Some (make_amount_div 0L fee 0L),
Some (div ~a:[ a_class [ Display.d_flex ; Flex.flex_row ;
Flex.align_items_center ; Spacing.mxa;
Spacing.mb2] ]
(match del.Dune.node_del_delegate with
| None -> [ span [ txt "Unset Delegate" ] ]
| Some delegate ->
[ blockies
~classes:["account-blockies" ; Spacing.mx3]
delegate ;
span [ txt delegate ] ]))
| _ -> None, None in
match amount_div, dst_div with
| Some amount_div, Some dst_div when List.length ids < 10 ->
i+1, (("op_" ^ (string_of_int i)), string_of_int i) :: ids,
div ~a:[ a_class [ Display.d_flex ; Flex.flex_column ] ] (
dst_div :: amount_div) :: panes
| _ -> i+1, ids, panes)
(1, [], []) ops in
let pane_ids, op_panes =
if List.length pane_ids < (n - 1) then
("last_op", "... " ^ (string_of_int n)) :: pane_ids,
div [] :: op_panes
else pane_ids, op_panes in
let pane_ids, op_panes = List.rev pane_ids, List.rev op_panes in
let detail_divs = add_gas_limit gas_limit [] in
let detail_divs = add_storage_limit storage_limit detail_divs in
let tr_info = div ~a:[ a_class [ Text.left ] ] [
ul ~a:[ a_class [ Nav.nav ; Nav.nav_tabs ;
Nav.navbar_dark ; Spacing.px1 ];
a_role [ "tablist" ] ] ([
make_tab_li ~active:true "amount" "Amount";
make_tab_li "details" "Details" ] @
List.map (fun (id, name) -> make_tab_li id name) pane_ids);
div ~a:[ a_class [ Nav.tab_content ] ] ([
make_tab_pane ~active:true "amount" amount_div;
make_tab_pane "details" (List.rev detail_divs) ] @
List.map2 (fun p (id, _)-> make_tab_pane id [ p ]) op_panes pane_ids)
] in
let cb_ok = (fun () ->
Mrequest.Node.send_manager_operations ~state
~error:(fun _c _msg -> ignore @@ deny notif) op_bytes ops
(fun (op_hash, _, _ops) -> confirm ~msg:(Js.string op_hash) notif)
) in
[ tr_src_div ; tr_info ; alert cb_ok ]
| OpNot {not_op; _} ->
match not_op.mo_det with
| TraDetails trd ->
......@@ -1042,7 +1122,7 @@ let update_full_notif refresh state n =
[ p ~a:[ a_class [ "header-info" ; Text.center ] ] [ txt "Approval Request" ] ] ;
match n with
| ApprovNot _ -> update_approve_page refresh state n
| OpNot _ ->
| _ ->
let forging_dom = make_forging_dom () in
replace_fade_id center_id [ forging_dom ] ;
update_op_page refresh state n
......
......@@ -151,7 +151,7 @@ let update_op_page refresh state notif =
let update_full_notif refresh state n = match n with
| ApprovNot _ -> update_approve_page refresh state n
| OpNot _ -> update_op_page refresh state n
| _ -> update_op_page refresh state n
let add_notif_modal notif =
let nid = Mhelpers.notif_id_of_not notif in
......@@ -165,6 +165,7 @@ let add_notif_modal notif =
| OpNot {not_op={mo_det=OriDetails _; _}; _} -> "Origination Request"
| OpNot {not_op={mo_det=ManDetails _; _}; _} -> "Manage Account Request"
| OpNot {not_op={mo_det=RvlDetails _; _}; _} -> "Reveal Request"
| BatchNot _ -> "Batch Request"
in
let nmod =
div ~a:[ a_id id_modal ;
......
......@@ -41,9 +41,7 @@ open Metal_message_types
open Metal_types
let remove_window notif =
let wid = match notif with
| OpNot n -> n.not_wid
| ApprovNot n -> n.not_approv_wid in
let wid = Mhelpers.notif_wid_of_not notif in
Windows.getAll (fun wins ->
List.iter (fun win ->
Js_types.def_case
......@@ -254,7 +252,7 @@ let update_op_page notif =
let make_op_page wid args =
let _, rid = List.find (fun (n, _v) -> n = "req_id") args in
Js_utils.log "make_op_page %s" rid ;
let msg : message Js.t = Metal_message.mk_tr_req "popup" rid in
let msg : message Js.t = Metal_message.mk_op_req "popup" rid in
let info = Runtime_utils.mk_connection_info "popup" in
let port = Runtime.connect ~info () in
port##postMessage msg ;
......@@ -294,9 +292,7 @@ let make_op_page wid args =
notif_acc = acc.pkh) ns).notifs
with Not_found -> [] in
let n_notif = List.length notifs in
if (List.exists
(function ApprovNot n -> n.not_approv_wid = wid
| OpNot n -> n.not_wid = wid)
if (List.exists (fun n -> Mhelpers.notif_wid_of_not n = wid)
notifs) then
update_op_page notif
else
......@@ -313,6 +309,68 @@ let make_op_page wid args =
(* make_error_page *) ()
)
let make_batch_page wid args =
let _, rid = List.find (fun (n, _v) -> n = "req_id") args in
Js_utils.log "make_batch_page %s" rid ;
let msg : message Js.t = Metal_message.mk_batch_req "popup" rid in
let info = Runtime_utils.mk_connection_info "popup" in
let port = Runtime.connect ~info () in
port##postMessage msg ;
Browser_utils.addListener1
(port##.onMessage)
(fun ans ->
Js_utils.js_log ans ;
if msg##.req##.id = ans##.res##.id &&
ans##.src = Js.string "background" then
begin
Storage_reader.get_account (fun (acc, _) -> match acc, Js.Optdef.to_option wid with
| Some acc, Some wid ->
let open Js_types in
let (data :
Storage_types.Local.notif_manager_info_js t
Storage_types.Local.manager_operation_js t js_array t) =
ans##.res##.result in
let tsp = Jsdate.now_tsp () in
let not_op = Storage_utils.(Of_js.(
to_list (manager_operation notif_manager_info) data)) in
let origin = match to_def_option port##.sender with
| None -> "unknown"
| Some sender -> match to_def_option sender##.url with
| None -> "unknown"
| Some origin -> to_string origin in
let notif =
Mhelpers.make_notif_batch
~id:rid
~wid
~tsp
~origin
not_op
in
Storage_reader.get_notifs (fun ns ->
let notifs =
try
(List.find (fun {notif_acc ; _} ->
notif_acc = acc.pkh) ns).notifs
with Not_found -> [] in
let n_notif = List.length notifs in
if (List.exists (fun n -> Mhelpers.notif_wid_of_not n = wid)
notifs) then
update_op_page notif
else
Storage_writer.add_notif
~callback:(fun _ ->
Browser_action.set_badge ~text:(string_of_int @@ n_notif + 1) () ;
update_op_page notif)
acc.pkh
notif)
| _, _ -> ()
) ;
end
else
(* make_error_page *) ()
)
let dispatch id args =
try
let _, typ = List.find (fun (n, _v) -> n = "type") args in
......@@ -321,6 +379,7 @@ let dispatch id args =
| "unlock" -> make_unlock_page ()
| "approve" -> make_approve_page_metadata id args
| "send" | "originate" | "delegate" -> make_op_page id args
| "batch" -> make_batch_page id args
| _ -> Js_utils.log "don't know what to do with %s" typ
with Not_found ->
Js_utils.log "No type argument"
......
......@@ -212,7 +212,7 @@ let update_badge account =
Chrome.Browser_action.set_badge
~text:(if n_notif = 0 then "" else string_of_int n_notif) ())
let notif_kind_to_row network = function
let rec notif_kind_to_row network = function
| OpNot { not_op = {mo_det = TraDetails trd; _}; _ } ->
div ~a:[ a_class [
Display.d_flex; Flex.justify_center ;
......@@ -287,6 +287,10 @@ let notif_kind_to_row network = function
| None -> []
| Some None -> [ span [ txt "unset recovery" ] ]
| Some (Some r) -> [ span [ txt @@ Printf.sprintf "recovery set as %s" r ] ]))
| BatchNot b ->
div ~a:[ a_class [ Display.d_flex; Flex.flex_column ] ] (
List.map (fun not_op -> notif_kind_to_row network
(OpNot {b with not_op})) b.not_op)
| ApprovNot n ->
let icon =
match n.not_approv_icon with None -> "FILLER.PNG" | Some icon -> icon in
......
......@@ -142,22 +142,24 @@ div.d-none * {
font-size: x-large ;
}
#amount .currency img {
.currency img {
height:50px ;
}
#amount .pp-dun {
font-size: xx-large ;
font-size: x-large ;
}
#amount .flex-fill {
text-align: center ;
}
#param .flex-fill .param span,
#script .flex-fill .param span,