Make Contract Calls Great Again #35
+42
-2
@@ -16,7 +16,7 @@
|
|||||||
refresh/0,
|
refresh/0,
|
||||||
nonce/1, spend/1, chain_id/0, grids/1,
|
nonce/1, spend/1, chain_id/0, grids/1,
|
||||||
sign_mess/1, sign_binary/1, sign_tx/1, sign_call/3,
|
sign_mess/1, sign_binary/1, sign_tx/1, sign_call/3,
|
||||||
deploy/1, prompt_call/3, list_calls/0,
|
deploy/1, prompt_call/3, list_calls/0, open_contract/1, show_call/2,
|
||||||
make_key/6, recover_key/1, mnemonic/1, rename_key/2, drop_key/1, list_keys/0,
|
make_key/6, recover_key/1, mnemonic/1, rename_key/2, drop_key/1, list_keys/0,
|
||||||
add_node/1, set_sole_node/1]).
|
add_node/1, set_sole_node/1]).
|
||||||
-export([tic/1, update_balance/2]).
|
-export([tic/1, update_balance/2]).
|
||||||
@@ -210,7 +210,7 @@ deploy(Build) ->
|
|||||||
when FunDef :: {FunName, FunType},
|
when FunDef :: {FunName, FunType},
|
||||||
FunName :: string(),
|
FunName :: string(),
|
||||||
FunType :: call | dryr | init,
|
FunType :: call | dryr | init,
|
||||||
ConID :: none | binary(),
|
ConID :: none | string(),
|
||||||
Build :: map(). % Fixme
|
Build :: map(). % Fixme
|
||||||
|
|
||||||
prompt_call(FunDef, ConID, Build) ->
|
prompt_call(FunDef, ConID, Build) ->
|
||||||
@@ -229,6 +229,28 @@ list_calls() ->
|
|||||||
gen_server:call(?MODULE, list_calls).
|
gen_server:call(?MODULE, list_calls).
|
||||||
|
|
||||||
|
|
||||||
|
-spec open_contract(ConID) -> ok
|
||||||
|
when ConID :: string().
|
||||||
|
%% @doc
|
||||||
|
%% Ask the controller to tell the devman interface to open a deployed contract.
|
||||||
|
%% The controller will start the devman if it isn't already on.
|
||||||
|
|
||||||
|
open_contract(ConID) ->
|
||||||
|
gen_server:cast(?MODULE, {open_contract, ConID}).
|
||||||
|
|
||||||
|
|
||||||
|
-spec show_call(ConID, Info) -> ok
|
||||||
|
when ConID :: string(),
|
||||||
|
Info :: map().
|
||||||
|
%% @doc
|
||||||
|
%% Ask the controller to tell the devman interface to dislpay the result of a call
|
||||||
|
%% to the indicated contract. Opens the contract in question if it isn't alread open.
|
||||||
|
%% Starts the devman if it isn't already running.
|
||||||
|
|
||||||
|
show_call(ConID, Info) ->
|
||||||
|
gen_server:cast(?MODULE, {show_call, ConID, Info}).
|
||||||
|
|
||||||
|
|
||||||
-spec make_key(Type, Size, Name, Seed, Encoding, Transform) -> ok
|
-spec make_key(Type, Size, Name, Seed, Encoding, Transform) -> ok
|
||||||
when Type :: {eddsa, ed25519},
|
when Type :: {eddsa, ed25519},
|
||||||
Size :: 256,
|
Size :: 256,
|
||||||
@@ -499,6 +521,12 @@ handle_cast({rename_key, ID, NewName}, State) ->
|
|||||||
handle_cast({drop_key, ID}, State) ->
|
handle_cast({drop_key, ID}, State) ->
|
||||||
NewState = do_drop_key(ID, State),
|
NewState = do_drop_key(ID, State),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
|
handle_cast({open_contract, ConID}, State) ->
|
||||||
|
NewState = do_open_contract(ConID, State),
|
||||||
|
{noreply, NewState};
|
||||||
|
handle_cast({show_call, ConID, Info}, State) ->
|
||||||
|
NewState = do_show_call(ConID, Info, State),
|
||||||
|
{noreply, NewState};
|
||||||
handle_cast({add_node, New}, State) ->
|
handle_cast({add_node, New}, State) ->
|
||||||
NewState = do_add_node(New, State),
|
NewState = do_add_node(New, State),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
@@ -991,6 +1019,18 @@ do_drop_key(ID, State = #s{wallet = W, wallets = Wallets, pass = Pass}) ->
|
|||||||
State#s{wallet = NewWallet}.
|
State#s{wallet = NewWallet}.
|
||||||
|
|
||||||
|
|
||||||
|
do_open_contract(ConID, State) ->
|
||||||
|
NewState = do_show_ui(gd_v_devman, State),
|
||||||
|
ok = gd_v_devman:open_contract(ConID),
|
||||||
|
NewState.
|
||||||
|
|
||||||
|
|
||||||
|
do_show_call(ConID, Info, State) ->
|
||||||
|
NewState = do_show_ui(gd_v_devman, State),
|
||||||
|
ok = gd_v_devman:call_result(ConID, Info),
|
||||||
|
NewState.
|
||||||
|
|
||||||
|
|
||||||
do_open_wallet(Path, Phrase, State = #s{timer = Timer}) ->
|
do_open_wallet(Path, Phrase, State = #s{timer = Timer}) ->
|
||||||
Pass = pass(Phrase),
|
Pass = pass(Phrase),
|
||||||
case read(Path, Pass) of
|
case read(Path, Pass) of
|
||||||
|
|||||||
+61
-25
@@ -25,6 +25,7 @@
|
|||||||
prefs = #{} :: map(),
|
prefs = #{} :: map(),
|
||||||
con_id = <<"">> :: binary(),
|
con_id = <<"">> :: binary(),
|
||||||
fundef = none :: none | fun_def(),
|
fundef = none :: none | fun_def(),
|
||||||
|
funret = none :: none | term(), % FIXME
|
||||||
build = none :: none | map(),
|
build = none :: none | map(),
|
||||||
args = [] :: [#w{}],
|
args = [] :: [#w{}],
|
||||||
kp = #w{} :: #w{},
|
kp = #w{} :: #w{},
|
||||||
@@ -94,14 +95,14 @@ init({Prefs, FunDef = {FunName, FunIlk}, ConID, Build, Selected, Keys}) ->
|
|||||||
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 = {FunArgs, FunReturn} = maps:get(FunName, FunSpecs),
|
||||||
{CallTypeLabel, ActionLabel} =
|
{CallTypeLabel, ActionLabel} =
|
||||||
case FunIlk 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")}
|
||||||
end,
|
end,
|
||||||
Arity = integer_to_list(length(element(1, FunSpec))),
|
Arity = integer_to_list(length(FunArgs)),
|
||||||
Title = [CallTypeLabel, ": ", ConName, ".", FunName, "/", Arity],
|
Title = [CallTypeLabel, ": ", ConName, ".", FunName, "/", Arity],
|
||||||
Wx = wx:new(),
|
Wx = wx:new(),
|
||||||
Frame = wxFrame:new(Wx, ?wxID_ANY, Title),
|
Frame = wxFrame:new(Wx, ?wxID_ANY, Title),
|
||||||
@@ -128,18 +129,18 @@ init({Prefs, FunDef = {FunName, FunIlk}, ConID, Build, Selected, Keys}) ->
|
|||||||
TX_Info = #w{wx = InfoT} = gd_lib:mono_text(TX_Sz_Box, tx_info, "", Multi),
|
TX_Info = #w{wx = InfoT} = gd_lib:mono_text(TX_Sz_Box, tx_info, "", Multi),
|
||||||
|
|
||||||
_ = wxStaticBoxSizer:add(TX_Sz, HashT, zxw:flags({base, 5})),
|
_ = wxStaticBoxSizer:add(TX_Sz, HashT, zxw:flags({base, 5})),
|
||||||
_ = wxStaticBoxSizer:add(TX_Sz, InfoT, zxw:flags({base, 5})),
|
_ = wxStaticBoxSizer:add(TX_Sz, InfoT, zxw:flags({wide, 5})),
|
||||||
|
|
||||||
ArgSzArgs =
|
ArgSzArgs =
|
||||||
case HasArgs of
|
case HasArgs of
|
||||||
true -> {wide, 5};
|
true -> [{proportion, 2}, {flag, ?wxEXPAND bor ?wxALL}, {border, 5}];
|
||||||
false -> {base, 5}
|
false -> zxw:flags({base, 5})
|
||||||
end,
|
end,
|
||||||
_ = wxSizer:add(MainSz, ArgSz, zxw:flags(ArgSzArgs)),
|
_ = wxSizer:add(MainSz, ArgSz, ArgSzArgs),
|
||||||
_ = wxSizer:add(MainSz, KeySz, zxw:flags({base, 5})),
|
_ = wxSizer:add(MainSz, KeySz, zxw:flags({base, 5})),
|
||||||
_ = wxSizer:add(MainSz, ParamSz, zxw:flags({base, 5})),
|
_ = wxSizer:add(MainSz, ParamSz, zxw:flags({base, 5})),
|
||||||
_ = wxSizer:add(MainSz, ActionBn, zxw:flags({base, 5})),
|
_ = wxSizer:add(MainSz, ActionBn, zxw:flags({base, 5})),
|
||||||
_ = wxSizer:add(MainSz, TX_Sz, zxw:flags({base, 5})),
|
_ = wxSizer:add(MainSz, TX_Sz, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL}, {border, 5}]),
|
||||||
|
|
||||||
_ = wxFrame:setSizer(Frame, MainSz),
|
_ = wxFrame:setSizer(Frame, MainSz),
|
||||||
_ = wxFrame:setSize(Frame, {900, 900}),
|
_ = wxFrame:setSize(Frame, {900, 900}),
|
||||||
@@ -149,7 +150,7 @@ init({Prefs, FunDef = {FunName, FunIlk}, ConID, Build, Selected, Keys}) ->
|
|||||||
true = wxFrame:show(Frame),
|
true = wxFrame:show(Frame),
|
||||||
State =
|
State =
|
||||||
#s{wx = Wx, frame = Frame, j = J, prefs = Prefs,
|
#s{wx = Wx, frame = Frame, j = J, prefs = Prefs,
|
||||||
fundef = FunDef, con_id = ConID, build = Build,
|
fundef = FunDef, funret = FunReturn, con_id = ConID, build = Build,
|
||||||
args = Args, kp = KP, params = Params,
|
args = Args, kp = KP, params = Params,
|
||||||
return = Return, copy = Copy,
|
return = Return, copy = Copy,
|
||||||
action = Action, status = none,
|
action = Action, status = none,
|
||||||
@@ -306,7 +307,7 @@ code_change(_, State, _) ->
|
|||||||
|
|
||||||
retire(State = #s{frame = Frame}) ->
|
retire(State = #s{frame = Frame}) ->
|
||||||
ok = wxWindow:destroy(Frame),
|
ok = wxWindow:destroy(Frame),
|
||||||
{noreply, State}.
|
{stop, normal, State}.
|
||||||
|
|
||||||
|
|
||||||
terminate(Reason, State) ->
|
terminate(Reason, State) ->
|
||||||
@@ -433,10 +434,44 @@ do_call2(State = #s{action = #w{wx = ActionB}}, SignedTX) ->
|
|||||||
do_dry_run(State = #s{action = #w{wx = ActionB}}, ConID, TX) ->
|
do_dry_run(State = #s{action = #w{wx = ActionB}}, ConID, TX) ->
|
||||||
_ = wxButton:disable(ActionB),
|
_ = wxButton:disable(ActionB),
|
||||||
case hz:dry_run(TX) of
|
case hz:dry_run(TX) of
|
||||||
{ok, Result} -> update_info(State#s{tx_info = Result});
|
{ok, Result} -> dry_run2(State#s{tx_info = Result});
|
||||||
Other -> handle_troubling(State, {error, ConID, Other})
|
Other -> handle_troubling(State, {error, ConID, Other})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
dry_run2(State = #s{funret = ReturnType,
|
||||||
|
return = #w{wx = ReturnT},
|
||||||
|
copy = #w{wx = CopyB},
|
||||||
|
tx_data = TXData,
|
||||||
|
tx_info = TXInfo,
|
||||||
|
hash = #w{wx = HashT},
|
||||||
|
info = #w{wx = InfoT}}) ->
|
||||||
|
ReturnV =
|
||||||
|
case TXInfo of
|
||||||
|
#{"results" :=
|
||||||
|
[#{"call_obj" :=
|
||||||
|
#{"return_type" := "revert",
|
||||||
|
"return_value" := ReturnCB},
|
||||||
|
"result" := "ok","type" := "contract_call"}]} ->
|
||||||
|
io_lib:format("Revert: ~ts", [hz:decode_bytearray(ReturnCB, sophia)]);
|
||||||
|
#{"results" :=
|
||||||
|
[#{"call_obj" :=
|
||||||
|
#{"return_type" := "ok",
|
||||||
|
"return_value" := ReturnCB},
|
||||||
|
"result" := "ok","type" := "contract_call"}]} ->
|
||||||
|
hz:decode_bytearray(ReturnCB, {sophia, ReturnType});
|
||||||
|
Other ->
|
||||||
|
io_lib:format("???: ~tp", [Other])
|
||||||
|
end,
|
||||||
|
_ = wxButton:enable(CopyB),
|
||||||
|
FormattedHash = io_lib:format("~tp", [TXData]),
|
||||||
|
FormattedInfo = io_lib:format("~tp", [TXInfo]),
|
||||||
|
ok = wxTextCtrl:setValue(ReturnT, ReturnV),
|
||||||
|
ok = wxTextCtrl:setValue(HashT, FormattedHash),
|
||||||
|
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
||||||
|
State.
|
||||||
|
|
||||||
|
|
||||||
check_tx(State = #s{frame = Frame,
|
check_tx(State = #s{frame = Frame,
|
||||||
j = J,
|
j = J,
|
||||||
fundef = {_, init},
|
fundef = {_, init},
|
||||||
@@ -448,15 +483,22 @@ check_tx(State = #s{frame = Frame,
|
|||||||
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 = tell(info, "Contract deployed: ~p", [Info]),
|
ok = tell(info, "Contract deployed: ~p", [Info]),
|
||||||
|
_ = wxButton:disable(ActionB),
|
||||||
ok = gd_con:open_contract(ConID),
|
ok = gd_con:open_contract(ConID),
|
||||||
ok = wxWindow:destroy(Frame),
|
ok = wxWindow:destroy(Frame),
|
||||||
exit(0);
|
self() ! retire,
|
||||||
|
State;
|
||||||
|
{error, "Tx not mined"} ->
|
||||||
|
ok = wxTextCtrl:setValue(InfoT, J("[Transaction not yet mined.]")),
|
||||||
|
ok = wxButton:setLabel(ActionB, J("Check Deployment Status")),
|
||||||
|
_ = wxButton:enable(ActionB),
|
||||||
|
State;
|
||||||
Other ->
|
Other ->
|
||||||
FormattedJunk = io_lib:format("~tp", [Other]),
|
FormattedJunk = io_lib:format("~tp", [Other]),
|
||||||
ok = wxTextCtrl:setValue(InfoT, FormattedJunk),
|
ok = wxTextCtrl:setValue(InfoT, FormattedJunk),
|
||||||
ok = wxButton:setLabel(ActionB, J("Deploy")),
|
ok = wxButton:setLabel(ActionB, J("Check Depoyment Status")),
|
||||||
_ = wxButton:enable(ActionB),
|
_ = wxButton:enable(ActionB),
|
||||||
State#s{status = none}
|
State
|
||||||
end;
|
end;
|
||||||
check_tx(State = #s{j = J,
|
check_tx(State = #s{j = J,
|
||||||
con_id = ConID,
|
con_id = ConID,
|
||||||
@@ -476,18 +518,18 @@ check_tx(State = #s{j = J,
|
|||||||
_ = wxButton:disable(ActionB),
|
_ = wxButton:disable(ActionB),
|
||||||
ok = wxTextCtrl:setValue(ReturnT, Value),
|
ok = wxTextCtrl:setValue(ReturnT, Value),
|
||||||
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
||||||
ok = gd_con:show_call_result(ConID, Info),
|
ok = gd_con:show_call(ConID, Info),
|
||||||
update_info(State#s{status = included, tx_info = Info});
|
State#s{status = included, tx_info = Info};
|
||||||
{ok, Reason = #{"call_info" := #{"return_type" := "revert"}}} ->
|
{ok, Reason = #{"call_info" := #{"return_type" := "revert"}}} ->
|
||||||
_ = wxButton:enable(CopyB),
|
_ = wxButton:enable(CopyB),
|
||||||
_ = wxButton:disable(ActionB),
|
_ = wxButton:disable(ActionB),
|
||||||
FormattedInfo = io_lib:format("~tp", [Reason]),
|
FormattedInfo = io_lib:format("~tp", [Reason]),
|
||||||
ok = wxTextCtrl:setValue(ReturnT, FormattedInfo), % FIXME
|
ok = wxTextCtrl:setValue(ReturnT, FormattedInfo), % FIXME
|
||||||
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
ok = wxTextCtrl:setValue(InfoT, FormattedInfo),
|
||||||
ok = gd_con:show_call_result(ConID, Reason),
|
ok = gd_con:show_call(ConID, Reason),
|
||||||
State#s{status = rejected, tx_info = Reason};
|
State#s{status = rejected, tx_info = Reason};
|
||||||
{error, "Tx not mined"} ->
|
{error, "Tx not mined"} ->
|
||||||
ok = wxTextCtrl:setValue(InfoT, J("Transaction not yet mined.")),
|
ok = wxTextCtrl:setValue(InfoT, J("[Transaction not yet mined.]")),
|
||||||
ok = wxButton:setLabel(ActionB, J("Check Transaction Status")),
|
ok = wxButton:setLabel(ActionB, J("Check Transaction Status")),
|
||||||
_ = wxButton:enable(ActionB),
|
_ = wxButton:enable(ActionB),
|
||||||
State;
|
State;
|
||||||
@@ -502,16 +544,10 @@ check_tx(State = #s{tx_data = TXData,
|
|||||||
State.
|
State.
|
||||||
|
|
||||||
|
|
||||||
update_info(State = #s{tx_info = TXInfo, return = #w{wx = Return}}) ->
|
|
||||||
Formatted = io_lib:format("TXInfo: ~p~n", [TXInfo]),
|
|
||||||
ok = wxTextCtrl:setValue(Return, Formatted),
|
|
||||||
State.
|
|
||||||
|
|
||||||
|
|
||||||
copy(#s{tx_info = none}) ->
|
copy(#s{tx_info = none}) ->
|
||||||
ok;
|
ok;
|
||||||
copy(#s{return = #w{wx = Return}}) ->
|
copy(#s{return = #w{wx = ReturnT}}) ->
|
||||||
Output = wxTextCtrl:getValue(Return),
|
Output = wxTextCtrl:getValue(ReturnT),
|
||||||
gd_lib:copy_to_clipboard(Output).
|
gd_lib:copy_to_clipboard(Output).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-29
@@ -559,41 +559,16 @@ open_file(State = #s{frame = Frame, j = J, prefs = Prefs}) ->
|
|||||||
|
|
||||||
|
|
||||||
open_hash(State = #s{frame = Frame, j = J}) ->
|
open_hash(State = #s{frame = Frame, j = J}) ->
|
||||||
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Retrieve Contract Source")),
|
Title = J("Retrieve Contract Source"),
|
||||||
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
Label = J("Address Hash"),
|
||||||
AddressSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Address Hash")}]),
|
case zxw_modal_text:show(Frame, Title, [{label, Label}]) of
|
||||||
AddressTx = wxTextCtrl:new(Dialog, ?wxID_ANY),
|
|
||||||
_ = wxSizer:add(AddressSz, AddressTx, zxw:flags(wide)),
|
|
||||||
ButtSz = wxBoxSizer:new(?wxHORIZONTAL),
|
|
||||||
Affirm = wxButton:new(Dialog, ?wxID_OK),
|
|
||||||
Cancel = wxButton:new(Dialog, ?wxID_CANCEL),
|
|
||||||
_ = wxBoxSizer:add(ButtSz, Affirm, zxw:flags(wide)),
|
|
||||||
_ = wxBoxSizer:add(ButtSz, Cancel, zxw:flags(wide)),
|
|
||||||
_ = wxSizer:add(Sizer, AddressSz, zxw:flags(wide)),
|
|
||||||
_ = wxSizer:add(Sizer, ButtSz, zxw:flags(wide)),
|
|
||||||
ok = wxDialog:setSizer(Dialog, Sizer),
|
|
||||||
ok = wxBoxSizer:layout(Sizer),
|
|
||||||
ok = wxDialog:setSize(Dialog, {500, 200}),
|
|
||||||
ok = wxDialog:center(Dialog),
|
|
||||||
ok = wxTextCtrl:setFocus(AddressTx),
|
|
||||||
Choice =
|
|
||||||
case wxDialog:showModal(Dialog) of
|
|
||||||
?wxID_OK ->
|
|
||||||
case wxTextCtrl:getValue(AddressTx) of
|
|
||||||
"" -> cancel;
|
|
||||||
A -> {ok, A}
|
|
||||||
end;
|
|
||||||
?wxID_CANCEL ->
|
|
||||||
cancel
|
|
||||||
end,
|
|
||||||
ok = wxDialog:destroy(Dialog),
|
|
||||||
case Choice of
|
|
||||||
{ok, Address = "ct_" ++ _} -> open_hash2(State, Address);
|
{ok, Address = "ct_" ++ _} -> open_hash2(State, Address);
|
||||||
{ok, Address = "th_" ++ _} -> get_contract_from_tx(State, Address);
|
{ok, Address = "th_" ++ _} -> get_contract_from_tx(State, Address);
|
||||||
{ok, Turd} -> handle_troubling(State, {bad_address, Turd});
|
{ok, Turd} -> handle_troubling(State, {bad_address, Turd});
|
||||||
cancel -> State
|
cancel -> State
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
get_contract_from_tx(State, Address) ->
|
get_contract_from_tx(State, Address) ->
|
||||||
case hz:tx_info(Address) of
|
case hz:tx_info(Address) of
|
||||||
{ok, #{"call_info" := #{"contract_id" := Contract}}} ->
|
{ok, #{"call_info" := #{"contract_id" := Contract}}} ->
|
||||||
|
|||||||
Reference in New Issue
Block a user