Current section
Files
Jump to
Current section
Files
src/gleeth@commands@wallet.erl
-module(gleeth@commands@wallet).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeth/commands/wallet.gleam").
-export([parse_args/1, run/1, print_usage/0, print_help/0]).
-export_type([wallet_operation/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type wallet_operation() :: {create_from_key, binary()} |
generate_new |
{show_info, binary()} |
{sign_message, binary(), binary()} |
{verify_message, binary(), binary(), binary()}.
-file("src/gleeth/commands/wallet.gleam", 29).
?DOC(" Parse wallet command arguments\n").
-spec parse_args(list(binary())) -> {ok, wallet_operation()} | {error, binary()}.
parse_args(Args) ->
case Args of
[<<"create"/utf8>>, <<"--private-key"/utf8>>, Key] ->
{ok, {create_from_key, Key}};
[<<"create"/utf8>>, <<"-k"/utf8>>, Key@1] ->
{ok, {create_from_key, Key@1}};
[<<"generate"/utf8>>] ->
{ok, generate_new};
[<<"info"/utf8>>, <<"--private-key"/utf8>>, Key@2] ->
{ok, {show_info, Key@2}};
[<<"info"/utf8>>, <<"-k"/utf8>>, Key@3] ->
{ok, {show_info, Key@3}};
[<<"sign"/utf8>>,
<<"--private-key"/utf8>>,
Key@4,
<<"--message"/utf8>>,
Message] ->
{ok, {sign_message, Key@4, Message}};
[<<"sign"/utf8>>, <<"-k"/utf8>>, Key@5, <<"-m"/utf8>>, Message@1] ->
{ok, {sign_message, Key@5, Message@1}};
[<<"verify"/utf8>>,
<<"--public-key"/utf8>>,
Pubkey,
<<"--message"/utf8>>,
Message@2,
<<"--signature"/utf8>>,
Sig] ->
{ok, {verify_message, Pubkey, Message@2, Sig}};
[<<"verify"/utf8>>,
<<"-p"/utf8>>,
Pubkey@1,
<<"-m"/utf8>>,
Message@3,
<<"-s"/utf8>>,
Sig@1] ->
{ok, {verify_message, Pubkey@1, Message@3, Sig@1}};
_ ->
{error,
<<"Invalid wallet command. Use: create|generate|info|sign|verify"/utf8>>}
end.
-file("src/gleeth/commands/wallet.gleam", 123).
?DOC(" Handle signing a message\n").
-spec handle_sign_message(binary(), binary()) -> {ok, nil} | {error, binary()}.
handle_sign_message(Private_key_hex, Message) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@validation:validate_private_key(
Private_key_hex
),
gleam@result:map_error(_pipe, fun(Err) -> case Err of
{parse_error, Msg} ->
Msg;
_ ->
<<"Invalid private key format"/utf8>>
end end)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@1 = gleeth@crypto@wallet:from_private_key_hex(
Private_key_hex
),
gleam@result:map_error(
_pipe@1,
fun(Err@1) ->
gleeth@crypto@wallet:error_to_string(Err@1)
end
)
end,
fun(Wallet_result) ->
gleam@result:'try'(
begin
_pipe@2 = gleeth@crypto@wallet:sign_personal_message(
Wallet_result,
Message
),
gleam@result:map_error(
_pipe@2,
fun(Err@2) ->
gleeth@crypto@wallet:error_to_string(Err@2)
end
)
end,
fun(Signature) ->
gleeth@ethereum@formatting:print_success(
<<"Message signed successfully!"/utf8>>
),
gleeth@ethereum@formatting:print_section(
<<""/utf8>>
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Message"/utf8>>,
Message
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Signature"/utf8>>,
gleeth@crypto@secp256k1:signature_to_hex(
Signature
)
),
{V, R, S} = gleeth@crypto@secp256k1:signature_to_vrs(
Signature
),
gleeth@ethereum@formatting:print_section(
<<"Signature components"/utf8>>
),
gleeth@ethereum@formatting:print_labeled_value(
<<"v"/utf8>>,
gleam@string:inspect(V)
),
gleeth@ethereum@formatting:print_labeled_value(
<<"r"/utf8>>,
R
),
gleeth@ethereum@formatting:print_labeled_value(
<<"s"/utf8>>,
S
),
{ok, nil}
end
)
end
)
end
).
-file("src/gleeth/commands/wallet.gleam", 239).
?DOC(" Parse signature from validated hex string\n").
-spec parse_signature_hex(binary()) -> {ok, gleeth@crypto@secp256k1:signature()} |
{error, binary()}.
parse_signature_hex(Signature_hex) ->
Clean_hex = gleeth@utils@hex:strip_prefix(Signature_hex),
R_hex = gleam@string:slice(Clean_hex, 0, 64),
S_hex = gleam@string:slice(Clean_hex, 64, 64),
V_hex = gleam@string:slice(Clean_hex, 128, 2),
gleam@result:'try'(
begin
_pipe = gleeth@utils@hex:decode(<<"0x"/utf8, R_hex/binary>>),
gleam@result:map_error(
_pipe,
fun(_) -> <<"Invalid r component in signature"/utf8>> end
)
end,
fun(R_bytes) ->
gleam@result:'try'(
begin
_pipe@1 = gleeth@utils@hex:decode(
<<"0x"/utf8, S_hex/binary>>
),
gleam@result:map_error(
_pipe@1,
fun(_) ->
<<"Invalid s component in signature"/utf8>>
end
)
end,
fun(S_bytes) ->
gleam@result:'try'(case gleam@int:base_parse(V_hex, 16) of
{ok, V} ->
{ok, V - 27};
{error, _} ->
{error,
<<"Invalid v component in signature"/utf8>>}
end, fun(V_int) ->
{ok, {signature, R_bytes, S_bytes, V_int}}
end)
end
)
end
).
-file("src/gleeth/commands/wallet.gleam", 165).
?DOC(" Handle verifying a message signature\n").
-spec handle_verify_message(binary(), binary(), binary()) -> {ok, nil} |
{error, binary()}.
handle_verify_message(Public_key_hex, Message, Signature_hex) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@validation:validate_public_key(Public_key_hex),
gleam@result:map_error(_pipe, fun(Err) -> case Err of
{parse_error, Msg} ->
Msg;
_ ->
<<"Invalid public key format"/utf8>>
end end)
end,
fun(Validated_pubkey) ->
gleam@result:'try'(
begin
_pipe@1 = gleeth@utils@hex:decode(Validated_pubkey),
gleam@result:map_error(
_pipe@1,
fun(_) -> <<"Failed to decode public key"/utf8>> end
)
end,
fun(Public_key_bytes) ->
Public_key = {public_key, Public_key_bytes},
gleam@result:'try'(
begin
_pipe@2 = gleeth@utils@validation:validate_signature(
Signature_hex
),
gleam@result:map_error(
_pipe@2,
fun(Err@1) -> case Err@1 of
{parse_error, Msg@1} ->
Msg@1;
_ ->
<<"Invalid signature format"/utf8>>
end end
)
end,
fun(Validated_signature) ->
gleam@result:'try'(
parse_signature_hex(Validated_signature),
fun(Signature) ->
Message_bytes = gleam_stdlib:identity(
Message
),
Message_length = begin
_pipe@3 = erlang:byte_size(
Message_bytes
),
gleam@string:inspect(_pipe@3)
end,
Prefix = <<"\\x19Ethereum Signed Message:\\n"/utf8,
Message_length/binary>>,
Prefix_bytes = gleam_stdlib:identity(Prefix),
Full_message = gleam@bit_array:append(
Prefix_bytes,
Message_bytes
),
Message_hash = gleeth@crypto@keccak:keccak256_binary(
Full_message
),
gleam@result:'try'(
gleeth@crypto@secp256k1:verify_signature(
Message_hash,
Signature,
Public_key
),
fun(Is_valid) -> case Is_valid of
true ->
gleeth@ethereum@formatting:print_success(
<<"Signature verification successful!"/utf8>>
),
gleeth@ethereum@formatting:print_section(
<<""/utf8>>
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Message"/utf8>>,
Message
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Public Key"/utf8>>,
Public_key_hex
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Signature"/utf8>>,
Signature_hex
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Status"/utf8>>,
<<"VALID ✓"/utf8>>
),
{ok, nil};
false ->
gleeth@ethereum@formatting:print_error(
<<"Signature verification failed!"/utf8>>
),
gleeth@ethereum@formatting:print_section(
<<""/utf8>>
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Message"/utf8>>,
Message
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Public Key"/utf8>>,
Public_key_hex
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Signature"/utf8>>,
Signature_hex
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Status"/utf8>>,
<<"INVALID ✗"/utf8>>
),
{error,
<<"Signature is not valid for the given message and public key"/utf8>>}
end end
)
end
)
end
)
end
)
end
).
-file("src/gleeth/commands/wallet.gleam", 266).
?DOC(" Print formatted wallet information\n").
-spec print_wallet_info(gleeth@crypto@wallet:wallet()) -> nil.
print_wallet_info(Wallet_obj) ->
Address = gleeth@crypto@wallet:get_address(Wallet_obj),
Private_key = gleeth@crypto@wallet:get_private_key_hex(Wallet_obj),
Public_key = gleeth@crypto@wallet:get_public_key_hex(Wallet_obj),
Is_valid = gleeth@crypto@wallet:is_valid(Wallet_obj),
gleeth@ethereum@formatting:print_labeled_value(
<<"Address"/utf8>>,
gleeth@ethereum@formatting:display_address(Address)
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Private Key"/utf8>>,
gleeth@utils@hex:normalize(Private_key)
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Public Key"/utf8>>,
gleeth@utils@hex:normalize(Public_key)
),
gleeth@ethereum@formatting:print_labeled_value(
<<"Valid"/utf8>>,
gleam@string:inspect(Is_valid)
).
-file("src/gleeth/commands/wallet.gleam", 61).
?DOC(" Handle creating wallet from private key\n").
-spec handle_create_from_key(binary()) -> {ok, nil} | {error, binary()}.
handle_create_from_key(Private_key_hex) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@validation:validate_private_key(
Private_key_hex
),
gleam@result:map_error(_pipe, fun(Err) -> case Err of
{parse_error, Msg} ->
Msg;
_ ->
<<"Invalid private key format"/utf8>>
end end)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@1 = gleeth@crypto@wallet:from_private_key_hex(
Private_key_hex
),
gleam@result:map_error(
_pipe@1,
fun(Err@1) ->
gleeth@crypto@wallet:error_to_string(Err@1)
end
)
end,
fun(Wallet_result) ->
gleeth@ethereum@formatting:print_success(
<<"Wallet created successfully!"/utf8>>
),
gleeth@ethereum@formatting:print_section(<<""/utf8>>),
print_wallet_info(Wallet_result),
{ok, nil}
end
)
end
).
-file("src/gleeth/commands/wallet.gleam", 84).
?DOC(" Handle generating new wallet\n").
-spec handle_generate_new() -> {ok, nil} | {error, binary()}.
handle_generate_new() ->
case gleeth@crypto@wallet:generate() of
{ok, New_wallet} ->
gleeth@ethereum@formatting:print_success(
<<"New wallet generated!"/utf8>>
),
gleeth@ethereum@formatting:print_warning(
<<"WARNING: Save your private key securely!"/utf8>>
),
gleeth@ethereum@formatting:print_section(<<""/utf8>>),
print_wallet_info(New_wallet),
{ok, nil};
{error, Err} ->
{error,
<<"Failed to generate wallet: "/utf8,
(gleeth@crypto@wallet:error_to_string(Err))/binary>>}
end.
-file("src/gleeth/commands/wallet.gleam", 100).
?DOC(" Handle showing wallet info\n").
-spec handle_show_info(binary()) -> {ok, nil} | {error, binary()}.
handle_show_info(Private_key_hex) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@validation:validate_private_key(
Private_key_hex
),
gleam@result:map_error(_pipe, fun(Err) -> case Err of
{parse_error, Msg} ->
Msg;
_ ->
<<"Invalid private key format"/utf8>>
end end)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@1 = gleeth@crypto@wallet:from_private_key_hex(
Private_key_hex
),
gleam@result:map_error(
_pipe@1,
fun(Err@1) ->
gleeth@crypto@wallet:error_to_string(Err@1)
end
)
end,
fun(Wallet_result) ->
gleeth@ethereum@formatting:print_info(
<<"Wallet Information:"/utf8>>
),
gleeth@ethereum@formatting:print_section(<<""/utf8>>),
print_wallet_info(Wallet_result),
{ok, nil}
end
)
end
).
-file("src/gleeth/commands/wallet.gleam", 48).
?DOC(" Execute wallet operation\n").
-spec run(wallet_operation()) -> {ok, nil} | {error, binary()}.
run(Operation) ->
case Operation of
{create_from_key, Private_key} ->
handle_create_from_key(Private_key);
generate_new ->
handle_generate_new();
{show_info, Private_key@1} ->
handle_show_info(Private_key@1);
{sign_message, Private_key@2, Message} ->
handle_sign_message(Private_key@2, Message);
{verify_message, Public_key, Message@1, Signature} ->
handle_verify_message(Public_key, Message@1, Signature)
end.
-file("src/gleeth/commands/wallet.gleam", 279).
?DOC(" Print usage information\n").
-spec print_usage() -> nil.
print_usage() ->
gleam_stdlib:println(<<"Usage: gleeth wallet <command> [options]"/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Commands:"/utf8>>),
gleam_stdlib:println(
<<" create --private-key <key> Create wallet from private key"/utf8>>
),
gleam_stdlib:println(
<<" generate Generate new random wallet"/utf8>>
),
gleam_stdlib:println(
<<" info --private-key <key> Show wallet information"/utf8>>
),
gleam_stdlib:println(
<<" sign --private-key <key> --message <msg> Sign a message"/utf8>>
),
gleam_stdlib:println(
<<" verify --public-key <key> --message <msg> --signature <sig> Verify a signature"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Options:"/utf8>>),
gleam_stdlib:println(
<<" --private-key, -k <key> Private key (hex format)"/utf8>>
),
gleam_stdlib:println(
<<" --public-key, -p <key> Public key (hex format)"/utf8>>
),
gleam_stdlib:println(
<<" --message, -m <message> Message to sign/verify"/utf8>>
),
gleam_stdlib:println(
<<" --signature, -s <signature> Signature to verify (hex format)"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Examples:"/utf8>>),
gleam_stdlib:println(<<" gleeth wallet create -k 0x1234..."/utf8>>),
gleam_stdlib:println(<<" gleeth wallet generate"/utf8>>),
gleam_stdlib:println(<<" gleeth wallet info -k 0x1234..."/utf8>>),
gleam_stdlib:println(
<<" gleeth wallet sign -k 0x1234... -m 'Hello World'"/utf8>>
),
gleam_stdlib:println(
<<" gleeth wallet verify -p 0x04abc... -m 'Hello World' -s 0xdef..."/utf8>>
).
-file("src/gleeth/commands/wallet.gleam", 308).
?DOC(" Print help for wallet command\n").
-spec print_help() -> nil.
print_help() ->
gleam_stdlib:println(<<"Gleeth Wallet Management"/utf8>>),
gleam_stdlib:println(<<"========================"/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Manage Ethereum wallets and sign messages."/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
print_usage(),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Security Notes:"/utf8>>),
gleam_stdlib:println(<<"- Never share your private key"/utf8>>),
gleam_stdlib:println(<<"- Store private keys securely"/utf8>>),
gleam_stdlib:println(<<"- Use hardware wallets for large amounts"/utf8>>),
gleam_stdlib:println(<<"- Test on testnets before mainnet"/utf8>>).