diff --git a/src/gmc_con.erl b/src/gmc_con.erl index 1c8eae7..a17eb4d 100644 --- a/src/gmc_con.erl +++ b/src/gmc_con.erl @@ -13,9 +13,11 @@ -behavior(gen_server). -export([show_ui/1, open_wallet/2, close_wallet/0, new_wallet/3, import_wallet/3, drop_wallet/2, + selected/1, password/2, refresh/0, nonce/1, spend/2, chain/1, grids/1, sign_mess/1, sign_tx/1, + deploy/2, make_key/6, recover_key/1, mnemonic/1, rename_key/2, drop_key/1, add_node/1, set_sole_node/1]). -export([encrypt/2, decrypt/2]). @@ -41,6 +43,7 @@ {version = 1 :: integer(), window = none :: none | wx:wx_object(), tasks = [] :: [#ui{}], + picked = 0 :: non_neg_integer(), wallet = none :: none | #wallet{}, pass = none :: none | binary(), prefs = #{} :: #{module() := term()}, @@ -104,6 +107,13 @@ drop_wallet(Path, Delete) -> gen_server:cast(?MODULE, {drop_wallet, Path, Delete}). +-spec selected(Index) -> ok + when Index :: pos_integer() | none. + +selected(Index) -> + gen_server:cast(?MODULE, {selected, Index}). + + -spec password(Old, New) -> ok when Old :: none | string(), New :: none | string(). @@ -162,6 +172,17 @@ sign_tx(Request) -> gen_server:cast(?MODULE, {sign_tx, Request}). +-spec deploy(Build, InitArgs) -> Result + when Build :: map(), + InitArgs :: [Arg :: string()], + Result :: {ok, TX_Hash :: clutch:id()} + | {error, Reason}, + Reason :: term(). % FIXME + +deploy(Build, InitArgs) -> + gen_server:call(?MODULE, {deploy, Build, InitArgs}). + + -spec make_key(Type, Size, Name, Seed, Encoding, Transform) -> ok when Type :: {eddsa, ed25519}, Size :: 256, @@ -262,6 +283,7 @@ start_link() -> init(none) -> ok = log(info, "Starting"), + process_flag(sensitive, true), Prefs = read_prefs(), GUI_Prefs = maps:get(gmc_gui, Prefs, #{}), Window = gmc_gui:start_link(GUI_Prefs), @@ -304,6 +326,9 @@ handle_call({save, Module, Prefs}, _, State) -> handle_call({mnemonic, ID}, _, State) -> Response = do_mnemonic(ID, State), {reply, Response, State}; +handle_call({deploy, Build, InitArgs}, _, State) -> + Result = do_deploy(Build, InitArgs, State), + {reply, Result, State}; handle_call(Unexpected, From, State) -> ok = log(warning, "Unexpected call from ~tp: ~tp~n", [From, Unexpected]), {noreply, State}. @@ -337,6 +362,9 @@ handle_cast({import_wallet, Name, Path, Password}, State) -> handle_cast({drop_wallet, Path, Delete}, State) -> NewState = do_drop_wallet(Path, Delete, State), {noreply, NewState}; +handle_cast({selected, Index}, State) -> + NewState = State#s{selected = Index}, + {noreply, NewState}; handle_cast({password, Old, New}, State) -> NewState = do_password(Old, New, State), {noreply, NewState}; @@ -870,6 +898,43 @@ do_mnemonic(ID, #s{wallet = #wallet{keys = Keys}}) -> end. +do_deploy(Build, InitArgs, #s{selected = Index, wallet = #wallet{keys = Keys}}) -> + #key{pair = #s{public = PubKey, secret := SecKey}} = lists:nth(Index, Keys), + case hz:contract_create_built(PubKey, Build, InitArgs) of + {ok, CreateTX} -> do_deploy2(SecKey, CreateTX); + Error -> Error + end. + +do_deploy2(SecKey, CreateTX) -> + case gmc_con:sign(Request) of + {ok, SignedTX} -> do_deploy3(SignedTX); + Error -> Error + end. + +do_deploy3(SignedTX) -> + case hz:post_tx(SignedTX) of + {ok, Data = #{"tx_hash" := TXHash}} -> + ok = tell("Contract deploy TX succeded with: ~p", [TXHash]), + do_deploy4(Data); + {ok, WTF} -> + {error, WTF}; + Error -> + Error + end. + +do_deploy4(#{"tx_hash" := TXHash}) -> + case hz:tx_info(TZHash) of + {ok, {"call_info" := #{"return_type" := "ok", "contract_id" := ConID}}} -> + {contract_id, ConID}; + {error, "Tx not mined"} -> + {tx_hash, TXHash}; + {ok, Reason = {"call_info" := #{"return_type" := "revert"}}} -> + {error, Reason}; + Error -> + Error + end. + + do_rename_key(ID, NewName, State = #s{wallet = W}) -> #wallet{poas = POAs, keys = Keys} = W, A = lists:keyfind(ID, #poa.id, POAs), diff --git a/src/gmc_gui.erl b/src/gmc_gui.erl index 66f1c05..1bbb0e5 100644 --- a/src/gmc_gui.erl +++ b/src/gmc_gui.erl @@ -863,10 +863,12 @@ do_selection(Selected, State = #s{prefs = Prefs, accounts = Accounts, balance = {_, #w{wx = B}}, id = {_, #w{wx = I}}}) when Selected < length(Accounts) -> - #poa{id = ID, balances = Balances} = lists:nth(Selected + 1, Accounts), + OneBasedIndex = Selected + 1, + #poa{id = ID, balances = Balances} = lists:nth(OneBasedIndex, Accounts), [#balance{total = Pucks}] = Balances, ok = wxStaticText:setLabel(I, ID), ok = wxStaticText:setLabel(B, price_to_string(Pucks)), + ok = gmc_con:selected(OneBasedIndex), NewPrefs = maps:put(selected, Selected, Prefs), State#s{prefs = NewPrefs}; do_selection(_, State) -> diff --git a/src/gmc_v_devman.erl b/src/gmc_v_devman.erl index c552dd8..cf8034e 100644 --- a/src/gmc_v_devman.erl +++ b/src/gmc_v_devman.erl @@ -234,15 +234,15 @@ handle_info(Unexpected, State) -> handle_event(E = #wx{event = #wxCommand{type = command_button_clicked}, - id = ID}, + id = ID}, State = #s{buttons = Buttons}) -> NewState = case maps:get(ID, Buttons, undefined) of - #w{name = new} -> new_file(State); - #w{name = open} -> open_file(State); - #w{name = close} -> close_file(State); - #w{name = compile} -> compile(State); - #w{name = Name} -> clicked(State, Name); + #w{name = new} -> new_file(State); + #w{name = open} -> open_file(State); + #w{name = close} -> close_file(State); + #w{name = compile} -> compile(State); + #w{name = Name, wx = Button} -> clicked(State, Name, Button); undefined -> tell("Received message: ~w", [E]), State @@ -279,30 +279,32 @@ terminate(Reason, State) -> %%% Doers -clicked(State = #s{book = {Notebook, Pages}}, Name) -> +clicked(State = #s{book = {Notebook, Pages}}, Name, Button) -> case wxNotebook:getSelection(Notebook) of ?wxNOT_FOUND -> + ok = tell("Inconcievable! No notebook page is selected!"), State; Index -> Page = lists:nth(Index + 1, Pages), - clicked(State, Page, Name) + clicked(State, Page, Name, Button) end. clicked(State, #p{instances = Is, funs = {_, Funs}, builds = Builds}, {<<"init">>, call}) -> - BuildLabel = wxChoice:getStringSelection(Is), - Build = maps:get(BuildLabel, Builds), + Label = wxChoice:getStringSelection(Is), + Build = maps:get(Label, Builds), #f{args = Args} = lists:keyfind(<<"init">>, #f.name, Funs), InitArgs = lists:map(fun get_arg/1, Args), - ok = tell("BuildLabel: ~p~nArgs: ~p~nInitArgs: ~p", [BuildLabel, Args, InitArgs]), -% contract_create_built( - State; + ok = tell("Label: ~p~nArgs: ~p~nInitArgs: ~p", [Label, Args, InitArgs]), + case gmc_con:deploy(Build, InitArgs) of + {contract_id, ConID} -> + {tx_hash, TX_Hash} -> + {error, Reason} -> + ok = tell("Deploy failed with: ~p", [Reason]) + State clicked(State, Page, Name) -> ok = tell("Button: ~p~nPage: ~p", [Name, Page]), State. -get_arg({_, InputField, _}) -> - wxTextCtrl:getValue(InputField). - new_file(State = #s{frame = Frame, j = J, prefs = Prefs}) -> DefaultDir =