Packages

Ethereum library for Gleam - JSON-RPC client, transaction signing, ABI encoding, and wallet management on the BEAM

Current section

Files

Jump to
gleeth src gleeth@cli.erl
Raw

src/gleeth@cli.erl

-module(gleeth@cli).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeth/cli.gleam").
-export([parse_args/1, show_help/0]).
-export_type([command/0, args/0]).
-type command() :: block_number |
{balance, list(binary()), gleam@option:option(binary())} |
{call, binary(), binary(), list(binary()), gleam@option:option(binary())} |
{transaction, binary()} |
{code, binary()} |
{estimate_gas, binary(), binary(), binary(), binary()} |
{storage_at, binary(), binary(), binary()} |
{get_logs, binary(), binary(), binary(), list(binary())} |
{send, binary(), binary(), binary(), binary(), binary(), boolean()} |
{wallet, list(binary())} |
help.
-type args() :: {args, command(), binary()}.
-file("src/gleeth/cli.gleam", 185).
-spec split_until_flag(list(binary())) -> {list(binary()), list(binary())}.
split_until_flag(Args) ->
case Args of
[] ->
{[], []};
[Arg | Rest] ->
case gleam_stdlib:string_starts_with(Arg, <<"--"/utf8>>) of
true ->
{[], Args};
false ->
{Addresses, Remaining} = split_until_flag(Rest),
{[Arg | Addresses], Remaining}
end
end.
-file("src/gleeth/cli.gleam", 201).
-spec get_env_rpc_url() -> {ok, binary()} | {error, nil}.
get_env_rpc_url() ->
gleeth_ffi:get_env(<<"GLEETH_RPC_URL"/utf8>>).
-file("src/gleeth/cli.gleam", 129).
-spec extract_rpc_url(list(binary())) -> {ok, binary()} |
{error, gleeth@rpc@types:gleeth_error()}.
extract_rpc_url(Args) ->
case Args of
[<<"--rpc-url"/utf8>>, Url | _] ->
{ok, Url};
[] ->
case get_env_rpc_url() of
{ok, Url@1} ->
{ok, Url@1};
{error, _} ->
{error,
{config_error,
<<"RPC URL required. Use --rpc-url or set GLEETH_RPC_URL environment variable."/utf8>>}}
end;
_ ->
{error,
{config_error,
<<"Invalid arguments. RPC URL must be specified with --rpc-url."/utf8>>}}
end.
-file("src/gleeth/cli.gleam", 150).
-spec parse_balance_args(list(binary())) -> {ok,
{list(binary()), gleam@option:option(binary()), binary()}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_balance_args(Args) ->
case Args of
[<<"--file"/utf8>>, Filename | Rest] ->
gleam@result:'try'(
extract_rpc_url(Rest),
fun(Rpc_url) -> {ok, {[], {some, Filename}, Rpc_url}} end
);
[<<"-f"/utf8>>, Filename@1 | Rest@1] ->
gleam@result:'try'(
extract_rpc_url(Rest@1),
fun(Rpc_url@1) -> {ok, {[], {some, Filename@1}, Rpc_url@1}} end
);
_ ->
{Address_args, Remaining} = split_until_flag(Args),
case Address_args of
[] ->
{error,
{config_error,
<<"At least one address or --file must be specified"/utf8>>}};
_ ->
gleam@result:'try'(
gleeth@utils@validation:validate_addresses(Address_args),
fun(Validated_addresses) ->
gleam@result:'try'(
extract_rpc_url(Remaining),
fun(Rpc_url@2) ->
{ok, {Validated_addresses, none, Rpc_url@2}}
end
)
end
)
end
end.
-file("src/gleeth/cli.gleam", 215).
-spec extract_call_args_helper(
list(binary()),
list(binary()),
gleam@option:option(binary())
) -> {list(binary()), gleam@option:option(binary()), list(binary())}.
extract_call_args_helper(Args, Parameters, Abi_file) ->
case Args of
[<<"--rpc-url"/utf8>> | _] ->
{lists:reverse(Parameters), Abi_file, Args};
[<<"--abi"/utf8>>, File | Rest] ->
extract_call_args_helper(Rest, Parameters, {some, File});
[Param | Rest@1] ->
extract_call_args_helper(Rest@1, [Param | Parameters], Abi_file);
[] ->
{lists:reverse(Parameters), Abi_file, []}
end.
-file("src/gleeth/cli.gleam", 209).
-spec extract_call_args(list(binary())) -> {list(binary()),
gleam@option:option(binary()),
list(binary())}.
extract_call_args(Args) ->
extract_call_args_helper(Args, [], none).
-file("src/gleeth/cli.gleam", 241).
-spec parse_estimate_gas_args_helper(
list(binary()),
binary(),
binary(),
binary(),
binary(),
list(binary())
) -> {ok, {binary(), binary(), binary(), binary(), list(binary())}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_estimate_gas_args_helper(Args, From, To, Value, Data, Remaining) ->
case Args of
[] ->
{ok, {From, To, Value, Data, Remaining}};
[<<"--from"/utf8>>, Addr | Rest] ->
gleam@result:'try'(
gleeth@utils@validation:validate_address(Addr),
fun(Validated_addr) ->
parse_estimate_gas_args_helper(
Rest,
Validated_addr,
To,
Value,
Data,
Remaining
)
end
);
[<<"--to"/utf8>>, Addr@1 | Rest@1] ->
gleam@result:'try'(
gleeth@utils@validation:validate_address(Addr@1),
fun(Validated_addr@1) ->
parse_estimate_gas_args_helper(
Rest@1,
From,
Validated_addr@1,
Value,
Data,
Remaining
)
end
);
[<<"--value"/utf8>>, Val | Rest@2] ->
parse_estimate_gas_args_helper(
Rest@2,
From,
To,
Val,
Data,
Remaining
);
[<<"--data"/utf8>>, Hex_data | Rest@3] ->
parse_estimate_gas_args_helper(
Rest@3,
From,
To,
Value,
Hex_data,
Remaining
);
_ ->
{ok, {From, To, Value, Data, Args}}
end.
-file("src/gleeth/cli.gleam", 231).
-spec parse_estimate_gas_args(list(binary())) -> {ok,
{binary(), binary(), binary(), binary(), list(binary())}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_estimate_gas_args(Args) ->
parse_estimate_gas_args_helper(
Args,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
[]
).
-file("src/gleeth/cli.gleam", 300).
-spec parse_storage_at_args_helper(
list(binary()),
binary(),
binary(),
binary(),
list(binary())
) -> {ok, {binary(), binary(), binary(), list(binary())}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_storage_at_args_helper(Args, Address, Slot, Block, Remaining) ->
case Args of
[] ->
case (Address =:= <<""/utf8>>) orelse (Slot =:= <<""/utf8>>) of
true ->
{error,
{config_error,
<<"storage-at requires --address and --slot flags"/utf8>>}};
false ->
{ok, {Address, Slot, Block, Remaining}}
end;
[<<"--address"/utf8>>, Addr | Rest] ->
gleam@result:'try'(
gleeth@utils@validation:validate_address(Addr),
fun(Validated_addr) ->
parse_storage_at_args_helper(
Rest,
Validated_addr,
Slot,
Block,
Remaining
)
end
);
[<<"--slot"/utf8>>, Slot_val | Rest@1] ->
parse_storage_at_args_helper(
Rest@1,
Address,
Slot_val,
Block,
Remaining
);
[<<"--block"/utf8>>, Block_val | Rest@2] ->
parse_storage_at_args_helper(
Rest@2,
Address,
Slot,
Block_val,
Remaining
);
_ ->
{ok, {Address, Slot, Block, Args}}
end.
-file("src/gleeth/cli.gleam", 293).
-spec parse_storage_at_args(list(binary())) -> {ok,
{binary(), binary(), binary(), list(binary())}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_storage_at_args(Args) ->
parse_storage_at_args_helper(
Args,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
[]
).
-file("src/gleeth/cli.gleam", 348).
-spec parse_get_logs_args_helper(
list(binary()),
binary(),
binary(),
binary(),
list(binary()),
list(binary())
) -> {ok, {binary(), binary(), binary(), list(binary()), list(binary())}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_get_logs_args_helper(
Args,
From_block,
To_block,
Address,
Topics,
Remaining
) ->
case Args of
[] ->
{ok, {From_block, To_block, Address, Topics, Remaining}};
[<<"--from-block"/utf8>>, Block | Rest] ->
parse_get_logs_args_helper(
Rest,
Block,
To_block,
Address,
Topics,
Remaining
);
[<<"--to-block"/utf8>>, Block@1 | Rest@1] ->
parse_get_logs_args_helper(
Rest@1,
From_block,
Block@1,
Address,
Topics,
Remaining
);
[<<"--address"/utf8>>, Addr | Rest@2] ->
gleam@result:'try'(
gleeth@utils@validation:validate_address(Addr),
fun(Validated_addr) ->
parse_get_logs_args_helper(
Rest@2,
From_block,
To_block,
Validated_addr,
Topics,
Remaining
)
end
);
[<<"--topic"/utf8>>, Topic | Rest@3] ->
New_topics = [Topic | Topics],
parse_get_logs_args_helper(
Rest@3,
From_block,
To_block,
Address,
New_topics,
Remaining
);
_ ->
{ok, {From_block, To_block, Address, Topics, Args}}
end.
-file("src/gleeth/cli.gleam", 338).
-spec parse_get_logs_args(list(binary())) -> {ok,
{binary(), binary(), binary(), list(binary()), list(binary())}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_get_logs_args(Args) ->
parse_get_logs_args_helper(
Args,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
[],
[]
).
-file("src/gleeth/cli.gleam", 424).
-spec parse_send_args_helper(
list(binary()),
binary(),
binary(),
binary(),
binary(),
binary(),
boolean(),
list(binary())
) -> {ok,
{binary(),
binary(),
binary(),
binary(),
binary(),
boolean(),
list(binary())}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_send_args_helper(
Args,
To,
Value,
Private_key,
Gas_limit,
Data,
Legacy,
Remaining
) ->
case Args of
[] ->
case (To =:= <<""/utf8>>) orelse (Private_key =:= <<""/utf8>>) of
true ->
{error,
{config_error,
<<"send requires --to and --private-key flags"/utf8>>}};
false ->
{ok,
{To,
Value,
Private_key,
Gas_limit,
Data,
Legacy,
Remaining}}
end;
[<<"--to"/utf8>>, Addr | Rest] ->
gleam@result:'try'(
gleeth@utils@validation:validate_address(Addr),
fun(Validated_addr) ->
parse_send_args_helper(
Rest,
Validated_addr,
Value,
Private_key,
Gas_limit,
Data,
Legacy,
Remaining
)
end
);
[<<"--value"/utf8>>, Val | Rest@1] ->
parse_send_args_helper(
Rest@1,
To,
Val,
Private_key,
Gas_limit,
Data,
Legacy,
Remaining
);
[<<"--private-key"/utf8>>, Key | Rest@2] ->
parse_send_args_helper(
Rest@2,
To,
Value,
Key,
Gas_limit,
Data,
Legacy,
Remaining
);
[<<"--gas-limit"/utf8>>, Gl | Rest@3] ->
parse_send_args_helper(
Rest@3,
To,
Value,
Private_key,
Gl,
Data,
Legacy,
Remaining
);
[<<"--data"/utf8>>, D | Rest@4] ->
parse_send_args_helper(
Rest@4,
To,
Value,
Private_key,
Gas_limit,
D,
Legacy,
Remaining
);
[<<"--legacy"/utf8>> | Rest@5] ->
parse_send_args_helper(
Rest@5,
To,
Value,
Private_key,
Gas_limit,
Data,
true,
Remaining
);
_ ->
{ok, {To, Value, Private_key, Gas_limit, Data, Legacy, Args}}
end.
-file("src/gleeth/cli.gleam", 415).
-spec parse_send_args(list(binary())) -> {ok,
{binary(),
binary(),
binary(),
binary(),
binary(),
boolean(),
list(binary())}} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_send_args(Args) ->
parse_send_args_helper(
Args,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
<<""/utf8>>,
<<"0x"/utf8>>,
false,
[]
).
-file("src/gleeth/cli.gleam", 48).
-spec parse_args(list(binary())) -> {ok, args()} |
{error, gleeth@rpc@types:gleeth_error()}.
parse_args(Args) ->
case Args of
[] ->
{ok, {args, help, <<""/utf8>>}};
[<<"help"/utf8>>] ->
{ok, {args, help, <<""/utf8>>}};
[<<"--help"/utf8>>] ->
{ok, {args, help, <<""/utf8>>}};
[<<"-h"/utf8>>] ->
{ok, {args, help, <<""/utf8>>}};
[<<"block-number"/utf8>> | Rest] ->
gleam@result:'try'(
extract_rpc_url(Rest),
fun(Rpc_url) -> {ok, {args, block_number, Rpc_url}} end
);
[<<"balance"/utf8>> | Args@1] ->
gleam@result:'try'(
parse_balance_args(Args@1),
fun(_use0) ->
{Addresses, File, Rpc_url@1} = _use0,
{ok, {args, {balance, Addresses, File}, Rpc_url@1}}
end
);
[<<"call"/utf8>>, Contract, Function | Rest@1] ->
gleam@result:'try'(
gleeth@utils@validation:validate_address(Contract),
fun(Validated_contract) ->
{Parameters, Abi_file, Rpc_args} = extract_call_args(Rest@1),
gleam@result:'try'(
extract_rpc_url(Rpc_args),
fun(Rpc_url@2) ->
{ok,
{args,
{call,
Validated_contract,
Function,
Parameters,
Abi_file},
Rpc_url@2}}
end
)
end
);
[<<"transaction"/utf8>>, Hash | Rest@2] ->
gleam@result:'try'(
gleeth@utils@validation:validate_hash(Hash),
fun(Validated_hash) ->
gleam@result:'try'(
extract_rpc_url(Rest@2),
fun(Rpc_url@3) ->
{ok,
{args, {transaction, Validated_hash}, Rpc_url@3}}
end
)
end
);
[<<"code"/utf8>>, Address | Rest@3] ->
gleam@result:'try'(
gleeth@utils@validation:validate_address(Address),
fun(Validated_address) ->
gleam@result:'try'(
extract_rpc_url(Rest@3),
fun(Rpc_url@4) ->
{ok, {args, {code, Validated_address}, Rpc_url@4}}
end
)
end
);
[<<"estimate-gas"/utf8>> | Rest@4] ->
gleam@result:'try'(
parse_estimate_gas_args(Rest@4),
fun(_use0@1) ->
{From, To, Value, Data, Remaining} = _use0@1,
gleam@result:'try'(
extract_rpc_url(Remaining),
fun(Rpc_url@5) ->
{ok,
{args,
{estimate_gas, From, To, Value, Data},
Rpc_url@5}}
end
)
end
);
[<<"storage-at"/utf8>> | Rest@5] ->
gleam@result:'try'(
parse_storage_at_args(Rest@5),
fun(_use0@2) ->
{Address@1, Slot, Block, Remaining@1} = _use0@2,
gleam@result:'try'(
extract_rpc_url(Remaining@1),
fun(Rpc_url@6) ->
{ok,
{args,
{storage_at, Address@1, Slot, Block},
Rpc_url@6}}
end
)
end
);
[<<"get-logs"/utf8>> | Rest@6] ->
gleam@result:'try'(
parse_get_logs_args(Rest@6),
fun(_use0@3) ->
{From_block, To_block, Address@2, Topics, Remaining@2} = _use0@3,
gleam@result:'try'(
extract_rpc_url(Remaining@2),
fun(Rpc_url@7) ->
{ok,
{args,
{get_logs,
From_block,
To_block,
Address@2,
Topics},
Rpc_url@7}}
end
)
end
);
[<<"send"/utf8>> | Rest@7] ->
gleam@result:'try'(
parse_send_args(Rest@7),
fun(_use0@4) ->
{To@1,
Value@1,
Private_key,
Gas_limit,
Data@1,
Legacy,
Remaining@3} = _use0@4,
gleam@result:'try'(
extract_rpc_url(Remaining@3),
fun(Rpc_url@8) ->
{ok,
{args,
{send,
To@1,
Value@1,
Private_key,
Gas_limit,
Data@1,
Legacy},
Rpc_url@8}}
end
)
end
);
[<<"wallet"/utf8>> | Wallet_args] ->
{ok, {args, {wallet, Wallet_args}, <<""/utf8>>}};
_ ->
{error,
{config_error,
<<"Invalid command. Use --help for usage information."/utf8>>}}
end.
-file("src/gleeth/cli.gleam", 521).
-spec show_help() -> nil.
show_help() ->
gleam_stdlib:println(<<"gleeth - Ethereum blockchain query tool"/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"USAGE:"/utf8>>),
gleam_stdlib:println(<<" gleeth <COMMAND> [OPTIONS]"/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"COMMANDS:"/utf8>>),
gleam_stdlib:println(
<<" block-number Get latest block number"/utf8>>
),
gleam_stdlib:println(
<<" balance <address> [address2...] Get balance of one or more addresses"/utf8>>
),
gleam_stdlib:println(
<<" balance --file <filename> Get balances from file (one address per line)"/utf8>>
),
gleam_stdlib:println(
<<" call <contract> <function> [params...] Call a contract function"/utf8>>
),
gleam_stdlib:println(
<<" transaction <hash> Get transaction details"/utf8>>
),
gleam_stdlib:println(
<<" code <address> Get contract bytecode at address"/utf8>>
),
gleam_stdlib:println(
<<" estimate-gas [OPTIONS] Estimate gas for a transaction"/utf8>>
),
gleam_stdlib:println(
<<" storage-at --address <addr> --slot <slot> [OPTIONS] Get storage value at slot"/utf8>>
),
gleam_stdlib:println(
<<" get-logs [OPTIONS] Get event logs with filtering"/utf8>>
),
gleam_stdlib:println(
<<" send [OPTIONS] Sign and broadcast a transaction"/utf8>>
),
gleam_stdlib:println(
<<" help Show this help message"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"OPTIONS:"/utf8>>),
gleam_stdlib:println(
<<" --rpc-url <URL> RPC endpoint URL"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"CALL OPTIONS:"/utf8>>),
gleam_stdlib:println(
<<" --abi <file> JSON ABI file for typed encoding/decoding"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"ESTIMATE-GAS OPTIONS:"/utf8>>),
gleam_stdlib:println(
<<" --from <address> Sender address (optional)"/utf8>>
),
gleam_stdlib:println(
<<" --to <address> Recipient address (optional)"/utf8>>
),
gleam_stdlib:println(
<<" --value <wei> Wei amount to send (optional)"/utf8>>
),
gleam_stdlib:println(
<<" --data <hex> Transaction data (optional)"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"STORAGE-AT OPTIONS:"/utf8>>),
gleam_stdlib:println(
<<" --address <address> Contract address (required)"/utf8>>
),
gleam_stdlib:println(
<<" --slot <hex> Storage slot position (required)"/utf8>>
),
gleam_stdlib:println(
<<" --block <number|hash|latest> Block to query (optional, defaults to 'latest')"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"GET-LOGS OPTIONS:"/utf8>>),
gleam_stdlib:println(
<<" --from-block <number|hash> Starting block (optional, defaults to 'latest')"/utf8>>
),
gleam_stdlib:println(
<<" --to-block <number|hash> Ending block (optional, defaults to 'latest')"/utf8>>
),
gleam_stdlib:println(
<<" --address <address> Contract address to filter (optional)"/utf8>>
),
gleam_stdlib:println(
<<" --topic <hex> Topic filter (repeatable for multiple topics)"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"ENVIRONMENT VARIABLES:"/utf8>>),
gleam_stdlib:println(
<<" GLEETH_RPC_URL Default RPC endpoint URL"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"EXAMPLES:"/utf8>>),
gleam_stdlib:println(
<<" gleeth block-number --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(
<<" gleeth balance 0x742dBF0b6d9bAA31b82BB5bcB6e0e1C7a5b30000 --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(
<<" gleeth balance addr1 addr2 addr3 --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(
<<" gleeth balance --file addresses.txt --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(
<<" gleeth call 0xA0b86a33E6Fb7e4f67c5776f8fcB44F56c71d8b8 totalSupply --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(
<<" gleeth call 0xA0b86a33E6Fb7e4f67c5776f8fcB44F56c71d8b8 balanceOf address:0x742d... --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(
<<" gleeth send --to 0x7099... --value 0xde0b6b3a7640000 --private-key 0xac09... --rpc-url http://localhost:8545"/utf8>>
),
gleam_stdlib:println(
<<" gleeth estimate-gas --from 0x742d... --to 0x7a25... --value 0x1000... --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(
<<" gleeth storage-at --address 0xA0b86a... --slot 0x0 --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(
<<" gleeth get-logs --address 0xA0b86a... --from-block 0x1000000 --rpc-url https://eth.llamarpc.com"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"SEND OPTIONS:"/utf8>>),
gleam_stdlib:println(
<<" --to <address> Recipient address (required)"/utf8>>
),
gleam_stdlib:println(
<<" --value <hex> Wei amount to send (hex, e.g. 0xde0b6b3a7640000 for 1 ETH)"/utf8>>
),
gleam_stdlib:println(
<<" --private-key <hex> Sender's private key (required)"/utf8>>
),
gleam_stdlib:println(
<<" --gas-limit <hex> Gas limit (optional, defaults to 21000)"/utf8>>
),
gleam_stdlib:println(
<<" --data <hex> Transaction data (optional)"/utf8>>
),
gleam_stdlib:println(
<<" --legacy Use legacy (Type 0) instead of EIP-1559"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"WALLET COMMANDS:"/utf8>>),
gleam_stdlib:println(
<<" gleeth wallet create --private-key 0x1234..."/utf8>>
),
gleam_stdlib:println(<<" gleeth wallet generate"/utf8>>),
gleam_stdlib:println(
<<" gleeth wallet info --private-key 0x1234..."/utf8>>
),
gleam_stdlib:println(
<<" gleeth wallet sign --private-key 0x1234... --message 'Hello World'"/utf8>>
).