WIP
This commit is contained in:
parent
cb21cefb24
commit
a286c00783
@ -1,19 +1,83 @@
|
||||
-record(ak,
|
||||
% Node, Chain and Net represent the physical network.
|
||||
|
||||
-record(node,
|
||||
{ip = {161,97,102,143} :: inet:ip_address(),
|
||||
external = 3013 :: inet:port_number(), % 3013
|
||||
internal = none :: none | inet:port_number(), % 3113
|
||||
rosetta = none :: none | inet:port_number(), % 8080
|
||||
channel = none :: none | inet:port_number(), % 3014
|
||||
mdw = none :: none | inet:port_number()}). % 4000
|
||||
|
||||
|
||||
-record(chain,
|
||||
{id = "mint.devnet" :: string(),
|
||||
coins = ["gaju"] :: [string()],
|
||||
nodes = [#node{}] :: [#node{}]}).
|
||||
|
||||
|
||||
-record(net,
|
||||
{id = "devnet" :: string(),
|
||||
chains = [#chain{}] :: [#chain{}]}).
|
||||
|
||||
|
||||
|
||||
% AC and Coin represent the financial authority graph for a given coin.
|
||||
|
||||
-record(ac,
|
||||
{id = none :: string(),
|
||||
acs = [] :: [#ac{}]}).
|
||||
|
||||
|
||||
-record(coin,
|
||||
{id = "gaju" :: string(),
|
||||
mint = "mint.devnet" :: string(),
|
||||
acs = [#ac{}] :: [#ac{}]}).
|
||||
|
||||
|
||||
|
||||
% Balance, POA, Key, TXs, all culminate in capturing a complete Wallet view.
|
||||
-record(balance,
|
||||
{coin = "gaju" :: string(),
|
||||
total = 0 :: non_neg_integer(),
|
||||
dist = [{"mint.devnet", 0}] :: [{Chain :: string(), non_neg_integer()}]}).
|
||||
|
||||
|
||||
-record(poa,
|
||||
{name = "" :: string(),
|
||||
id = <<>> :: clutch:id(),
|
||||
balance = 0 :: non_neg_integer(),
|
||||
balances = [#balance{}] :: [#balance{}],
|
||||
history = [] :: [clutch:tx()],
|
||||
checked = never :: never | clutch:ts()}).
|
||||
|
||||
|
||||
-record(key,
|
||||
{name = "" :: string(),
|
||||
id = <<>> :: clutch:id(),
|
||||
pair = #{} :: #{public := binary(), secret := binary()},
|
||||
type = {{eddsa, ed25519}, 256} :: {Cipher :: term(), Size :: pos_integer()}}).
|
||||
|
||||
|
||||
-record(tx,
|
||||
{id = none :: none | clutch:id(),
|
||||
amount = 0 :: non_neg_integer(),
|
||||
type = spend :: spend | atom()}).
|
||||
|
||||
|
||||
-record(key,
|
||||
{name = "" :: string(),
|
||||
id = <<>> :: clutch:id(),
|
||||
pair = #{} :: #{public := binary(), secret := binary()},
|
||||
type = {{eddsa, ed25519}, 256} :: {Cipher :: term(), Size :: pos_integer()}}).
|
||||
-record(spend_tx,
|
||||
{sender_id = <<>> :: clutch:id(),
|
||||
recipient_id = <<>> :: clutch:id(),
|
||||
amount = 0 :: non_neg_integer(),
|
||||
gas_price = 0 :: non_neg_integer(),
|
||||
gas = 0 :: non_neg_integer(),
|
||||
ttl = 1 :: pos_integer(),
|
||||
nonce = 0 :: non_neg_integer(),
|
||||
payload = <<>> :: binary()}).
|
||||
|
||||
|
||||
-record(wallet,
|
||||
{version = 1 :: integer(),
|
||||
poas = [] :: [#poa{}],
|
||||
keys = [] :: [#key{}],
|
||||
pass = none :: none | binary(),
|
||||
network_id = <<"mint.devnet">> :: binary(),
|
||||
chains = [#chain{}] :: [#chain{}]}).
|
||||
|
@ -12,7 +12,7 @@
|
||||
-export([ts/0]).
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
-export_type([id/0, key/0, ak/0, tx/0, ts/0]).
|
||||
-export_type([id/0, key/0, poa/0, tx/0, ts/0]).
|
||||
|
||||
-include("$zx_include/zx_logger.hrl").
|
||||
-include("gmc.hrl").
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
-type id() :: binary().
|
||||
-type key() :: #key{}.
|
||||
-type ak() :: #ak{}.
|
||||
-type poa() :: #poa{}.
|
||||
-type tx() :: #tx{}.
|
||||
-type ts() :: integer().
|
||||
|
||||
|
242
src/gmc_con.erl
242
src/gmc_con.erl
@ -11,8 +11,8 @@
|
||||
-license("GPL-3.0-or-later").
|
||||
|
||||
-behavior(gen_server).
|
||||
-export([make_key/6, recover_key/1, mnemonic/1, rename_key/2, drop_key/1,
|
||||
login/1, password/2]). % add_key/1, drop_key/1]).
|
||||
-export([open_wallet/2, close_wallet/0, password/2,
|
||||
make_key/6, recover_key/1, mnemonic/1, rename_key/2, drop_key/1]).
|
||||
-export([encrypt/2, decrypt/2]).
|
||||
-export([start_link/0, stop/0, save/1]).
|
||||
-export([init/1, terminate/2, code_change/3,
|
||||
@ -26,26 +26,43 @@
|
||||
|
||||
|
||||
-record(s,
|
||||
{window = none :: none | wx:wx_object(),
|
||||
accounts = [] :: [clutch:ak()],
|
||||
pass = none :: none | binary(),
|
||||
keys = [] :: [clutch:key()],
|
||||
chains = [] :: [chain()],
|
||||
{version = 1 :: integer(),
|
||||
window = none :: none | wx:wx_object(),
|
||||
wallet = #wallet{} :: #wallet{},
|
||||
prefs = #{} :: #{atom() := term()}}).
|
||||
|
||||
-record(chain,
|
||||
{id = "" :: string(),
|
||||
nodes = [] :: [address()],
|
||||
mdws = [] :: [address()]}).
|
||||
|
||||
-type state() :: #s{}.
|
||||
-type chain() :: tuple().
|
||||
-type address() :: {inet:ip_address(), inet:port_number()}.
|
||||
|
||||
|
||||
|
||||
%% Interface
|
||||
|
||||
|
||||
-spec open_wallet(Path, Password) -> {ok, Wallet} | {error, Reason}
|
||||
when Path :: file:filename(),
|
||||
Password :: string(),
|
||||
Wallet :: {Accounts :: [clutch:ak()], Selected :: integer()},
|
||||
Reason :: bad_password | file:posix().
|
||||
|
||||
open_wallet(Path, Password) ->
|
||||
gen_server:call(?MODULE, {open_wallet, Path, Password}).
|
||||
|
||||
|
||||
-spec close_wallet() -> ok.
|
||||
|
||||
close_wallet() ->
|
||||
gen_server:cast(?MODULE, close_wallet).
|
||||
|
||||
|
||||
-spec password(Old, New) -> ok
|
||||
when Old :: none | string(),
|
||||
New :: none | string().
|
||||
|
||||
password(Old, New) ->
|
||||
gen_server:cast(?MODULE, {password, Old, New}).
|
||||
|
||||
|
||||
-spec make_key(Type, Size, Name, Seed, Encoding, Transform) -> ok
|
||||
when Type :: {eddsa, ed25519},
|
||||
Size :: 256,
|
||||
@ -101,21 +118,6 @@ stop() ->
|
||||
gen_server:cast(?MODULE, stop).
|
||||
|
||||
|
||||
-spec login(Phrase) -> ok
|
||||
when Phrase :: string().
|
||||
|
||||
login(Phrase) ->
|
||||
gen_server:cast(?MODULE, {login, Phrase}).
|
||||
|
||||
|
||||
-spec password(Old, New) -> ok
|
||||
when Old :: none | string(),
|
||||
New :: none | string().
|
||||
|
||||
password(Old, New) ->
|
||||
gen_server:cast(?MODULE, {password, Old, New}).
|
||||
|
||||
|
||||
-spec save(Prefs) -> ok | {error, Reason}
|
||||
when Prefs :: #{atom() := term()},
|
||||
Reason :: file:posix().
|
||||
@ -147,11 +149,8 @@ init(none) ->
|
||||
ok = log(info, "Starting"),
|
||||
Prefs = read_prefs(),
|
||||
Window = gmc_gui:start_link(Prefs),
|
||||
ok = log(info, "Window: ~p", [Window]),
|
||||
ok = gmc_gui:ask_password(),
|
||||
State = #s{window = Window},
|
||||
ArgV = zx_daemon:argv(),
|
||||
ok = gmc_gui:show(ArgV),
|
||||
State = #s{window = Window, prefs = Prefs},
|
||||
{ok, State}.
|
||||
|
||||
|
||||
@ -183,6 +182,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({open_wallet, Path, Phrase}, _, State) ->
|
||||
{Response, NewState} = do_open_wallet(Path, Phrase, State),
|
||||
{reply, Response, NewState};
|
||||
handle_call({save, Prefs}, _, State) ->
|
||||
Response = do_save(State#s{prefs = Prefs}),
|
||||
{reply, Response, State};
|
||||
@ -214,15 +216,12 @@ handle_cast({rename_key, ID, NewName}, State) ->
|
||||
handle_cast({drop_key, ID}, State) ->
|
||||
NewState = do_drop_key(ID, State),
|
||||
{noreply, NewState};
|
||||
handle_cast({login, Phrase}, State) ->
|
||||
NewState = do_login(Phrase, State),
|
||||
{noreply, NewState};
|
||||
handle_cast({password, Old, New}, State) ->
|
||||
NewState = do_password(Old, New, State),
|
||||
{noreply, NewState};
|
||||
handle_cast(stop, State) ->
|
||||
ok = log(info, "Received a 'stop' message."),
|
||||
{stop, normal, State};
|
||||
ok = zx:stop(),
|
||||
{noreply, State};
|
||||
handle_cast(Unexpected, State) ->
|
||||
ok = tell(warning, "Unexpected cast: ~tp~n", [Unexpected]),
|
||||
{noreply, State}.
|
||||
@ -284,15 +283,17 @@ do_make_key(Name, Seed, base58, Transform, State) ->
|
||||
State
|
||||
end.
|
||||
|
||||
do_make_key2(Name, Bin, Transform, State = #s{accounts = Accounts, keys = Keys}) ->
|
||||
do_make_key2(Name, Bin, Transform, State = #s{wallet = W}) ->
|
||||
#wallet{poas = POAs, keys = Keys} = W,
|
||||
T = transform(Transform),
|
||||
Seed = T(Bin),
|
||||
Key = #key{name = KeyName, id = ID} = gmc_key_master:make_key(Name, Seed),
|
||||
Account = #ak{name = KeyName, id = ID},
|
||||
POA = #poa{name = KeyName, id = ID},
|
||||
NewKeys = [Key | Keys],
|
||||
NewAccounts = [Account | Accounts],
|
||||
ok = gmc_gui:show(NewAccounts),
|
||||
State#s{accounts = NewAccounts, keys = NewKeys}.
|
||||
NewPOAs = [POA | POAs],
|
||||
NewWallet = W#wallet{poas = NewPOAs, keys = NewKeys},
|
||||
ok = gmc_gui:show(NewPOAs),
|
||||
State#s{wallet = NewWallet}.
|
||||
|
||||
|
||||
base64_decode(String) ->
|
||||
@ -324,7 +325,7 @@ t_xor(B, A) ->
|
||||
crypto:exor(H, A).
|
||||
|
||||
|
||||
do_recover_key(Mnemonic, State = #s{keys = Keys, accounts = Accounts}) ->
|
||||
do_recover_key(Mnemonic, State) ->
|
||||
case gmc_key_master:decode(Mnemonic) of
|
||||
{ok, Seed} ->
|
||||
do_recover_key2(Seed, State);
|
||||
@ -333,21 +334,23 @@ do_recover_key(Mnemonic, State = #s{keys = Keys, accounts = Accounts}) ->
|
||||
State
|
||||
end.
|
||||
|
||||
do_recover_key2(Seed, State = #s{keys = Keys, accounts = Accounts}) ->
|
||||
do_recover_key2(Seed, State = #s{wallet = W}) ->
|
||||
#wallet{keys = Keys, poas = POAs} = W,
|
||||
Recovered = #key{id = ID, name = Name} = gmc_key_master:make_key("", Seed),
|
||||
case lists:keymember(ID, #key.id, Keys) of
|
||||
false ->
|
||||
NewKeys = [Recovered | Keys],
|
||||
Account = #ak{name = Name, id = ID},
|
||||
NewAccounts = [Account | Accounts],
|
||||
ok = gmc_gui:show(NewAccounts),
|
||||
State#s{accounts = NewAccounts, keys = NewKeys};
|
||||
POA = #poa{name = Name, id = ID},
|
||||
NewPOAs = [POA | POAs],
|
||||
ok = gmc_gui:show(NewPOAs),
|
||||
NewWallet = W#wallet{poas = NewPOAs, keys = NewKeys},
|
||||
State#s{wallet = NewWallet};
|
||||
true ->
|
||||
State
|
||||
end.
|
||||
|
||||
|
||||
do_mnemonic(ID, #s{keys = Keys}) ->
|
||||
do_mnemonic(ID, #s{wallet = #wallet{keys = Keys}}) ->
|
||||
case lists:keyfind(ID, #key.id, Keys) of
|
||||
#key{pair = #{secret := <<K:32/binary, _/binary>>}} ->
|
||||
Mnemonic = gmc_key_master:encode(K),
|
||||
@ -357,20 +360,24 @@ do_mnemonic(ID, #s{keys = Keys}) ->
|
||||
end.
|
||||
|
||||
|
||||
do_rename_key(ID, NewName, State = #s{accounts = Accounts, keys = Keys}) ->
|
||||
A = lists:keyfind(ID, #ak.id, Accounts),
|
||||
do_rename_key(ID, NewName, State = #s{wallet = W}) ->
|
||||
#wallet{poas = POAs, keys = Keys} = W,
|
||||
A = lists:keyfind(ID, #poa.id, POAs),
|
||||
K = lists:keyfind(ID, #key.id, Keys),
|
||||
NewAccounts = lists:keystore(ID, #ak.id, Accounts, A#ak{name = NewName}),
|
||||
NewPOAs = lists:keystore(ID, #poa.id, POAs, A#poa{name = NewName}),
|
||||
NewKeys = lists:keystore(ID, #key.id, Keys, K#key{name = NewName}),
|
||||
ok = gmc_gui:show(NewAccounts),
|
||||
State#s{accounts = NewAccounts, keys = NewKeys}.
|
||||
NewWallet = W#wallet{poas = NewPOAs, keys = NewKeys},
|
||||
ok = gmc_gui:show(NewPOAs),
|
||||
State#s{wallet = NewWallet}.
|
||||
|
||||
|
||||
do_drop_key(ID, State = #s{accounts = Accounts, keys = Keys}) ->
|
||||
NewAccounts = lists:keydelete(ID, #ak.id, Accounts),
|
||||
do_drop_key(ID, State = #s{wallet = W}) ->
|
||||
#wallet{poas = POAs, keys = Keys} = W,
|
||||
NewPOAs = lists:keydelete(ID, #poa.id, POAs),
|
||||
NewKeys = lists:keydelete(ID, #key.id, Keys),
|
||||
ok = gmc_gui:show(NewAccounts),
|
||||
State#s{accounts = NewAccounts, keys = NewKeys}.
|
||||
NewWallet = W#wallet{poas = NewPOAs, keys = NewKeys},
|
||||
ok = gmc_gui:show(NewPOAs),
|
||||
State#s{wallet = NewWallet}.
|
||||
|
||||
|
||||
encrypt(Pass, Binary) ->
|
||||
@ -387,74 +394,127 @@ pass(Phrase) ->
|
||||
crypto:hash(sha3_256, Phrase).
|
||||
|
||||
|
||||
do_login(none, State) ->
|
||||
do_open_wallet(Path, none, State) ->
|
||||
case read(none) of
|
||||
{ok, Recovered = #s{accounts = Accounts}} ->
|
||||
ok = gmc_gui:show(Accounts),
|
||||
Recovered;
|
||||
error ->
|
||||
State
|
||||
{ok, Recovered = #wallet{poas = POAs}} -> {POAs, State#s{wallet = Recovered}};
|
||||
Error -> {Error, State}
|
||||
end;
|
||||
do_login(Phrase, State = #s{pass = none}) ->
|
||||
do_open_wallet(Path, Phrase, State) ->
|
||||
Pass = pass(Phrase),
|
||||
try
|
||||
case read(Pass) of
|
||||
{ok, Recovered = #s{accounts = Accounts}} ->
|
||||
ok = gmc_gui:show(Accounts),
|
||||
Recovered;
|
||||
error ->
|
||||
State#s{pass = Pass}
|
||||
end
|
||||
catch
|
||||
E:R ->
|
||||
ok = tell("Problem with loading state: {~p, ~p}", [E, R]),
|
||||
ok = gmc_gui:ask_password(),
|
||||
State
|
||||
{ok, Recovered = #wallet{poas = POAs}} -> {POAs, State#s{wallet = Recovered}};
|
||||
Error -> {Error, State}
|
||||
end.
|
||||
|
||||
|
||||
do_password(none, none, State) ->
|
||||
State;
|
||||
do_password(none, New, State = #s{pass = none}) ->
|
||||
do_password(none, New, State = #s{wallet = #wallet{pass = none}}) ->
|
||||
Pass = pass(New),
|
||||
State#s{pass = Pass};
|
||||
do_password(Old, none, State = #s{pass = Pass}) ->
|
||||
State#s{wallet = #wallet{pass = Pass}};
|
||||
do_password(Old, none, State = #s{wallet = #wallet{pass = Pass}}) ->
|
||||
case pass(Old) =:= Pass of
|
||||
true -> State#s{pass = none};
|
||||
true -> State#s{wallet = #wallet{pass = none}};
|
||||
false -> State
|
||||
end;
|
||||
do_password(Old, New, State = #s{pass = Pass}) ->
|
||||
do_password(Old, New, State = #s{wallet = #wallet{pass = Pass}}) ->
|
||||
case pass(Old) =:= Pass of
|
||||
true -> State#s{pass = pass(New)};
|
||||
true -> State#s{wallet = #wallet{pass = pass(New)}};
|
||||
false -> State
|
||||
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);
|
||||
false ->
|
||||
log(warning, "Tried do_spend with a bad key: ~p", [KeyID])
|
||||
end.
|
||||
|
||||
do_spend2(PrivKey,
|
||||
#spend_tx{sender_id = SenderID,
|
||||
recipient_id = RecipientId,
|
||||
amount = Amount,
|
||||
gas_price = GasPrice,
|
||||
gas = Gas,
|
||||
ttl = TTL,
|
||||
nonce = Nonce,
|
||||
payload = Payload},
|
||||
#s{wallet = #wallet{network_id = NetworkID}}) ->
|
||||
Type = spend_tx,
|
||||
Vsn = 1,
|
||||
Fields =
|
||||
[{sender_id, SenderID},
|
||||
{recipient_id, RecipientId},
|
||||
{amount, Amount},
|
||||
{gas_price, GasPrice},
|
||||
{gas, Gas},
|
||||
{ttl, TTL},
|
||||
{nonce, Nonce},
|
||||
{payload, Payload}],
|
||||
Template =
|
||||
[{sender_id, id},
|
||||
{recipient_id, id},
|
||||
{amount, int},
|
||||
{gas_price, int},
|
||||
{gas, int},
|
||||
{ttl, int},
|
||||
{nonce, int},
|
||||
{payload, binary}],
|
||||
BinaryTX = aeser_chain_objects:serialize(Type, Vsn, Template, Fields),
|
||||
NetworkTX = <<NetworkID/binary, BinaryTX/binary>>,
|
||||
Signature = ecu_eddsa:sign_detached(NetworkTX, PrivKey),
|
||||
SigTxType = signed_tx,
|
||||
SigTxVsn = 1,
|
||||
SigTemplate =
|
||||
[{signatures, [binary]},
|
||||
{transaction, binary}],
|
||||
TX_Data =
|
||||
[{signatures, [Signature]},
|
||||
{transaction, NetworkTX}],
|
||||
SignedTX = aeser_chain_objects:serialize(SigTxType, SigTxVsn, SigTemplate, TX_Data),
|
||||
tell("SpendTX: ~p", [SignedTX]).
|
||||
|
||||
|
||||
do_save(State = #s{prefs = Prefs}) ->
|
||||
ok = persist(Prefs),
|
||||
do_save2(State).
|
||||
|
||||
|
||||
do_save2(State = #s{pass = none}) ->
|
||||
do_save2(State = #s{wallet = W = #wallet{pass = none}}) ->
|
||||
Path = save_path(),
|
||||
ok = filelib:ensure_dir(Path),
|
||||
file:write_file(Path, term_to_binary(State));
|
||||
do_save2(State = #s{pass = Pass}) ->
|
||||
file:write_file(Path, term_to_binary(W));
|
||||
do_save2(State = #s{wallet = W = #wallet{pass = Pass}}) ->
|
||||
Path = save_path(),
|
||||
ok = filelib:ensure_dir(Path),
|
||||
Cipher = encrypt(Pass, term_to_binary(State)),
|
||||
Cipher = encrypt(Pass, term_to_binary(W)),
|
||||
file:write_file(Path, Cipher).
|
||||
|
||||
|
||||
read(none) ->
|
||||
case file:read_file(save_path()) of
|
||||
{ok, Bin} -> {ok, binary_to_term(Bin)};
|
||||
{error, enoent} -> error
|
||||
{ok, Bin} -> read2(Bin);
|
||||
Error -> Error
|
||||
end;
|
||||
read(Pass) ->
|
||||
case file:read_file(save_path()) of
|
||||
{ok, Cipher} -> {ok, binary_to_term(decrypt(Pass, Cipher))};
|
||||
{error, enoent} -> error
|
||||
{ok, Cipher} ->
|
||||
try
|
||||
Bin = decrypt(Pass, Cipher),
|
||||
read2(Bin)
|
||||
catch
|
||||
E:R -> {E, R}
|
||||
end;
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
read2(Bin) ->
|
||||
case zx_lib:b_to_t(Bin) of
|
||||
{ok, T} -> {ok, T};
|
||||
error -> {error, badarg}
|
||||
end.
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
lang = en :: en | jp,
|
||||
j = none :: none | fun(),
|
||||
prefs = #{} :: #{atom() := term()},
|
||||
accounts = [] :: [clutch:ak()],
|
||||
accounts = [] :: [clutch:poa()],
|
||||
picker = none :: none | wx:wx_object(),
|
||||
id = {#w{}, #w{}} :: labeled(),
|
||||
balance = {#w{}, #w{}} :: labeled(),
|
||||
@ -280,6 +280,7 @@ handle_event(#wx{event = #wxCommand{type = command_button_clicked},
|
||||
#w{name = drop_key} -> drop_key(State);
|
||||
#w{name = copy} -> copy(State);
|
||||
#w{name = www} -> www(State);
|
||||
#w{name = send} -> spend(State);
|
||||
#w{name = grids} -> grids_dialogue(State);
|
||||
#w{name = Name} -> handle_button(Name, State);
|
||||
false -> State
|
||||
@ -437,7 +438,7 @@ show_mnemonic(State = #s{picker = Picker}) ->
|
||||
end.
|
||||
|
||||
show_mnemonic(Selected, State = #s{frame = Frame, j = J, accounts = Accounts}) ->
|
||||
#ak{id = ID} = lists:nth(Selected, Accounts),
|
||||
#poa{id = ID} = lists:nth(Selected, Accounts),
|
||||
{ok, Mnemonic} = gmc_con:mnemonic(ID),
|
||||
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Mnemonic")),
|
||||
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
||||
@ -468,7 +469,7 @@ rename_key(State = #s{picker = Picker}) ->
|
||||
end.
|
||||
|
||||
rename_key(Selected, State = #s{frame = Frame, j = J, accounts = Accounts}) ->
|
||||
#ak{id = ID, name = Name} = lists:nth(Selected, Accounts),
|
||||
#poa{id = ID, name = Name} = lists:nth(Selected, Accounts),
|
||||
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("New Key")),
|
||||
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
||||
NameSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Name (Optional)")}]),
|
||||
@ -507,7 +508,7 @@ drop_key(State = #s{picker = Picker}) ->
|
||||
end.
|
||||
|
||||
drop_key(Selected, State = #s{frame = Frame, j = J, accounts = Accounts}) ->
|
||||
#ak{id = ID, name = Name} = lists:nth(Selected, Accounts),
|
||||
#poa{id = ID, name = Name} = lists:nth(Selected, Accounts),
|
||||
Dialog = wxDialog:new(Frame, ?wxID_ANY, J("New Key")),
|
||||
Sizer = wxBoxSizer:new(?wxVERTICAL),
|
||||
Message = ["REALLY delete key: ", Name, " ?"],
|
||||
@ -563,6 +564,43 @@ www(State = #s{id = {_, #w{wx = ID_T}}}) ->
|
||||
State.
|
||||
|
||||
|
||||
spend(State) ->
|
||||
tell("Would be doing a SpendTX"),
|
||||
State.
|
||||
|
||||
%spend(State = #s{accounts = []}) ->
|
||||
% State;
|
||||
%spend(State = #s{picker = Picker}) ->
|
||||
% case wxListBox:getSelection(Picker) of
|
||||
% -1 -> State;
|
||||
% Selected -> spend(Selected + 1, State)
|
||||
% end.
|
||||
|
||||
%spend(Selected, State = #s{frame = Frame, j = J, }) ->
|
||||
% #poa{id = ID, name = Name} = lists:nth(Selected, Accounts),
|
||||
% Dialog = wxDialog:new(Frame, ?wxID_ANY, J("New Key")),
|
||||
% Sizer = wxBoxSizer:new(?wxVERTICAL),
|
||||
% Account = [J("From: "), Name, " (", ID, ")"],
|
||||
% MessageT = wxStaticText:new(Dialog, ?wxID_ANY, Message),
|
||||
% 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)),
|
||||
% _ = wxBoxSizer:add(Sizer, MessageT, zxw:flags(wide)),
|
||||
% _ = wxBoxSizer:add(Sizer, ButtSz, zxw:flags(base)),
|
||||
% ok = wxDialog:setSizer(Dialog, Sizer),
|
||||
% ok = wxBoxSizer:layout(Sizer),
|
||||
% ok = wxFrame:center(Dialog),
|
||||
% ok =
|
||||
% case wxDialog:showModal(Dialog) of
|
||||
% ?wxID_OK -> gmc_con:drop_key(ID);
|
||||
% ?wxID_CANCEL -> ok
|
||||
% end,
|
||||
% ok = wxDialog:destroy(Dialog),
|
||||
% State State.
|
||||
|
||||
|
||||
grids_dialogue(State = #s{frame = Frame, j = J}) ->
|
||||
tell("Handle GRIDS URL"),
|
||||
% ok =
|
||||
@ -582,7 +620,8 @@ handle_button(Name, State) ->
|
||||
do_selection(Selected,
|
||||
State = #s{prefs = Prefs, accounts = Accounts,
|
||||
balance = {_, #w{wx = B}}, id = {_, #w{wx = I}}}) ->
|
||||
#ak{id = ID, balance = Pucks} = lists:nth(Selected + 1, Accounts),
|
||||
#poa{id = ID, balances = Balances} = lists:nth(Selected + 1, Accounts),
|
||||
[#balance{total = Pucks}] = Balances,
|
||||
ok = wxStaticText:setLabel(I, ID),
|
||||
ok = wxStaticText:setLabel(B, price_to_string(Pucks)),
|
||||
NewPrefs = maps:put(selected, Selected, Prefs),
|
||||
@ -590,7 +629,7 @@ do_selection(Selected,
|
||||
|
||||
|
||||
do_show(Accounts, State = #s{prefs = Prefs, picker = Picker}) ->
|
||||
AKs = [Name || #ak{name = Name} <- Accounts],
|
||||
AKs = [Name || #poa{name = Name} <- Accounts],
|
||||
ok = wxListBox:set(Picker, AKs),
|
||||
case Accounts of
|
||||
[] ->
|
||||
@ -622,6 +661,7 @@ do_ask_password(#s{frame = Frame, j = J}) ->
|
||||
ok = wxBoxSizer:layout(Sizer),
|
||||
ok = wxFrame:center(Dialog),
|
||||
ok = wxStyledTextCtrl:setFocus(PassTx),
|
||||
Path = filename:join(zx_lib:path(var, "otpr", "clutch"), "opaque.data"),
|
||||
ok =
|
||||
case wxDialog:showModal(Dialog) of
|
||||
?wxID_OK ->
|
||||
@ -630,9 +670,9 @@ do_ask_password(#s{frame = Frame, j = J}) ->
|
||||
"" -> none;
|
||||
P -> P
|
||||
end,
|
||||
gmc_con:login(Phrase);
|
||||
gmc_con:open_wallet(Path, Phrase);
|
||||
?wxID_CANCEL ->
|
||||
gmc_con:login(none)
|
||||
gmc_con:open_wallet(Path, none)
|
||||
end,
|
||||
wxDialog:destroy(Dialog).
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user