contract #5
@ -2,8 +2,8 @@
|
|||||||
[{description,"A desktop client for the Gajumaru network of blockchain networks"},
|
[{description,"A desktop client for the Gajumaru network of blockchain networks"},
|
||||||
{registered,[]},
|
{registered,[]},
|
||||||
{included_applications,[]},
|
{included_applications,[]},
|
||||||
{applications,[stdlib,kernel]},
|
{applications,[stdlib,kernel,sasl,ssl]},
|
||||||
{vsn,"0.1.4"},
|
{vsn,"0.3.0"},
|
||||||
{modules,[clutch,gmc_con,gmc_grids,gmc_gui,gmc_jt,
|
{modules,[clutch,gmc_con,gmc_grids,gmc_gui,gmc_jt,
|
||||||
gmc_key_master,gmc_sup,gmc_v,gmc_v_netman,
|
gmc_key_master,gmc_sup,gmc_v,gmc_v_netman,
|
||||||
gmc_v_wallman]},
|
gmc_v_wallman]},
|
||||||
|
@ -60,7 +60,9 @@
|
|||||||
-record(tx,
|
-record(tx,
|
||||||
{id = none :: none | clutch:id(),
|
{id = none :: none | clutch:id(),
|
||||||
amount = 0 :: non_neg_integer(),
|
amount = 0 :: non_neg_integer(),
|
||||||
type = spend :: spend | atom()}).
|
type = spend :: atom(),
|
||||||
|
status = submitted :: submitted | mined | rejected | failed,
|
||||||
|
meta = "" :: string()}).
|
||||||
|
|
||||||
|
|
||||||
-record(spend_tx,
|
-record(spend_tx,
|
||||||
@ -75,13 +77,14 @@
|
|||||||
|
|
||||||
|
|
||||||
-record(wallet,
|
-record(wallet,
|
||||||
{version = 1 :: integer(),
|
{version = 2 :: integer(),
|
||||||
name = "" :: string(),
|
name = "" :: string(),
|
||||||
poas = [] :: [#poa{}],
|
poas = [] :: [#poa{}],
|
||||||
keys = [] :: [#key{}],
|
keys = [] :: [#key{}],
|
||||||
chain_id = <<"groot.devnet">> :: binary(),
|
chain_id = <<"groot.devnet">> :: binary(),
|
||||||
endpoint = #node{} :: #node{},
|
endpoint = #node{} :: #node{},
|
||||||
nets = [#net{}] :: [#net{}]}).
|
nets = [#net{}] :: [#net{}],
|
||||||
|
txs = #{} :: clutch:key_txs()}).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
|
|
||||||
-module(clutch).
|
-module(clutch).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-behavior(application).
|
-behavior(application).
|
||||||
-author("Craig Everett <craigeverett@qpq.swiss>").
|
-author("Craig Everett <craigeverett@qpq.swiss>").
|
||||||
-copyright("QPQ AG <info@qpq.swiss>").
|
-copyright("QPQ AG <info@qpq.swiss>").
|
||||||
@ -12,7 +12,7 @@
|
|||||||
-export([ts/0]).
|
-export([ts/0]).
|
||||||
-export([start/2, stop/1]).
|
-export([start/2, stop/1]).
|
||||||
|
|
||||||
-export_type([id/0, key/0, poa/0, tx/0, ts/0]).
|
-export_type([id/0, key/0, poa/0, tx/0, ts/0, key_txs/0]).
|
||||||
|
|
||||||
-include("$zx_include/zx_logger.hrl").
|
-include("$zx_include/zx_logger.hrl").
|
||||||
-include("gmc.hrl").
|
-include("gmc.hrl").
|
||||||
@ -23,6 +23,8 @@
|
|||||||
-type poa() :: #poa{}.
|
-type poa() :: #poa{}.
|
||||||
-type tx() :: #tx{}.
|
-type tx() :: #tx{}.
|
||||||
-type ts() :: integer().
|
-type ts() :: integer().
|
||||||
|
-type chain_txs() :: #{ChainID :: binary() := [tx()]}.
|
||||||
|
-type key_txs() :: #{id() := {{LastCheck :: ts(), mdw | node}, chain_txs()}}.
|
||||||
|
|
||||||
|
|
||||||
ts() ->
|
ts() ->
|
||||||
@ -55,9 +57,9 @@ start(normal, _Args) ->
|
|||||||
ok = tell(error, "DANGER! This node is in distributed mode!"),
|
ok = tell(error, "DANGER! This node is in distributed mode!"),
|
||||||
init:stop(1)
|
init:stop(1)
|
||||||
end,
|
end,
|
||||||
ok = application:ensure_started(sasl),
|
|
||||||
ok = application:ensure_started(hakuzaru),
|
ok = application:ensure_started(hakuzaru),
|
||||||
ok = application:ensure_started(zxwidgets),
|
ok = application:ensure_started(zxwidgets),
|
||||||
|
ok = application:ensure_started(sophia),
|
||||||
gmc_sup:start_link().
|
gmc_sup:start_link().
|
||||||
|
|
||||||
|
|
||||||
|
201
src/gmc_con.erl
201
src/gmc_con.erl
@ -1,11 +1,9 @@
|
|||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Clutch Controller
|
%%% GajuDesk Controller
|
||||||
%%%
|
|
||||||
%%% This process is a in charge of maintaining the program's state.
|
|
||||||
%%% @end
|
%%% @end
|
||||||
|
|
||||||
-module(gmc_con).
|
-module(gmc_con).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-author("Craig Everett <craigeverett@qpq.swiss>").
|
-author("Craig Everett <craigeverett@qpq.swiss>").
|
||||||
-copyright("QPQ AG <info@qpq.swiss>").
|
-copyright("QPQ AG <info@qpq.swiss>").
|
||||||
-license("GPL-3.0-or-later").
|
-license("GPL-3.0-or-later").
|
||||||
@ -13,10 +11,12 @@
|
|||||||
-behavior(gen_server).
|
-behavior(gen_server).
|
||||||
-export([show_ui/1,
|
-export([show_ui/1,
|
||||||
open_wallet/2, close_wallet/0, new_wallet/3, import_wallet/3, drop_wallet/2,
|
open_wallet/2, close_wallet/0, new_wallet/3, import_wallet/3, drop_wallet/2,
|
||||||
|
selected/1,
|
||||||
password/2,
|
password/2,
|
||||||
refresh/0,
|
refresh/0,
|
||||||
nonce/1, spend/2, chain/1, grids/1, sign_mess/1, sign_tx/1,
|
nonce/1, spend/2, chain/1, grids/1, sign_mess/1, sign_tx/1, sign_call/3, dry_run/2,
|
||||||
make_key/6, recover_key/1, mnemonic/1, rename_key/2, drop_key/1,
|
deploy/3,
|
||||||
|
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([encrypt/2, decrypt/2]).
|
-export([encrypt/2, decrypt/2]).
|
||||||
-export([save/2]).
|
-export([save/2]).
|
||||||
@ -41,6 +41,7 @@
|
|||||||
{version = 1 :: integer(),
|
{version = 1 :: integer(),
|
||||||
window = none :: none | wx:wx_object(),
|
window = none :: none | wx:wx_object(),
|
||||||
tasks = [] :: [#ui{}],
|
tasks = [] :: [#ui{}],
|
||||||
|
selected = 0 :: non_neg_integer(),
|
||||||
wallet = none :: none | #wallet{},
|
wallet = none :: none | #wallet{},
|
||||||
pass = none :: none | binary(),
|
pass = none :: none | binary(),
|
||||||
prefs = #{} :: #{module() := term()},
|
prefs = #{} :: #{module() := term()},
|
||||||
@ -104,6 +105,13 @@ drop_wallet(Path, Delete) ->
|
|||||||
gen_server:cast(?MODULE, {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
|
-spec password(Old, New) -> ok
|
||||||
when Old :: none | string(),
|
when Old :: none | string(),
|
||||||
New :: none | string().
|
New :: none | string().
|
||||||
@ -162,6 +170,35 @@ sign_tx(Request) ->
|
|||||||
gen_server:cast(?MODULE, {sign_tx, Request}).
|
gen_server:cast(?MODULE, {sign_tx, Request}).
|
||||||
|
|
||||||
|
|
||||||
|
-spec sign_call(ConID, PubKey, TX) -> ok
|
||||||
|
when ConID :: clutch:id(),
|
||||||
|
PubKey :: clutch:id(),
|
||||||
|
TX :: binary().
|
||||||
|
|
||||||
|
sign_call(ConID, PubKey, TX) ->
|
||||||
|
gen_server:cast(?MODULE, {sign_call, ConID, PubKey, TX}).
|
||||||
|
|
||||||
|
|
||||||
|
-spec dry_run(ConID, TX) -> ok
|
||||||
|
when ConID :: clutch:id(),
|
||||||
|
TX :: binary().
|
||||||
|
|
||||||
|
dry_run(ConID, TX) ->
|
||||||
|
gen_server:cast(?MODULE, {dry_run, ConID, TX}).
|
||||||
|
|
||||||
|
|
||||||
|
-spec deploy(CreatorID, Build, InitArgs) -> Result
|
||||||
|
when CreatorID :: clutch:id(),
|
||||||
|
Build :: map(),
|
||||||
|
InitArgs :: [Arg :: string()],
|
||||||
|
Result :: {ok, TX_Hash :: clutch:id()}
|
||||||
|
| {error, Reason},
|
||||||
|
Reason :: term(). % FIXME
|
||||||
|
|
||||||
|
deploy(CreatorID, Build, InitArgs) ->
|
||||||
|
gen_server:cast(?MODULE, {deploy, CreatorID, Build, InitArgs}).
|
||||||
|
|
||||||
|
|
||||||
-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,
|
||||||
@ -211,6 +248,14 @@ drop_key(ID) ->
|
|||||||
gen_server:cast(?MODULE, {drop_key, ID}).
|
gen_server:cast(?MODULE, {drop_key, ID}).
|
||||||
|
|
||||||
|
|
||||||
|
-spec list_keys() -> Result
|
||||||
|
when Result :: {ok, Selected :: non_neg_integer(), Keys :: [clutch:id()]}
|
||||||
|
| error.
|
||||||
|
|
||||||
|
list_keys() ->
|
||||||
|
gen_server:call(?MODULE, list_keys).
|
||||||
|
|
||||||
|
|
||||||
-spec add_node(New) -> ok
|
-spec add_node(New) -> ok
|
||||||
when New :: #node{}.
|
when New :: #node{}.
|
||||||
|
|
||||||
@ -262,6 +307,7 @@ start_link() ->
|
|||||||
|
|
||||||
init(none) ->
|
init(none) ->
|
||||||
ok = log(info, "Starting"),
|
ok = log(info, "Starting"),
|
||||||
|
process_flag(sensitive, true),
|
||||||
Prefs = read_prefs(),
|
Prefs = read_prefs(),
|
||||||
GUI_Prefs = maps:get(gmc_gui, Prefs, #{}),
|
GUI_Prefs = maps:get(gmc_gui, Prefs, #{}),
|
||||||
Window = gmc_gui:start_link(GUI_Prefs),
|
Window = gmc_gui:start_link(GUI_Prefs),
|
||||||
@ -295,6 +341,9 @@ read_prefs() ->
|
|||||||
%% The gen_server:handle_call/3 callback.
|
%% The gen_server:handle_call/3 callback.
|
||||||
%% See: http://erlang.org/doc/man/gen_server.html#Module:handle_call-3
|
%% See: http://erlang.org/doc/man/gen_server.html#Module:handle_call-3
|
||||||
|
|
||||||
|
handle_call(list_keys, _, State) ->
|
||||||
|
Response = do_list_keys(State),
|
||||||
|
{reply, Response, State};
|
||||||
handle_call({nonce, ID}, _, State) ->
|
handle_call({nonce, ID}, _, State) ->
|
||||||
Response = do_nonce(ID),
|
Response = do_nonce(ID),
|
||||||
{reply, Response, State};
|
{reply, Response, State};
|
||||||
@ -324,9 +373,9 @@ handle_cast({open_wallet, Path, Phrase}, State) ->
|
|||||||
NewState = do_open_wallet(Path, Phrase, State),
|
NewState = do_open_wallet(Path, Phrase, State),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
handle_cast(close_wallet, State) ->
|
handle_cast(close_wallet, State) ->
|
||||||
NewState = do_close_wallet(State),
|
NextState = do_close_wallet(State),
|
||||||
ok = gmc_gui:show([]),
|
ok = gmc_gui:show([]),
|
||||||
ok = do_show_ui(gmc_v_wallman, NewState),
|
NewState = do_show_ui(gmc_v_wallman, NextState),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
handle_cast({new_wallet, Name, Path, Password}, State) ->
|
handle_cast({new_wallet, Name, Path, Password}, State) ->
|
||||||
NewState = do_new_wallet(Name, Path, Password, State),
|
NewState = do_new_wallet(Name, Path, Password, State),
|
||||||
@ -337,6 +386,9 @@ handle_cast({import_wallet, Name, Path, Password}, State) ->
|
|||||||
handle_cast({drop_wallet, Path, Delete}, State) ->
|
handle_cast({drop_wallet, Path, Delete}, State) ->
|
||||||
NewState = do_drop_wallet(Path, Delete, State),
|
NewState = do_drop_wallet(Path, Delete, State),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
|
handle_cast({selected, Index}, State) ->
|
||||||
|
NewState = State#s{selected = Index},
|
||||||
|
{noreply, NewState};
|
||||||
handle_cast({password, Old, New}, State) ->
|
handle_cast({password, Old, New}, State) ->
|
||||||
NewState = do_password(Old, New, State),
|
NewState = do_password(Old, New, State),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
@ -358,6 +410,15 @@ handle_cast({sign_mess, Request}, State) ->
|
|||||||
handle_cast({sign_tx, Request}, State) ->
|
handle_cast({sign_tx, Request}, State) ->
|
||||||
ok = do_sign_tx(Request, State),
|
ok = do_sign_tx(Request, State),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
handle_cast({sign_call, ConID, PubKey, TX}, State) ->
|
||||||
|
ok = do_sign_call(State, ConID, PubKey, TX),
|
||||||
|
{noreply, State};
|
||||||
|
handle_cast({dry_run, ConID, TX}, State) ->
|
||||||
|
ok = do_dry_run(ConID, TX),
|
||||||
|
{noreply, State};
|
||||||
|
handle_cast({deploy, CreatorID, Build, InitArgs}, State) ->
|
||||||
|
ok = do_deploy(CreatorID, Build, InitArgs, State),
|
||||||
|
{noreply, State};
|
||||||
handle_cast({make_key, Name, Seed, Encoding, Transform}, State) ->
|
handle_cast({make_key, Name, Seed, Encoding, Transform}, State) ->
|
||||||
NewState = do_make_key(Name, Seed, Encoding, Transform, State),
|
NewState = do_make_key(Name, Seed, Encoding, Transform, State),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
@ -587,8 +648,8 @@ do_grids_sig2(WTF) ->
|
|||||||
do_sign_mess(Request = #{"public_id" := ID, "payload" := Message},
|
do_sign_mess(Request = #{"public_id" := ID, "payload" := Message},
|
||||||
#s{wallet = #wallet{keys = Keys}}) ->
|
#s{wallet = #wallet{keys = Keys}}) ->
|
||||||
case lists:keyfind(ID, #key.id, Keys) of
|
case lists:keyfind(ID, #key.id, Keys) of
|
||||||
#key{pair = #{secret := PrivKey}} ->
|
#key{pair = #{secret := SecKey}} ->
|
||||||
Sig = base64:encode(sign_message(list_to_binary(Message), PrivKey)),
|
Sig = base64:encode(sign_message(list_to_binary(Message), SecKey)),
|
||||||
do_sign_mess2(Request#{"signature" => Sig});
|
do_sign_mess2(Request#{"signature" => Sig});
|
||||||
false ->
|
false ->
|
||||||
gmc_gui:trouble({bad_key, ID})
|
gmc_gui:trouble({bad_key, ID})
|
||||||
@ -612,13 +673,13 @@ do_sign_mess2(Request = #{"url" := URL}) ->
|
|||||||
|
|
||||||
|
|
||||||
% TODO: Should probably be part of Hakuzaru
|
% TODO: Should probably be part of Hakuzaru
|
||||||
sign_message(Message, PrivKey) ->
|
sign_message(Message, SecKey) ->
|
||||||
Prefix = <<"Gajumaru Signed Message:\n">>,
|
Prefix = <<"Gajumaru Signed Message:\n">>,
|
||||||
{ok, PSize} = vencode(byte_size(Prefix)),
|
{ok, PSize} = vencode(byte_size(Prefix)),
|
||||||
{ok, MSize} = vencode(byte_size(Message)),
|
{ok, MSize} = vencode(byte_size(Message)),
|
||||||
Smashed = iolist_to_binary([PSize, Prefix, MSize, Message]),
|
Smashed = iolist_to_binary([PSize, Prefix, MSize, Message]),
|
||||||
{ok, Hashed} = eblake2:blake2b(32, Smashed),
|
{ok, Hashed} = eblake2:blake2b(32, Smashed),
|
||||||
ecu_eddsa:sign_detached(Hashed, PrivKey).
|
ecu_eddsa:sign_detached(Hashed, SecKey).
|
||||||
|
|
||||||
|
|
||||||
vencode(N) when N < 0 ->
|
vencode(N) when N < 0 ->
|
||||||
@ -646,9 +707,9 @@ do_sign_tx(Request = #{"public_id" := ID, "payload" := CallData, "network_id" :=
|
|||||||
#s{wallet = #wallet{keys = Keys}}) ->
|
#s{wallet = #wallet{keys = Keys}}) ->
|
||||||
BinNID = list_to_binary(NID),
|
BinNID = list_to_binary(NID),
|
||||||
case lists:keyfind(ID, #key.id, Keys) of
|
case lists:keyfind(ID, #key.id, Keys) of
|
||||||
#key{pair = #{secret := PrivKey}} ->
|
#key{pair = #{secret := SecKey}} ->
|
||||||
BinaryTX = list_to_binary(CallData),
|
BinaryTX = list_to_binary(CallData),
|
||||||
SignedTX = sign_tx_hash(BinaryTX, PrivKey, BinNID),
|
SignedTX = sign_tx_hash(BinaryTX, SecKey, BinNID),
|
||||||
do_sign_tx2(Request#{"signed" => true, "payload" := SignedTX});
|
do_sign_tx2(Request#{"signed" => true, "payload" := SignedTX});
|
||||||
false ->
|
false ->
|
||||||
gmc_gui:trouble({bad_key, ID})
|
gmc_gui:trouble({bad_key, ID})
|
||||||
@ -670,11 +731,11 @@ do_sign_tx2(Request = #{"url" := URL}) ->
|
|||||||
Error -> gmc_gui:trouble(Error)
|
Error -> gmc_gui:trouble(Error)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
sign_tx_hash(Unsigned, PrivKey, NetworkID) ->
|
sign_tx_hash(Unsigned, SecKey, NetworkID) ->
|
||||||
{ok, TX_Data} = aeser_api_encoder:safe_decode(transaction, Unsigned),
|
{ok, TX_Data} = gmser_api_encoder:safe_decode(transaction, Unsigned),
|
||||||
{ok, Hash} = eblake2:blake2b(32, TX_Data),
|
{ok, Hash} = eblake2:blake2b(32, TX_Data),
|
||||||
NetworkHash = <<NetworkID/binary, Hash/binary>>,
|
NetworkHash = <<NetworkID/binary, Hash/binary>>,
|
||||||
Signature = ecu_eddsa:sign_detached(NetworkHash, PrivKey),
|
Signature = ecu_eddsa:sign_detached(NetworkHash, SecKey),
|
||||||
SigTxType = signed_tx,
|
SigTxType = signed_tx,
|
||||||
SigTxVsn = 1,
|
SigTxVsn = 1,
|
||||||
SigTemplate =
|
SigTemplate =
|
||||||
@ -683,19 +744,57 @@ sign_tx_hash(Unsigned, PrivKey, NetworkID) ->
|
|||||||
TX =
|
TX =
|
||||||
[{signatures, [Signature]},
|
[{signatures, [Signature]},
|
||||||
{transaction, TX_Data}],
|
{transaction, TX_Data}],
|
||||||
SignedTX = aeser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX),
|
SignedTX = gmser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX),
|
||||||
aeser_api_encoder:encode(transaction, SignedTX).
|
gmser_api_encoder:encode(transaction, SignedTX).
|
||||||
|
|
||||||
|
|
||||||
|
do_sign_call(#s{wallet = #wallet{keys = Keys, chain_id = ChainID}},
|
||||||
|
ConID,
|
||||||
|
PubKey,
|
||||||
|
TX) ->
|
||||||
|
#key{pair = #{secret := SecKey}} = lists:keyfind(PubKey, #key.id, Keys),
|
||||||
|
SignedTX = sign_tx_hash(TX, SecKey, ChainID),
|
||||||
|
case hz:post_tx(SignedTX) of
|
||||||
|
{ok, Data = #{"tx_hash" := TXHash}} ->
|
||||||
|
ok = tell("Contract deploy TX succeded with: ~p", [TXHash]),
|
||||||
|
do_sign_call2(ConID, Data);
|
||||||
|
{ok, WTF} ->
|
||||||
|
gmc_v_devman:trouble({error, WTF});
|
||||||
|
Error ->
|
||||||
|
gmc_v_devman:trouble(Error)
|
||||||
|
end;
|
||||||
|
do_sign_call(_, _, _, _) ->
|
||||||
|
gmc_v_devman:trouble({error, no_chain}).
|
||||||
|
|
||||||
|
do_sign_call2(ConID, #{"tx_hash" := TXHash}) ->
|
||||||
|
case hz:tx_info(TXHash) of
|
||||||
|
{ok, CallInfo = #{"call_info" := #{"return_type" := "ok"}}} ->
|
||||||
|
gmc_v_devman:call_result(ConID, CallInfo);
|
||||||
|
{error, "Tx not mined"} ->
|
||||||
|
gmc_v_devman:trouble({tx_hash, TXHash});
|
||||||
|
{ok, Reason = #{"call_info" := #{"return_type" := "revert"}}} ->
|
||||||
|
gmc_v_devman:trouble({error, Reason});
|
||||||
|
Error ->
|
||||||
|
gmc_v_devman:trouble(Error)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
do_dry_run(ConID, TX) ->
|
||||||
|
case hz:dry_run(TX) of
|
||||||
|
{ok, Result} -> gmc_v_devman:dryrun_result(ConID, Result);
|
||||||
|
Other -> gmc_v_devmam:trouble({error, ConID, Other})
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
do_spend(KeyID, TX, State = #s{wallet = #wallet{keys = Keys}}) ->
|
do_spend(KeyID, TX, State = #s{wallet = #wallet{keys = Keys}}) ->
|
||||||
case lists:keyfind(KeyID, #key.id, Keys) of
|
case lists:keyfind(KeyID, #key.id, Keys) of
|
||||||
#key{pair = #{secret := PrivKey}} ->
|
#key{pair = #{secret := SecKey}} ->
|
||||||
do_spend2(PrivKey, TX, State);
|
do_spend2(SecKey, TX, State);
|
||||||
false ->
|
false ->
|
||||||
log(warning, "Tried do_spend with a bad key: ~p", [KeyID])
|
log(warning, "Tried do_spend with a bad key: ~p", [KeyID])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_spend2(PrivKey,
|
do_spend2(SecKey,
|
||||||
#spend_tx{sender_id = SenderID,
|
#spend_tx{sender_id = SenderID,
|
||||||
recipient_id = RecipientID,
|
recipient_id = RecipientID,
|
||||||
amount = Amount,
|
amount = Amount,
|
||||||
@ -725,9 +824,9 @@ do_spend2(PrivKey,
|
|||||||
{ttl, int},
|
{ttl, int},
|
||||||
{nonce, int},
|
{nonce, int},
|
||||||
{payload, binary}],
|
{payload, binary}],
|
||||||
BinaryTX = aeser_chain_objects:serialize(Type, Vsn, Template, Fields),
|
BinaryTX = gmser_chain_objects:serialize(Type, Vsn, Template, Fields),
|
||||||
NetworkTX = <<ChainID/binary, BinaryTX/binary>>,
|
NetworkTX = <<ChainID/binary, BinaryTX/binary>>,
|
||||||
Signature = ecu_eddsa:sign_detached(NetworkTX, PrivKey),
|
Signature = ecu_eddsa:sign_detached(NetworkTX, SecKey),
|
||||||
SigTxType = signed_tx,
|
SigTxType = signed_tx,
|
||||||
SigTxVsn = 1,
|
SigTxVsn = 1,
|
||||||
SigTemplate =
|
SigTemplate =
|
||||||
@ -736,12 +835,18 @@ do_spend2(PrivKey,
|
|||||||
TX_Data =
|
TX_Data =
|
||||||
[{signatures, [Signature]},
|
[{signatures, [Signature]},
|
||||||
{transaction, BinaryTX}],
|
{transaction, BinaryTX}],
|
||||||
SignedTX = aeser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX_Data),
|
SignedTX = gmser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX_Data),
|
||||||
Encoded = aeser_api_encoder:encode(transaction, SignedTX),
|
Encoded = gmser_api_encoder:encode(transaction, SignedTX),
|
||||||
Outcome = hz:post_tx(Encoded),
|
Outcome = hz:post_tx(Encoded),
|
||||||
tell("Outcome: ~p", [Outcome]).
|
tell("Outcome: ~p", [Outcome]).
|
||||||
|
|
||||||
|
|
||||||
|
do_list_keys(#s{selected = Selected, wallet = #wallet{poas = POAs}}) ->
|
||||||
|
{ok, Selected, [ID || #poa{id = ID} <- POAs]};
|
||||||
|
do_list_keys(#s{wallet = none}) ->
|
||||||
|
error.
|
||||||
|
|
||||||
|
|
||||||
do_nonce(ID) ->
|
do_nonce(ID) ->
|
||||||
hz:next_nonce(ID).
|
hz:next_nonce(ID).
|
||||||
|
|
||||||
@ -790,6 +895,9 @@ do_make_key(Name, Seed, base58, Transform, State) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
do_make_key2(_, _, _, State = #s{wallet = none}) ->
|
||||||
|
ok = gmc_gui:trouble("No wallet selected!"),
|
||||||
|
do_show_ui(gmc_v_wallman, State);
|
||||||
do_make_key2(Name, Bin, Transform,
|
do_make_key2(Name, Bin, Transform,
|
||||||
State = #s{wallet = Current, wallets = Wallets, pass = Pass}) ->
|
State = #s{wallet = Current, wallets = Wallets, pass = Pass}) ->
|
||||||
#wallet{name = WalletName, poas = POAs, keys = Keys} = Current,
|
#wallet{name = WalletName, poas = POAs, keys = Keys} = Current,
|
||||||
@ -870,6 +978,42 @@ do_mnemonic(ID, #s{wallet = #wallet{keys = Keys}}) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
do_deploy(CreatorID,
|
||||||
|
Build,
|
||||||
|
InitArgs,
|
||||||
|
#s{wallet = #wallet{keys = Keys, chain_id = ChainID}}) ->
|
||||||
|
#key{pair = #{secret := SecKey}} = lists:keyfind(CreatorID, #key.id, Keys),
|
||||||
|
case hz:contract_create_built(CreatorID, Build, InitArgs) of
|
||||||
|
{ok, CreateTX} -> do_deploy2(SecKey, CreateTX, ChainID);
|
||||||
|
Error -> gmc_v_devman:trouble(Error)
|
||||||
|
end.
|
||||||
|
|
||||||
|
do_deploy2(SecKey, CreateTX, ChainID) ->
|
||||||
|
SignedTX = sign_tx_hash(CreateTX, SecKey, ChainID),
|
||||||
|
tell(info, "SignedTX: ~p", [SignedTX]),
|
||||||
|
case hz:post_tx(SignedTX) of
|
||||||
|
{ok, Data = #{"tx_hash" := TXHash}} ->
|
||||||
|
ok = tell("Contract deploy TX succeded with: ~p", [TXHash]),
|
||||||
|
do_deploy3(Data);
|
||||||
|
{ok, WTF} ->
|
||||||
|
gmc_v_devman:trouble({error, WTF});
|
||||||
|
Error ->
|
||||||
|
gmc_v_devman:trouble(Error)
|
||||||
|
end.
|
||||||
|
|
||||||
|
do_deploy3(#{"tx_hash" := TXHash}) ->
|
||||||
|
case hz:tx_info(TXHash) of
|
||||||
|
{ok, #{"call_info" := #{"return_type" := "ok", "contract_id" := ConID}}} ->
|
||||||
|
gmc_v_devman:open_contract(ConID);
|
||||||
|
{error, "Tx not mined"} ->
|
||||||
|
gmc_v_devman:trouble({tx_hash, TXHash});
|
||||||
|
{ok, Reason = #{"call_info" := #{"return_type" := "revert"}}} ->
|
||||||
|
gmc_v_devman:trouble({error, Reason});
|
||||||
|
Error ->
|
||||||
|
gmc_v_devman:trouble(Error)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
do_rename_key(ID, NewName, State = #s{wallet = W}) ->
|
do_rename_key(ID, NewName, State = #s{wallet = W}) ->
|
||||||
#wallet{poas = POAs, keys = Keys} = W,
|
#wallet{poas = POAs, keys = Keys} = W,
|
||||||
A = lists:keyfind(ID, #poa.id, POAs),
|
A = lists:keyfind(ID, #poa.id, POAs),
|
||||||
@ -1073,7 +1217,7 @@ do_close_wallet(State = #s{wallet = Current, wallets = Wallets, pass = Pass}) ->
|
|||||||
#wallet{name = Name} = Current,
|
#wallet{name = Name} = Current,
|
||||||
RW = lists:keyfind(Name, #wr.name, Wallets),
|
RW = lists:keyfind(Name, #wr.name, Wallets),
|
||||||
ok = save_wallet(RW, Pass, Current),
|
ok = save_wallet(RW, Pass, Current),
|
||||||
State#s{pass = none, wallet = none}.
|
State#s{selected = 0, pass = none, wallet = none}.
|
||||||
|
|
||||||
|
|
||||||
save_wallet(#wr{path = Path, pass = false}, none, Wallet) ->
|
save_wallet(#wr{path = Path, pass = false}, none, Wallet) ->
|
||||||
@ -1115,7 +1259,8 @@ read2(Bin) ->
|
|||||||
|
|
||||||
read3(T) ->
|
read3(T) ->
|
||||||
case element(2, T) of
|
case element(2, T) of
|
||||||
1 -> {ok, T};
|
1 -> read3(setelement(2, erlang:append_element(T, #{}), 2));
|
||||||
|
2 -> {ok, T};
|
||||||
_ -> {error, bad_wallet}
|
_ -> {error, bad_wallet}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
|
|
||||||
-module(gmc_grids).
|
-module(gmc_grids).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-author("Craig Everett <craigeverett@qpq.swiss>").
|
-author("Craig Everett <craigeverett@qpq.swiss>").
|
||||||
-copyright("QPQ AG <info@qpq.swiss>").
|
-copyright("QPQ AG <info@qpq.swiss>").
|
||||||
-license("GPL-3.0-or-later").
|
-license("GPL-3.0-or-later").
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
%%% @doc
|
%%% @doc
|
||||||
%%% Clutch GUI
|
%%% GajuDesk GUI
|
||||||
%%%
|
|
||||||
%%% This process is responsible for creating the main GUI frame displayed to the user.
|
|
||||||
%%%
|
|
||||||
%%% Reference: http://erlang.org/doc/man/wx_object.html
|
|
||||||
%%% @end
|
%%% @end
|
||||||
|
|
||||||
-module(gmc_gui).
|
-module(gmc_gui).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-author("Craig Everett <craigeverett@qpq.swiss>").
|
-author("Craig Everett <craigeverett@qpq.swiss>").
|
||||||
-copyright("QPQ AG <info@qpq.swiss>").
|
-copyright("QPQ AG <info@qpq.swiss>").
|
||||||
-license("GPL-3.0-or-later").
|
-license("GPL-3.0-or-later").
|
||||||
@ -62,8 +58,8 @@ chain(ChainID, Node) ->
|
|||||||
wx_object:cast(?MODULE, {chain, ChainID, Node}).
|
wx_object:cast(?MODULE, {chain, ChainID, Node}).
|
||||||
|
|
||||||
|
|
||||||
trouble(Message) ->
|
trouble(Info) ->
|
||||||
wx_object:cast(?MODULE, {trouble, Message}).
|
wx_object:cast(?MODULE, {trouble, Info}).
|
||||||
|
|
||||||
|
|
||||||
ask_password() ->
|
ask_password() ->
|
||||||
@ -239,7 +235,7 @@ handle_cast({chain, ChainID, Node}, State) ->
|
|||||||
ok = do_chain(ChainID, Node, State),
|
ok = do_chain(ChainID, Node, State),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_cast({trouble, Info}, State) ->
|
handle_cast({trouble, Info}, State) ->
|
||||||
ok = handle_trouble(Info, State),
|
ok = handle_troubling(State, Info),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_cast(password, State) ->
|
handle_cast(password, State) ->
|
||||||
ok = do_ask_password(State),
|
ok = do_ask_password(State),
|
||||||
@ -321,6 +317,10 @@ handle_event(Event, State) ->
|
|||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
|
|
||||||
|
handle_troubling(#s{frame = Frame}, Info) ->
|
||||||
|
zxw:show_message(Frame, Info).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
code_change(_, State, _) ->
|
code_change(_, State, _) ->
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
@ -765,7 +765,7 @@ spend2(#poa{id = ID, name = Name}, Nonce, Height, State = #s{frame = Frame, j =
|
|||||||
?wxID_OK ->
|
?wxID_OK ->
|
||||||
{ok, PK} = decode_account_id(ID),
|
{ok, PK} = decode_account_id(ID),
|
||||||
TX =
|
TX =
|
||||||
#spend_tx{sender_id = aeser_id:create(account, PK),
|
#spend_tx{sender_id = gmser_id:create(account, PK),
|
||||||
recipient_id = wxTextCtrl:getValue(ToTx),
|
recipient_id = wxTextCtrl:getValue(ToTx),
|
||||||
amount = wxTextCtrl:getValue(AmtTx),
|
amount = wxTextCtrl:getValue(AmtTx),
|
||||||
gas_price = wxSlider:getValue(GasSl),
|
gas_price = wxSlider:getValue(GasSl),
|
||||||
@ -784,7 +784,7 @@ clean_spend(_, #spend_tx{recipient_id = ""}) ->
|
|||||||
ok;
|
ok;
|
||||||
clean_spend(ID, TX = #spend_tx{recipient_id = S}) when is_list(S) ->
|
clean_spend(ID, TX = #spend_tx{recipient_id = S}) when is_list(S) ->
|
||||||
case decode_account_id(S) of
|
case decode_account_id(S) of
|
||||||
{ok, PK} -> clean_spend(ID, TX#spend_tx{recipient_id = aeser_id:create(account, PK)});
|
{ok, PK} -> clean_spend(ID, TX#spend_tx{recipient_id = gmser_id:create(account, PK)});
|
||||||
Error -> tell("Decode recipient_id failed with: ~tp", [Error])
|
Error -> tell("Decode recipient_id failed with: ~tp", [Error])
|
||||||
end;
|
end;
|
||||||
clean_spend(ID, TX = #spend_tx{amount = S}) when is_list(S) ->
|
clean_spend(ID, TX = #spend_tx{amount = S}) when is_list(S) ->
|
||||||
@ -811,7 +811,7 @@ decode_account_id(S) when is_list(S) ->
|
|||||||
decode_account_id(list_to_binary(S));
|
decode_account_id(list_to_binary(S));
|
||||||
decode_account_id(B) ->
|
decode_account_id(B) ->
|
||||||
try
|
try
|
||||||
{account_pubkey, PK} = aeser_api_encoder:decode(B),
|
{account_pubkey, PK} = gmser_api_encoder:decode(B),
|
||||||
{ok, PK}
|
{ok, PK}
|
||||||
catch
|
catch
|
||||||
E:R -> {E, R}
|
E:R -> {E, R}
|
||||||
@ -863,10 +863,12 @@ do_selection(Selected,
|
|||||||
State = #s{prefs = Prefs, accounts = Accounts,
|
State = #s{prefs = Prefs, accounts = Accounts,
|
||||||
balance = {_, #w{wx = B}}, id = {_, #w{wx = I}}})
|
balance = {_, #w{wx = B}}, id = {_, #w{wx = I}}})
|
||||||
when Selected < length(Accounts) ->
|
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,
|
[#balance{total = Pucks}] = Balances,
|
||||||
ok = wxStaticText:setLabel(I, ID),
|
ok = wxStaticText:setLabel(I, ID),
|
||||||
ok = wxStaticText:setLabel(B, price_to_string(Pucks)),
|
ok = wxStaticText:setLabel(B, price_to_string(Pucks)),
|
||||||
|
ok = gmc_con:selected(OneBasedIndex),
|
||||||
NewPrefs = maps:put(selected, Selected, Prefs),
|
NewPrefs = maps:put(selected, Selected, Prefs),
|
||||||
State#s{prefs = NewPrefs};
|
State#s{prefs = NewPrefs};
|
||||||
do_selection(_, State) ->
|
do_selection(_, State) ->
|
||||||
@ -924,10 +926,6 @@ do_chain(ChainID, #node{ip = IP}, #s{buttons = Buttons}) ->
|
|||||||
ok = wxButton:setLabel(NodeB, Address).
|
ok = wxButton:setLabel(NodeB, Address).
|
||||||
|
|
||||||
|
|
||||||
handle_trouble(Info, #s{frame = Frame}) ->
|
|
||||||
zxw:show_message(Frame, Info).
|
|
||||||
|
|
||||||
|
|
||||||
do_ask_password(#s{frame = Frame, prefs = Prefs, j = J}) ->
|
do_ask_password(#s{frame = Frame, prefs = Prefs, j = J}) ->
|
||||||
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Password")),
|
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Password")),
|
||||||
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
%%% translation library is retained).
|
%%% translation library is retained).
|
||||||
|
|
||||||
-module(gmc_jt).
|
-module(gmc_jt).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-export([read_translations/1, j/2, oneshot_j/2]).
|
-export([read_translations/1, j/2, oneshot_j/2]).
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
|
|
||||||
-module(gmc_key_master).
|
-module(gmc_key_master).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
|
|
||||||
|
|
||||||
-export([make_key/2, encode/1, decode/1]).
|
-export([make_key/2, encode/1, decode/1]).
|
||||||
@ -18,21 +18,21 @@
|
|||||||
|
|
||||||
make_key("", <<>>) ->
|
make_key("", <<>>) ->
|
||||||
Pair = #{public := Public} = ecu_eddsa:sign_keypair(),
|
Pair = #{public := Public} = ecu_eddsa:sign_keypair(),
|
||||||
ID = aeser_api_encoder:encode(account_pubkey, Public),
|
ID = gmser_api_encoder:encode(account_pubkey, Public),
|
||||||
Name = binary_to_list(ID),
|
Name = binary_to_list(ID),
|
||||||
#key{name = Name, id = ID, pair = Pair};
|
#key{name = Name, id = ID, pair = Pair};
|
||||||
make_key("", Seed) ->
|
make_key("", Seed) ->
|
||||||
Pair = #{public := Public} = ecu_eddsa:sign_seed_keypair(Seed),
|
Pair = #{public := Public} = ecu_eddsa:sign_seed_keypair(Seed),
|
||||||
ID = aeser_api_encoder:encode(account_pubkey, Public),
|
ID = gmser_api_encoder:encode(account_pubkey, Public),
|
||||||
Name = binary_to_list(ID),
|
Name = binary_to_list(ID),
|
||||||
#key{name = Name, id = ID, pair = Pair};
|
#key{name = Name, id = ID, pair = Pair};
|
||||||
make_key(Name, <<>>) ->
|
make_key(Name, <<>>) ->
|
||||||
Pair = #{public := Public} = ecu_eddsa:sign_keypair(),
|
Pair = #{public := Public} = ecu_eddsa:sign_keypair(),
|
||||||
ID = aeser_api_encoder:encode(account_pubkey, Public),
|
ID = gmser_api_encoder:encode(account_pubkey, Public),
|
||||||
#key{name = Name, id = ID, pair = Pair};
|
#key{name = Name, id = ID, pair = Pair};
|
||||||
make_key(Name, Seed) ->
|
make_key(Name, Seed) ->
|
||||||
Pair = #{public := Public} = ecu_eddsa:sign_seed_keypair(Seed),
|
Pair = #{public := Public} = ecu_eddsa:sign_seed_keypair(Seed),
|
||||||
ID = aeser_api_encoder:encode(account_pubkey, Public),
|
ID = gmser_api_encoder:encode(account_pubkey, Public),
|
||||||
#key{name = Name, id = ID, pair = Pair}.
|
#key{name = Name, id = ID, pair = Pair}.
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
|
|
||||||
-module(gmc_sup).
|
-module(gmc_sup).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-behaviour(supervisor).
|
-behaviour(supervisor).
|
||||||
-author("Craig Everett <craigeverett@qpq.swiss>").
|
-author("Craig Everett <craigeverett@qpq.swiss>").
|
||||||
-copyright("QPQ AG <info@qpq.swiss>").
|
-copyright("QPQ AG <info@qpq.swiss>").
|
||||||
@ -36,11 +36,11 @@ start_link() ->
|
|||||||
|
|
||||||
init([]) ->
|
init([]) ->
|
||||||
RestartStrategy = {one_for_one, 0, 60},
|
RestartStrategy = {one_for_one, 0, 60},
|
||||||
Clients = {gmc_con,
|
Controller = {gmc_con,
|
||||||
{gmc_con, start_link, []},
|
{gmc_con, start_link, []},
|
||||||
permanent,
|
permanent,
|
||||||
5000,
|
5000,
|
||||||
worker,
|
worker,
|
||||||
[gmc_con]},
|
[gmc_con]},
|
||||||
Children = [Clients],
|
Children = [Controller],
|
||||||
{ok, {RestartStrategy, Children}}.
|
{ok, {RestartStrategy, Children}}.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-module(gmc_v).
|
-module(gmc_v).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-author("Craig Everett <craigeverett@qpq.swiss>").
|
-author("Craig Everett <craigeverett@qpq.swiss>").
|
||||||
-copyright("QPQ AG <info@qpq.swiss>").
|
-copyright("QPQ AG <info@qpq.swiss>").
|
||||||
-license("GPL-3.0-or-later").
|
-license("GPL-3.0-or-later").
|
||||||
|
1108
src/gmc_v_devman.erl
1108
src/gmc_v_devman.erl
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
-module(gmc_v_netman).
|
-module(gmc_v_netman).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-author("Craig Everett <zxq9@zxq9.com>").
|
-author("Craig Everett <zxq9@zxq9.com>").
|
||||||
-copyright("QPQ AG <info@qpq.swiss>").
|
-copyright("QPQ AG <info@qpq.swiss>").
|
||||||
-license("GPL-3.0-or-later").
|
-license("GPL-3.0-or-later").
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-module(gmc_v_wallman).
|
-module(gmc_v_wallman).
|
||||||
-vsn("0.1.4").
|
-vsn("0.3.0").
|
||||||
-author("Craig Everett <zxq9@zxq9.com>").
|
-author("Craig Everett <zxq9@zxq9.com>").
|
||||||
-copyright("QPQ AG <info@qpq.swiss>").
|
-copyright("QPQ AG <info@qpq.swiss>").
|
||||||
-license("GPL-3.0-or-later").
|
-license("GPL-3.0-or-later").
|
||||||
@ -273,7 +273,7 @@ do_new(State = #s{frame = Frame, j = J, prefs = Prefs}) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
do_new2(Path, J, Frame) ->
|
do_new2(Path, J, Frame) ->
|
||||||
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Set Node"), [{size, {400, 250}}]),
|
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("New Wallet"), [{size, {400, 250}}]),
|
||||||
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
||||||
|
|
||||||
NameSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Name")}]),
|
NameSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Name")}]),
|
||||||
@ -360,7 +360,7 @@ do_import2(_, "", _, _) ->
|
|||||||
abort;
|
abort;
|
||||||
do_import2(Dir, File, J, Frame) ->
|
do_import2(Dir, File, J, Frame) ->
|
||||||
Path = filename:join(Dir, File),
|
Path = filename:join(Dir, File),
|
||||||
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Set Node")),
|
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Import Wallet")),
|
||||||
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
||||||
|
|
||||||
NameSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Name")}]),
|
NameSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Name")}]),
|
||||||
|
13
zomp.meta
13
zomp.meta
@ -2,14 +2,15 @@
|
|||||||
{type,gui}.
|
{type,gui}.
|
||||||
{modules,[]}.
|
{modules,[]}.
|
||||||
{prefix,"gmc"}.
|
{prefix,"gmc"}.
|
||||||
{desc,"A desktop client for the Gajumaru network of blockchain networks"}.
|
|
||||||
{author,"Craig Everett"}.
|
{author,"Craig Everett"}.
|
||||||
{package_id,{"otpr","clutch",{0,1,4}}}.
|
{desc,"A desktop client for the Gajumaru network of blockchain networks"}.
|
||||||
{deps,[{"otpr","hakuzaru",{0,2,0}},
|
{package_id,{"otpr","clutch",{0,3,0}}}.
|
||||||
{"otpr","aesophia",{8,0,1}},
|
{deps,[{"otpr","sophia",{9,0,0}},
|
||||||
{"otpr","aeserialization",{0,1,2}},
|
{"otpr","hakuzaru",{0,3,0}},
|
||||||
|
{"otpr","gmbytecode",{3,4,1}},
|
||||||
|
{"otpr","lom",{1,0,0}},
|
||||||
|
{"otpr","gmserialization",{0,1,2}},
|
||||||
{"otpr","zj",{1,1,0}},
|
{"otpr","zj",{1,1,0}},
|
||||||
{"otpr","aebytecode",{3,2,1}},
|
|
||||||
{"otpr","erl_base58",{0,1,0}},
|
{"otpr","erl_base58",{0,1,0}},
|
||||||
{"otpr","eblake2",{1,0,0}},
|
{"otpr","eblake2",{1,0,0}},
|
||||||
{"otpr","ec_utils",{1,0,0}},
|
{"otpr","ec_utils",{1,0,0}},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user