contract #5

Merged
zxq9 merged 10 commits from contract into master 2025-02-25 16:43:29 +09:00
14 changed files with 1126 additions and 365 deletions

View File

@ -2,8 +2,8 @@
[{description,"A desktop client for the Gajumaru network of blockchain networks"},
{registered,[]},
{included_applications,[]},
{applications,[stdlib,kernel]},
{vsn,"0.1.4"},
{applications,[stdlib,kernel,sasl,ssl]},
{vsn,"0.3.0"},
{modules,[clutch,gmc_con,gmc_grids,gmc_gui,gmc_jt,
gmc_key_master,gmc_sup,gmc_v,gmc_v_netman,
gmc_v_wallman]},

View File

@ -60,7 +60,9 @@
-record(tx,
{id = none :: none | clutch:id(),
amount = 0 :: non_neg_integer(),
type = spend :: spend | atom()}).
type = spend :: atom(),
status = submitted :: submitted | mined | rejected | failed,
meta = "" :: string()}).
-record(spend_tx,
@ -75,13 +77,14 @@
-record(wallet,
{version = 1 :: integer(),
{version = 2 :: integer(),
name = "" :: string(),
poas = [] :: [#poa{}],
keys = [] :: [#key{}],
chain_id = <<"groot.devnet">> :: binary(),
endpoint = #node{} :: #node{},
nets = [#net{}] :: [#net{}]}).
nets = [#net{}] :: [#net{}],
txs = #{} :: clutch:key_txs()}).

View File

@ -3,7 +3,7 @@
%%% @end
-module(clutch).
-vsn("0.1.4").
-vsn("0.3.0").
-behavior(application).
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
@ -12,7 +12,7 @@
-export([ts/0]).
-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("gmc.hrl").
@ -23,6 +23,8 @@
-type poa() :: #poa{}.
-type tx() :: #tx{}.
-type ts() :: integer().
-type chain_txs() :: #{ChainID :: binary() := [tx()]}.
-type key_txs() :: #{id() := {{LastCheck :: ts(), mdw | node}, chain_txs()}}.
ts() ->
@ -55,9 +57,9 @@ start(normal, _Args) ->
ok = tell(error, "DANGER! This node is in distributed mode!"),
init:stop(1)
end,
ok = application:ensure_started(sasl),
ok = application:ensure_started(hakuzaru),
ok = application:ensure_started(zxwidgets),
ok = application:ensure_started(sophia),
gmc_sup:start_link().

View File

@ -1,11 +1,9 @@
%%% @doc
%%% Clutch Controller
%%%
%%% This process is a in charge of maintaining the program's state.
%%% GajuDesk Controller
%%% @end
-module(gmc_con).
-vsn("0.1.4").
-vsn("0.3.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("GPL-3.0-or-later").
@ -13,10 +11,12 @@
-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,
make_key/6, recover_key/1, mnemonic/1, rename_key/2, drop_key/1,
nonce/1, spend/2, chain/1, grids/1, sign_mess/1, sign_tx/1, sign_call/3, dry_run/2,
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]).
-export([encrypt/2, decrypt/2]).
-export([save/2]).
@ -41,6 +41,7 @@
{version = 1 :: integer(),
window = none :: none | wx:wx_object(),
tasks = [] :: [#ui{}],
selected = 0 :: non_neg_integer(),
wallet = none :: none | #wallet{},
pass = none :: none | binary(),
prefs = #{} :: #{module() := term()},
@ -104,6 +105,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 +170,35 @@ 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
when Type :: {eddsa, ed25519},
Size :: 256,
@ -211,6 +248,14 @@ 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
when New :: #node{}.
@ -262,6 +307,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),
@ -295,6 +341,9 @@ read_prefs() ->
%% The gen_server:handle_call/3 callback.
%% 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) ->
Response = do_nonce(ID),
{reply, Response, State};
@ -324,9 +373,9 @@ handle_cast({open_wallet, Path, Phrase}, State) ->
NewState = do_open_wallet(Path, Phrase, State),
{noreply, NewState};
handle_cast(close_wallet, State) ->
NewState = do_close_wallet(State),
NextState = do_close_wallet(State),
ok = gmc_gui:show([]),
ok = do_show_ui(gmc_v_wallman, NewState),
NewState = do_show_ui(gmc_v_wallman, NextState),
{noreply, NewState};
handle_cast({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) ->
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};
@ -358,6 +410,15 @@ handle_cast({sign_mess, Request}, State) ->
handle_cast({sign_tx, Request}, State) ->
ok = do_sign_tx(Request, 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) ->
NewState = do_make_key(Name, Seed, Encoding, Transform, State),
{noreply, NewState};
@ -587,8 +648,8 @@ do_grids_sig2(WTF) ->
do_sign_mess(Request = #{"public_id" := ID, "payload" := Message},
#s{wallet = #wallet{keys = Keys}}) ->
case lists:keyfind(ID, #key.id, Keys) of
#key{pair = #{secret := PrivKey}} ->
Sig = base64:encode(sign_message(list_to_binary(Message), PrivKey)),
#key{pair = #{secret := SecKey}} ->
Sig = base64:encode(sign_message(list_to_binary(Message), SecKey)),
do_sign_mess2(Request#{"signature" => Sig});
false ->
gmc_gui:trouble({bad_key, ID})
@ -612,13 +673,13 @@ do_sign_mess2(Request = #{"url" := URL}) ->
% TODO: Should probably be part of Hakuzaru
sign_message(Message, PrivKey) ->
sign_message(Message, SecKey) ->
Prefix = <<"Gajumaru Signed Message:\n">>,
{ok, PSize} = vencode(byte_size(Prefix)),
{ok, MSize} = vencode(byte_size(Message)),
Smashed = iolist_to_binary([PSize, Prefix, MSize, Message]),
{ok, Hashed} = eblake2:blake2b(32, Smashed),
ecu_eddsa:sign_detached(Hashed, PrivKey).
ecu_eddsa:sign_detached(Hashed, SecKey).
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}}) ->
BinNID = list_to_binary(NID),
case lists:keyfind(ID, #key.id, Keys) of
#key{pair = #{secret := PrivKey}} ->
#key{pair = #{secret := SecKey}} ->
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});
false ->
gmc_gui:trouble({bad_key, ID})
@ -670,11 +731,11 @@ do_sign_tx2(Request = #{"url" := URL}) ->
Error -> gmc_gui:trouble(Error)
end.
sign_tx_hash(Unsigned, PrivKey, NetworkID) ->
{ok, TX_Data} = aeser_api_encoder:safe_decode(transaction, Unsigned),
sign_tx_hash(Unsigned, SecKey, NetworkID) ->
{ok, TX_Data} = gmser_api_encoder:safe_decode(transaction, Unsigned),
{ok, Hash} = eblake2:blake2b(32, TX_Data),
NetworkHash = <<NetworkID/binary, Hash/binary>>,
Signature = ecu_eddsa:sign_detached(NetworkHash, PrivKey),
Signature = ecu_eddsa:sign_detached(NetworkHash, SecKey),
SigTxType = signed_tx,
SigTxVsn = 1,
SigTemplate =
@ -683,19 +744,57 @@ sign_tx_hash(Unsigned, PrivKey, NetworkID) ->
TX =
[{signatures, [Signature]},
{transaction, TX_Data}],
SignedTX = aeser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX),
aeser_api_encoder:encode(transaction, SignedTX).
SignedTX = gmser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX),
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}}) ->
case lists:keyfind(KeyID, #key.id, Keys) of
#key{pair = #{secret := PrivKey}} ->
do_spend2(PrivKey, TX, State);
#key{pair = #{secret := SecKey}} ->
do_spend2(SecKey, TX, State);
false ->
log(warning, "Tried do_spend with a bad key: ~p", [KeyID])
end.
do_spend2(PrivKey,
do_spend2(SecKey,
#spend_tx{sender_id = SenderID,
recipient_id = RecipientID,
amount = Amount,
@ -725,9 +824,9 @@ do_spend2(PrivKey,
{ttl, int},
{nonce, int},
{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>>,
Signature = ecu_eddsa:sign_detached(NetworkTX, PrivKey),
Signature = ecu_eddsa:sign_detached(NetworkTX, SecKey),
SigTxType = signed_tx,
SigTxVsn = 1,
SigTemplate =
@ -736,12 +835,18 @@ do_spend2(PrivKey,
TX_Data =
[{signatures, [Signature]},
{transaction, BinaryTX}],
SignedTX = aeser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX_Data),
Encoded = aeser_api_encoder:encode(transaction, SignedTX),
SignedTX = gmser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX_Data),
Encoded = gmser_api_encoder:encode(transaction, SignedTX),
Outcome = hz:post_tx(Encoded),
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) ->
hz:next_nonce(ID).
@ -790,6 +895,9 @@ do_make_key(Name, Seed, base58, Transform, State) ->
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,
State = #s{wallet = Current, wallets = Wallets, pass = Pass}) ->
#wallet{name = WalletName, poas = POAs, keys = Keys} = Current,
@ -870,6 +978,42 @@ do_mnemonic(ID, #s{wallet = #wallet{keys = Keys}}) ->
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}) ->
#wallet{poas = POAs, keys = Keys} = W,
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,
RW = lists:keyfind(Name, #wr.name, Wallets),
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) ->
@ -1115,7 +1259,8 @@ read2(Bin) ->
read3(T) ->
case element(2, T) of
1 -> {ok, T};
1 -> read3(setelement(2, erlang:append_element(T, #{}), 2));
2 -> {ok, T};
_ -> {error, bad_wallet}
end.

View File

@ -37,7 +37,7 @@
%%% @end
-module(gmc_grids).
-vsn("0.1.4").
-vsn("0.3.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("GPL-3.0-or-later").

View File

@ -1,13 +1,9 @@
%%% @doc
%%% Clutch GUI
%%%
%%% This process is responsible for creating the main GUI frame displayed to the user.
%%%
%%% Reference: http://erlang.org/doc/man/wx_object.html
%%% GajuDesk GUI
%%% @end
-module(gmc_gui).
-vsn("0.1.4").
-vsn("0.3.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("GPL-3.0-or-later").
@ -62,8 +58,8 @@ chain(ChainID, Node) ->
wx_object:cast(?MODULE, {chain, ChainID, Node}).
trouble(Message) ->
wx_object:cast(?MODULE, {trouble, Message}).
trouble(Info) ->
wx_object:cast(?MODULE, {trouble, Info}).
ask_password() ->
@ -239,7 +235,7 @@ handle_cast({chain, ChainID, Node}, State) ->
ok = do_chain(ChainID, Node, State),
{noreply, State};
handle_cast({trouble, Info}, State) ->
ok = handle_trouble(Info, State),
ok = handle_troubling(State, Info),
{noreply, State};
handle_cast(password, State) ->
ok = do_ask_password(State),
@ -321,6 +317,10 @@ handle_event(Event, State) ->
{noreply, State}.
handle_troubling(#s{frame = Frame}, Info) ->
zxw:show_message(Frame, Info).
code_change(_, State, _) ->
{ok, State}.
@ -765,7 +765,7 @@ spend2(#poa{id = ID, name = Name}, Nonce, Height, State = #s{frame = Frame, j =
?wxID_OK ->
{ok, PK} = decode_account_id(ID),
TX =
#spend_tx{sender_id = aeser_id:create(account, PK),
#spend_tx{sender_id = gmser_id:create(account, PK),
recipient_id = wxTextCtrl:getValue(ToTx),
amount = wxTextCtrl:getValue(AmtTx),
gas_price = wxSlider:getValue(GasSl),
@ -784,7 +784,7 @@ clean_spend(_, #spend_tx{recipient_id = ""}) ->
ok;
clean_spend(ID, TX = #spend_tx{recipient_id = S}) when is_list(S) ->
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])
end;
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(B) ->
try
{account_pubkey, PK} = aeser_api_encoder:decode(B),
{account_pubkey, PK} = gmser_api_encoder:decode(B),
{ok, PK}
catch
E:R -> {E, R}
@ -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) ->
@ -924,10 +926,6 @@ do_chain(ChainID, #node{ip = IP}, #s{buttons = Buttons}) ->
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}) ->
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Password")),
Sizer = wxBoxSizer:new(?wxVERTICAL),

View File

@ -15,7 +15,7 @@
%%% translation library is retained).
-module(gmc_jt).
-vsn("0.1.4").
-vsn("0.3.0").
-export([read_translations/1, j/2, oneshot_j/2]).

View File

@ -8,7 +8,7 @@
%%% @end
-module(gmc_key_master).
-vsn("0.1.4").
-vsn("0.3.0").
-export([make_key/2, encode/1, decode/1]).
@ -18,21 +18,21 @@
make_key("", <<>>) ->
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),
#key{name = Name, id = ID, pair = Pair};
make_key("", 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),
#key{name = Name, id = ID, pair = Pair};
make_key(Name, <<>>) ->
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};
make_key(Name, 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}.

View File

@ -12,7 +12,7 @@
%%% @end
-module(gmc_sup).
-vsn("0.1.4").
-vsn("0.3.0").
-behaviour(supervisor).
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
@ -36,11 +36,11 @@ start_link() ->
init([]) ->
RestartStrategy = {one_for_one, 0, 60},
Clients = {gmc_con,
Controller = {gmc_con,
{gmc_con, start_link, []},
permanent,
5000,
worker,
[gmc_con]},
Children = [Clients],
Children = [Controller],
{ok, {RestartStrategy, Children}}.

View File

@ -1,5 +1,5 @@
-module(gmc_v).
-vsn("0.1.4").
-vsn("0.3.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("GPL-3.0-or-later").

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
-module(gmc_v_netman).
-vsn("0.1.4").
-vsn("0.3.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("GPL-3.0-or-later").

View File

@ -1,5 +1,5 @@
-module(gmc_v_wallman).
-vsn("0.1.4").
-vsn("0.3.0").
-author("Craig Everett <zxq9@zxq9.com>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("GPL-3.0-or-later").
@ -273,7 +273,7 @@ do_new(State = #s{frame = Frame, j = J, prefs = Prefs}) ->
end.
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),
NameSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Name")}]),
@ -360,7 +360,7 @@ do_import2(_, "", _, _) ->
abort;
do_import2(Dir, File, J, Frame) ->
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),
NameSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Name")}]),

View File

@ -2,14 +2,15 @@
{type,gui}.
{modules,[]}.
{prefix,"gmc"}.
{desc,"A desktop client for the Gajumaru network of blockchain networks"}.
{author,"Craig Everett"}.
{package_id,{"otpr","clutch",{0,1,4}}}.
{deps,[{"otpr","hakuzaru",{0,2,0}},
{"otpr","aesophia",{8,0,1}},
{"otpr","aeserialization",{0,1,2}},
{desc,"A desktop client for the Gajumaru network of blockchain networks"}.
{package_id,{"otpr","clutch",{0,3,0}}}.
{deps,[{"otpr","sophia",{9,0,0}},
{"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","aebytecode",{3,2,1}},
{"otpr","erl_base58",{0,1,0}},
{"otpr","eblake2",{1,0,0}},
{"otpr","ec_utils",{1,0,0}},