Make Contract Calls Great Again #35
+72
-35
@@ -40,8 +40,8 @@
|
|||||||
|
|
||||||
|
|
||||||
-type fun_name() :: string().
|
-type fun_name() :: string().
|
||||||
-type fun_type() :: call | dryr | init.
|
-type fun_ilk() :: call | dryr | init.
|
||||||
-type fun_def() :: {fun_name(), fun_type()}.
|
-type fun_def() :: {fun_name(), fun_ilk()}.
|
||||||
-type param() :: {Label :: string(), Check :: fun(), #w{}}.
|
-type param() :: {Label :: string(), Check :: fun(), #w{}}.
|
||||||
-type status() :: none
|
-type status() :: none
|
||||||
| submitted
|
| submitted
|
||||||
@@ -89,14 +89,14 @@ start_link(Args) ->
|
|||||||
wx_object:start_link({local, ?MODULE}, ?MODULE, Args, []).
|
wx_object:start_link({local, ?MODULE}, ?MODULE, Args, []).
|
||||||
|
|
||||||
|
|
||||||
init({Prefs, FunDef = {FunName, FunType}, ConID, Build, Selected, Keys}) ->
|
init({Prefs, FunDef = {FunName, FunIlk}, ConID, Build, Selected, Keys}) ->
|
||||||
Lang = maps:get(lang, Prefs, en),
|
Lang = maps:get(lang, Prefs, en),
|
||||||
Trans = gd_jt:read_translations(?MODULE),
|
Trans = gd_jt:read_translations(?MODULE),
|
||||||
J = gd_jt:j(Lang, Trans),
|
J = gd_jt:j(Lang, Trans),
|
||||||
{aaci, ConName, FunSpecs, _} = maps:get(aaci, Build),
|
{aaci, ConName, FunSpecs, _} = maps:get(aaci, Build),
|
||||||
FunSpec = maps:get(FunName, FunSpecs),
|
FunSpec = maps:get(FunName, FunSpecs),
|
||||||
{CallTypeLabel, ActionLabel} =
|
{CallTypeLabel, ActionLabel} =
|
||||||
case FunType of
|
case FunIlk of
|
||||||
call -> {J("Contract Call"), J("Submit Call")};
|
call -> {J("Contract Call"), J("Submit Call")};
|
||||||
dryr -> {J("Dry Run"), J("Submit Dry Run")};
|
dryr -> {J("Dry Run"), J("Submit Dry Run")};
|
||||||
init -> {J("Deploy"), J("Deploy")}
|
init -> {J("Deploy"), J("Deploy")}
|
||||||
@@ -115,7 +115,7 @@ init({Prefs, FunDef = {FunName, FunType}, ConID, Build, Selected, Keys}) ->
|
|||||||
ok = wxChoice:setSelection(KeyPicker, ZeroBasedSelected),
|
ok = wxChoice:setSelection(KeyPicker, ZeroBasedSelected),
|
||||||
_ = wxStaticBoxSizer:add(KeySz, KeyPicker, zxw:flags(wide)),
|
_ = wxStaticBoxSizer:add(KeySz, KeyPicker, zxw:flags(wide)),
|
||||||
|
|
||||||
{ArgSz, Args, Return, Copy, HasArgs} = call_arg_sizer(Frame, J, FunType, FunSpec),
|
{ArgSz, Args, Return, Copy, HasArgs} = call_arg_sizer(Frame, J, FunIlk, FunSpec),
|
||||||
{ParamSz, Params} = call_param_sizer(Frame, J),
|
{ParamSz, Params} = call_param_sizer(Frame, J),
|
||||||
|
|
||||||
Action = #w{wx = ActionBn} = gd_lib:button(Frame, ActionLabel),
|
Action = #w{wx = ActionBn} = gd_lib:button(Frame, ActionLabel),
|
||||||
@@ -157,11 +157,11 @@ init({Prefs, FunDef = {FunName, FunType}, ConID, Build, Selected, Keys}) ->
|
|||||||
{Frame, State}.
|
{Frame, State}.
|
||||||
|
|
||||||
|
|
||||||
call_arg_sizer(Frame, J, {CallArgs, FunType, ReturnType}) ->
|
call_arg_sizer(Frame, J, FunIlk, {CallArgs, ReturnType}) ->
|
||||||
SpecSz = wxStaticBoxSizer:new(?wxVERTICAL, Frame, [{label, J("Function Spec")}]),
|
SpecSz = wxStaticBoxSizer:new(?wxVERTICAL, Frame, [{label, J("Function Spec")}]),
|
||||||
SpecBox = wxStaticBoxSizer:getStaticBox(SpecSz),
|
SpecBox = wxStaticBoxSizer:getStaticBox(SpecSz),
|
||||||
{CallSz, CallControls, HasArgs} = call_sizer(SpecBox, J, CallArgs),
|
{CallSz, CallControls, HasArgs} = call_sizer(SpecBox, J, CallArgs),
|
||||||
{ReturnSz, Return, Copy} = return_sizer(SpecBox, J, FunType, ReturnType),
|
{ReturnSz, Return, Copy} = return_sizer(SpecBox, J, FunIlk, ReturnType),
|
||||||
_ = wxStaticBoxSizer:add(SpecSz, CallSz, zxw:flags({wide, 5})),
|
_ = wxStaticBoxSizer:add(SpecSz, CallSz, zxw:flags({wide, 5})),
|
||||||
_ = wxStaticBoxSizer:add(SpecSz, ReturnSz, zxw:flags({base, 5})),
|
_ = wxStaticBoxSizer:add(SpecSz, ReturnSz, zxw:flags({base, 5})),
|
||||||
{SpecSz, CallControls, Return, Copy, HasArgs}.
|
{SpecSz, CallControls, Return, Copy, HasArgs}.
|
||||||
@@ -195,21 +195,22 @@ call_sizer(Parent, J, CallArgs) ->
|
|||||||
Controls = lists:map(AddArg, CallArgs),
|
Controls = lists:map(AddArg, CallArgs),
|
||||||
{CallSz, Controls, true}.
|
{CallSz, Controls, true}.
|
||||||
|
|
||||||
return_sizer(Parent, J, FunType, ReturnType) ->
|
return_sizer(Parent, J, FunIlk, ReturnType) ->
|
||||||
TypeLabel =
|
IlkLabel =
|
||||||
case FunType =:= init of
|
case FunIlk =:= init of
|
||||||
false -> textify(ReturnType);
|
false -> textify(ReturnType);
|
||||||
true -> J("Contract Address")
|
true -> J("Contract Address")
|
||||||
end,
|
end,
|
||||||
ReturnSz = wxStaticBoxSizer:new(?wxVERTICAL, Parent, [{label, J("Return Type")}]),
|
ReturnSz = wxStaticBoxSizer:new(?wxVERTICAL, Parent, [{label, J("Return Type")}]),
|
||||||
ReturnSzBox = wxStaticBoxSizer:getStaticBox(ReturnSz),
|
ReturnSzBox = wxStaticBoxSizer:getStaticBox(ReturnSz),
|
||||||
ReturnLabel = wxStaticText:new(ReturnSzBox, ?wxID_ANY, TypeLabel),
|
ReturnLabel = wxStaticText:new(ReturnSzBox, ?wxID_ANY, IlkLabel),
|
||||||
Single = [{style, ?wxTE_READONLY}],
|
Single = [{style, ?wxTE_READONLY}],
|
||||||
Return = #w{wx = ReturnTx} = gd_lib:mono_text(ReturnSzBox, return, "", Single),
|
Return = #w{wx = ReturnTx} = gd_lib:mono_text(ReturnSzBox, return, "", Single),
|
||||||
Copy = #w{wx = CopyBn} = gd_lib:button(ReturnSzBox, J("Copy")),
|
Copy = #w{wx = CopyB} = gd_lib:button(ReturnSzBox, J("Copy")),
|
||||||
|
_ = wxButton:disable(CopyB),
|
||||||
_ = wxStaticBoxSizer:add(ReturnSz, ReturnLabel, zxw:flags({wide, 5})),
|
_ = wxStaticBoxSizer:add(ReturnSz, ReturnLabel, zxw:flags({wide, 5})),
|
||||||
_ = wxStaticBoxSizer:add(ReturnSz, ReturnTx, zxw:flags({wide, 5})),
|
_ = wxStaticBoxSizer:add(ReturnSz, ReturnTx, zxw:flags({wide, 5})),
|
||||||
_ = wxStaticBoxSizer:add(ReturnSz, CopyBn, zxw:flags({wide, 5})),
|
_ = wxStaticBoxSizer:add(ReturnSz, CopyB, zxw:flags({wide, 5})),
|
||||||
{ReturnSz, Return, Copy}.
|
{ReturnSz, Return, Copy}.
|
||||||
|
|
||||||
|
|
||||||
@@ -253,6 +254,9 @@ call_param_sizer(Frame, J) ->
|
|||||||
{ParamSz, Params}.
|
{ParamSz, Params}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%%% Spine
|
||||||
|
|
||||||
handle_call(tx_hash, _, State) ->
|
handle_call(tx_hash, _, State) ->
|
||||||
TXHash = do_tx_hash(State),
|
TXHash = do_tx_hash(State),
|
||||||
{reply, TXHash, State};
|
{reply, TXHash, State};
|
||||||
@@ -270,6 +274,8 @@ handle_cast(Unexpected, State) ->
|
|||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
|
|
||||||
|
handle_info(retire, State) ->
|
||||||
|
retire(State);
|
||||||
handle_info(Unexpected, State) ->
|
handle_info(Unexpected, State) ->
|
||||||
ok = log(warning, "Unexpected info: ~tp~n", [Unexpected]),
|
ok = log(warning, "Unexpected info: ~tp~n", [Unexpected]),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
@@ -287,9 +293,8 @@ handle_event(#wx{event = #wxCommand{type = command_button_clicked}, id = ID},
|
|||||||
State = #s{copy = #w{id = ID}}) ->
|
State = #s{copy = #w{id = ID}}) ->
|
||||||
ok = copy(State),
|
ok = copy(State),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_event(#wx{event = #wxClose{}}, State = #s{frame = Frame}) ->
|
handle_event(#wx{event = #wxClose{}}, State) ->
|
||||||
ok = wxWindow:destroy(Frame),
|
retire(State);
|
||||||
{noreply, State};
|
|
||||||
handle_event(Event, State) ->
|
handle_event(Event, State) ->
|
||||||
ok = tell(info, "Unexpected event ~tp State: ~tp~n", [Event, State]),
|
ok = tell(info, "Unexpected event ~tp State: ~tp~n", [Event, State]),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
@@ -299,11 +304,19 @@ code_change(_, State, _) ->
|
|||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
|
|
||||||
|
retire(State = #s{frame = Frame}) ->
|
||||||
|
ok = wxWindow:destroy(Frame),
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
|
||||||
terminate(Reason, State) ->
|
terminate(Reason, State) ->
|
||||||
ok = log(info, "Reason: ~tp, State: ~tp", [Reason, State]),
|
ok = log(info, "Reason: ~tp, State: ~tp", [Reason, State]),
|
||||||
wx:destroy().
|
wx:destroy().
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%%% Handlers
|
||||||
|
|
||||||
handle_troubling(State = #s{frame = Frame}, Info) ->
|
handle_troubling(State = #s{frame = Frame}, Info) ->
|
||||||
ok = wxFrame:raise(Frame),
|
ok = wxFrame:raise(Frame),
|
||||||
ok = zxw:show_message(Frame, Info),
|
ok = zxw:show_message(Frame, Info),
|
||||||
@@ -340,12 +353,12 @@ prep_call4(State = #s{fundef = {"init", init}, build = Build}, ChainID, Params,
|
|||||||
{ok, CreateTX} -> deploy(State, ChainID, CallerID, CreateTX);
|
{ok, CreateTX} -> deploy(State, ChainID, CallerID, CreateTX);
|
||||||
Error -> handle_troubling(State, Error)
|
Error -> handle_troubling(State, Error)
|
||||||
end;
|
end;
|
||||||
prep_call4(State = #s{fundef = {Name, Type}, con_id = ConID, build = Build}, ChainID, Params, Args) ->
|
prep_call4(State = #s{fundef = {Name, Ilk}, con_id = ConID, build = Build}, ChainID, Params, Args) ->
|
||||||
{CallerID, Nonce, TTL, Gas, GP, Amount} = Params,
|
{CallerID, Nonce, TTL, Gas, GP, Amount} = Params,
|
||||||
AACI = maps:get(aaci, Build),
|
AACI = maps:get(aaci, Build),
|
||||||
case hz:contract_call(CallerID, Nonce, Gas, GP, Amount, TTL, AACI, ConID, Name, Args) of
|
case hz:contract_call(CallerID, Nonce, Gas, GP, Amount, TTL, AACI, ConID, Name, Args) of
|
||||||
{ok, UnsignedTX} ->
|
{ok, UnsignedTX} ->
|
||||||
case Type of
|
case Ilk of
|
||||||
call -> do_call(State, ChainID, CallerID, UnsignedTX);
|
call -> do_call(State, ChainID, CallerID, UnsignedTX);
|
||||||
dryr -> do_dry_run(State, ConID, UnsignedTX)
|
dryr -> do_dry_run(State, ConID, UnsignedTX)
|
||||||
end;
|
end;
|
||||||
@@ -388,7 +401,7 @@ deploy(State, ChainID, CallerID, CreateTX) ->
|
|||||||
Error -> handle_troubling(State, Error)
|
Error -> handle_troubling(State, Error)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
deploy2(State = #s{hash = #w{wx = HashT}, action = #w{wx = ActionB}}, SignedTX) ->
|
deploy2(State = #s{j = J, hash = #w{wx = HashT}, action = #w{wx = ActionB}}, SignedTX) ->
|
||||||
case hz:post_tx(SignedTX) of
|
case hz:post_tx(SignedTX) of
|
||||||
{ok, Data = #{"tx_hash" := TXHash}} ->
|
{ok, Data = #{"tx_hash" := TXHash}} ->
|
||||||
_ = wxButton:disable(ActionB),
|
_ = wxButton:disable(ActionB),
|
||||||
@@ -411,7 +424,6 @@ do_call(State, ChainID, CallerID, UnsignedTX) ->
|
|||||||
|
|
||||||
do_call2(State = #s{action = #w{wx = ActionB}}, SignedTX) ->
|
do_call2(State = #s{action = #w{wx = ActionB}}, SignedTX) ->
|
||||||
_ = wxButton:disable(ActionB),
|
_ = wxButton:disable(ActionB),
|
||||||
ok = wxButton:setLabel(ActionB, J("Check Transaction Status")),
|
|
||||||
case hz:post_tx(SignedTX) of
|
case hz:post_tx(SignedTX) of
|
||||||
{ok, Data} -> check_tx(State#s{tx_data = Data, status = submitted});
|
{ok, Data} -> check_tx(State#s{tx_data = Data, status = submitted});
|
||||||
Error -> handle_troubling(State, Error)
|
Error -> handle_troubling(State, Error)
|
||||||
@@ -425,41 +437,66 @@ do_dry_run(State = #s{action = #w{wx = ActionB}}, ConID, TX) ->
|
|||||||
Other -> handle_troubling(State, {error, ConID, Other})
|
Other -> handle_troubling(State, {error, ConID, Other})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
check_tx(State = #s{fundef = {_, init},
|
check_tx(State = #s{frame = Frame,
|
||||||
|
j = J,
|
||||||
|
fundef = {_, init},
|
||||||
tx_data = #{"tx_hash" := TXHash},
|
tx_data = #{"tx_hash" := TXHash},
|
||||||
tx_info = none,
|
tx_info = none,
|
||||||
return = #w{wx = ReturnT},
|
|
||||||
status = submitted,
|
status = submitted,
|
||||||
action = #w{wx = ActionB},
|
action = #w{wx = ActionB},
|
||||||
info = #w{wx = InfoT}}) ->
|
info = #w{wx = InfoT}}) ->
|
||||||
case hz:tx_info(TXHash) of
|
case hz:tx_info(TXHash) of
|
||||||
{ok, Info = #{"call_info" := #{"return_type" := "ok", "contract_id" := ConID}}} ->
|
{ok, Info = #{"call_info" := #{"return_type" := "ok", "contract_id" := ConID}}} ->
|
||||||
ok = wxTextCtrl:setValue(ReturnT, ConID),
|
ok = tell(info, "Contract deployed: ~p", [Info]),
|
||||||
ok = gd_v_devman:open_contract(ConID),
|
ok = gd_con:open_contract(ConID),
|
||||||
FormattedInfo = io_lib:fomat("~tw", [Info]),
|
ok = wxWindow:destroy(Frame),
|
||||||
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
exit(0);
|
||||||
|
Other ->
|
||||||
check_tx(State = #s{tx_data = #{"tx_hash" := TXHash},
|
FormattedJunk = io_lib:format("~tp", [Other]),
|
||||||
|
ok = wxTextCtrl:setValue(InfoT, FormattedJunk),
|
||||||
|
ok = wxButton:setLabel(ActionB, J("Deploy")),
|
||||||
|
_ = wxButton:enable(ActionB),
|
||||||
|
State#s{status = none}
|
||||||
|
end;
|
||||||
|
check_tx(State = #s{j = J,
|
||||||
|
con_id = ConID,
|
||||||
|
tx_data = #{"tx_hash" := TXHash},
|
||||||
tx_info = none,
|
tx_info = none,
|
||||||
status = submitted,
|
status = submitted,
|
||||||
|
return = #w{wx = ReturnT},
|
||||||
|
copy = #w{wx = CopyB},
|
||||||
action = #w{wx = ActionB},
|
action = #w{wx = ActionB},
|
||||||
info = #w{wx = InfoT}}) ->
|
info = #w{wx = InfoT}}) ->
|
||||||
case hz:tx_info(TXHash) of
|
case hz:tx_info(TXHash) of
|
||||||
{ok, Info = #{"call_info" := #{"return_type" := "ok",
|
{ok, Info = #{"call_info" := #{"return_type" := "ok",
|
||||||
"contract_id" := ConID,
|
"contract_id" := ConID,
|
||||||
"return_value" := Value}}} ->
|
"return_value" := Value}}} ->
|
||||||
FormattedInfo = io_lib:fomat("~tw", [Info]),
|
FormattedInfo = io_lib:fomat("~tp", [Info]),
|
||||||
|
_ = wxButton:enable(CopyB),
|
||||||
|
_ = wxButton:disable(ActionB),
|
||||||
|
ok = wxTextCtrl:setValue(ReturnT, Value),
|
||||||
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
||||||
ok = gd_v_devman:open_contract(ConID),
|
ok = gd_con:show_call_result(ConID, Info),
|
||||||
update_info(State#s{tx_info = Info});
|
update_info(State#s{status = included, tx_info = Info});
|
||||||
{error, "Tx not mined"} ->
|
|
||||||
handle_troubling(State, {error, not_mined});
|
|
||||||
{ok, Reason = #{"call_info" := #{"return_type" := "revert"}}} ->
|
{ok, Reason = #{"call_info" := #{"return_type" := "revert"}}} ->
|
||||||
handle_troubling(State, {error, Reason});
|
_ = wxButton:enable(CopyB),
|
||||||
|
_ = wxButton:disable(ActionB),
|
||||||
|
FormattedInfo = io_lib:format("~tp", [Reason]),
|
||||||
|
ok = wxTextCtrl:setValue(ReturnT, FormattedInfo), % FIXME
|
||||||
|
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
||||||
|
ok = gd_con:show_call_result(ConID, Reason),
|
||||||
|
State#s{status = rejected, tx_info = Reason};
|
||||||
|
{error, "Tx not mined"} ->
|
||||||
|
ok = wxTextCtrl:setValue(InfoT, J("Transaction not yet mined.")),
|
||||||
|
ok = wxButton:setLabel(ActionB, J("Check Transaction Status")),
|
||||||
|
_ = wxButton:enable(ActionB),
|
||||||
|
State;
|
||||||
Error ->
|
Error ->
|
||||||
handle_troubling(State, Error)
|
handle_troubling(State, Error)
|
||||||
end;
|
end;
|
||||||
check_tx(State = #s{tx_data = TXData}) ->
|
check_tx(State = #s{tx_data = TXData,
|
||||||
|
action = #w{wx = ActionB}}) ->
|
||||||
|
_ = wxButton:disable(ActionB),
|
||||||
tell(info, "TXData: ~p", [TXData]),
|
tell(info, "TXData: ~p", [TXData]),
|
||||||
ok = tell("Nothing to check"),
|
ok = tell("Nothing to check"),
|
||||||
State.
|
State.
|
||||||
|
|||||||
Reference in New Issue
Block a user