First-run wallet creatorator (v0.7.0) (#24)

Adds a first-run wallet and account creator option for noobs.
If they select the "create a default wallet" option, they are jumped to the name + password screen for wallet creation, and a new account is generated for them named "Account 1".

This leapfrogs the problem of users having to know what is going on with the blockchain and wallet at all before getting started.
#18
#19

Reviewed-on: #24
Reviewed-by: Ulf Wiger <ulfwiger@qpq.swiss>
Co-authored-by: Craig Everett <zxq9@zxq9.com>
Co-committed-by: Craig Everett <zxq9@zxq9.com>
This commit was merged in pull request #24.
This commit is contained in:
2025-08-07 15:47:05 +09:00
committed by Craig Everett
parent a2a9da0d98
commit f92c5fbde0
13 changed files with 236 additions and 80 deletions
+32 -30
View File
@@ -3,7 +3,7 @@
%%% @end
-module(gd_con).
-vsn("0.6.6").
-vsn("0.7.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("GPL-3.0-or-later").
@@ -38,15 +38,15 @@
mon = none :: none | reference()}).
-record(s,
{version = 1 :: integer(),
window = none :: none | wx:wx_object(),
timer = none :: none | reference(),
tasks = [] :: [#ui{}],
selected = 0 :: non_neg_integer(),
wallet = none :: none | #wallet{},
pass = none :: none | binary(),
prefs = #{} :: #{module() := term()},
wallets = [] :: [#wr{}]}).
{version = 1 :: integer(),
window = none :: none | wx:wx_object(),
timer = none :: none | reference(),
tasks = [] :: [#ui{}],
selected = 0 :: non_neg_integer(),
wallet = none :: none | #wallet{},
pass = none :: none | binary(),
prefs = #{} :: #{module() := term()},
wallets = [] :: [#wr{}]}).
-type state() :: #s{}.
@@ -63,15 +63,16 @@
when Name :: ui_name().
show_ui(Name) ->
gen_server:cast(?MODULE, {show_ui, Name}).
gen_server:call(?MODULE, {show_ui, Name}).
-spec open_wallet(Path, Phrase) -> ok
-spec open_wallet(Path, Phrase) -> Result
when Path :: file:filename(),
Phrase :: string().
Phrase :: string(),
Result :: ok | {error, Reason :: term()}.
open_wallet(Path, Phrase) ->
gen_server:cast(?MODULE, {open_wallet, Path, Phrase}).
gen_server:call(?MODULE, {open_wallet, Path, Phrase}).
-spec close_wallet() -> ok.
@@ -217,7 +218,7 @@ deploy(Build, Params, InitArgs) ->
Size :: 256,
Name :: string(),
Seed :: string(),
Encoding :: utf8 | base64 | base58,
Encoding :: utf8 | base64 | base58 | none,
Transform :: {Algo, Yugeness},
Algo :: sha3 | sha2 | x_or | pbkdf2,
Yugeness :: rand | non_neg_integer().
@@ -328,6 +329,7 @@ init(none) ->
T = erlang:send_after(tic(), self(), tic),
State = #s{window = Window, timer = T, wallets = Wallets, prefs = Prefs},
NewState = do_show_ui(gd_v_wallman, State),
ok = gd_v_wallman:first_run(),
{ok, NewState}.
@@ -365,6 +367,9 @@ handle_call(list_keys, _, State) ->
handle_call({nonce, ID}, _, State) ->
Response = do_nonce(ID),
{reply, Response, State};
handle_call({open_wallet, Path, Phrase}, _, State) ->
{Response, NewState} = do_open_wallet(Path, Phrase, State),
{reply, Response, NewState};
handle_call(network, _, State) ->
Response = do_network(State),
{reply, Response, State};
@@ -374,6 +379,9 @@ handle_call({save, Module, Prefs}, _, State) ->
handle_call({mnemonic, ID}, _, State) ->
Response = do_mnemonic(ID, State),
{reply, Response, State};
handle_call({show_ui, Name}, _, State) ->
NewState = do_show_ui(Name, State),
{reply, ok, NewState};
handle_call(Unexpected, From, State) ->
ok = log(warning, "Unexpected call from ~tp: ~tp~n", [From, Unexpected]),
{noreply, State}.
@@ -387,16 +395,11 @@ handle_call(Unexpected, From, State) ->
%% The gen_server:handle_cast/2 callback.
%% See: http://erlang.org/doc/man/gen_server.html#Module:handle_cast-2
handle_cast({show_ui, Name}, State) ->
NewState = do_show_ui(Name, State),
{noreply, NewState};
handle_cast({open_wallet, Path, Phrase}, State) ->
NewState = do_open_wallet(Path, Phrase, State),
{noreply, NewState};
handle_cast(close_wallet, State) ->
NextState = do_close_wallet(State),
ok = gd_gui:show([]),
NewState = do_show_ui(gd_v_wallman, NextState),
ok = gd_v_wallman:to_front(),
{noreply, NewState};
handle_cast({new_wallet, Net, Name, Path, Password}, State) ->
NewState = do_new_wallet(Net, Name, Path, Password, State),
@@ -477,6 +480,9 @@ handle_cast(Unexpected, State) ->
handle_info(tic, State) ->
NewState = do_tic(State),
{noreply, NewState};
handle_info({show_ui, Name}, State) ->
NewState = do_show_ui(Name, State),
{noreply, NewState};
handle_info({'DOWN', Mon, process, PID, Info}, State) ->
NewState = handle_down(Mon, PID, Info, State),
{noreply, NewState};
@@ -531,7 +537,6 @@ do_show_ui(Name, State = #s{tasks = Tasks, prefs = Prefs}) ->
Win = Name:start_link({TaskPrefs, TaskData}),
PID = wx_object:get_pid(Win),
Mon = monitor(process, PID),
ok = Name:to_front(Win),
UI = #ui{name = Name, pid = PID, wx = Win, mon = Mon},
State#s{tasks = [UI | Tasks]}
end.
@@ -863,7 +868,9 @@ do_make_key(Name, Seed, base58, Transform, State) ->
do_make_key2(_, _, _, State = #s{wallet = none}) ->
ok = gd_gui:trouble("No wallet selected!"),
do_show_ui(gd_v_wallman, State);
NewState = do_show_ui(gd_v_wallman, State),
ok = gd_v_wallman:to_front(),
NewState;
do_make_key2(Name, Bin, Transform,
State = #s{wallet = Current, wallets = Wallets, pass = Pass}) ->
#wallet{name = WalletName, poas = POAs, keys = Keys} = Current,
@@ -1020,17 +1027,12 @@ do_open_wallet(Path, Phrase, State) ->
{ok, ChainID} -> gd_gui:chain(ChainID, Node);
Error -> gd_gui:trouble(Error)
end,
State#s{pass = Pass, wallet = Recovered};
{ok, State#s{pass = Pass, wallet = Recovered}};
Error ->
ok = gd_gui:trouble(Error),
New = default_wallet(),
State#s{wallet = New}
{Error, State}
end.
default_wallet() ->
default_wallet(testnet).
default_wallet(mainnet) ->
Node = #node{ip = "groot.mainnet.gajumaru.io"},
Groot = #chain{id = <<"groot.mainnet">>,