Current section
Files
Jump to
Current section
Files
src/gleeth@utils@hex.erl
-module(gleeth@utils@hex).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeth/utils/hex.gleam").
-export([hex_to_bigint/1, hex_to_int/1, wei_to_ether/1, wei_to_gwei/1, format_wei_to_ether/1, format_wei_to_gwei/1, format_block_number/1, is_valid_hex/1, decode/1, encode/1, strip_prefix/1, ensure_prefix/1, normalize/1, from_int/1, to_int/1, is_valid_hex_chars/1, format_with_decimal/1, pad_left/2, validate_length/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/gleeth/utils/hex.gleam", 30).
-spec char_to_hex_value(binary()) -> {ok, integer()} | {error, nil}.
char_to_hex_value(Char) ->
case Char of
<<"0"/utf8>> ->
{ok, 0};
<<"1"/utf8>> ->
{ok, 1};
<<"2"/utf8>> ->
{ok, 2};
<<"3"/utf8>> ->
{ok, 3};
<<"4"/utf8>> ->
{ok, 4};
<<"5"/utf8>> ->
{ok, 5};
<<"6"/utf8>> ->
{ok, 6};
<<"7"/utf8>> ->
{ok, 7};
<<"8"/utf8>> ->
{ok, 8};
<<"9"/utf8>> ->
{ok, 9};
<<"a"/utf8>> ->
{ok, 10};
<<"A"/utf8>> ->
{ok, 10};
<<"b"/utf8>> ->
{ok, 11};
<<"B"/utf8>> ->
{ok, 11};
<<"c"/utf8>> ->
{ok, 12};
<<"C"/utf8>> ->
{ok, 12};
<<"d"/utf8>> ->
{ok, 13};
<<"D"/utf8>> ->
{ok, 13};
<<"e"/utf8>> ->
{ok, 14};
<<"E"/utf8>> ->
{ok, 14};
<<"f"/utf8>> ->
{ok, 15};
<<"F"/utf8>> ->
{ok, 15};
_ ->
{error, nil}
end.
-file("src/gleeth/utils/hex.gleam", 23).
-spec hex_chars_to_bigint(binary()) -> {ok, bigi:big_int()} | {error, nil}.
hex_chars_to_bigint(Hex) ->
Chars = gleam@string:to_graphemes(Hex),
gleam@result:'try'(
gleam@list:try_map(Chars, fun char_to_hex_value/1),
fun(Digits) -> bigi:undigits(Digits, 16) end
).
-file("src/gleeth/utils/hex.gleam", 10).
-spec hex_to_bigint(binary()) -> {ok, bigi:big_int()} | {error, nil}.
hex_to_bigint(Hex_string) ->
Clean_hex = case gleam_stdlib:string_starts_with(Hex_string, <<"0x"/utf8>>) of
true ->
gleam@string:drop_start(Hex_string, 2);
false ->
Hex_string
end,
case Clean_hex of
<<""/utf8>> ->
{ok, bigi_ffi:from(0)};
_ ->
hex_chars_to_bigint(Clean_hex)
end.
-file("src/gleeth/utils/hex.gleam", 53).
-spec hex_to_int(binary()) -> {ok, integer()} | {error, nil}.
hex_to_int(Hex_string) ->
gleam@result:'try'(
hex_to_bigint(Hex_string),
fun(Bigint) -> bigi_ffi:to(Bigint) end
).
-file("src/gleeth/utils/hex.gleam", 99).
-spec string_division(binary(), integer(), float()) -> {ok, float()} |
{error, nil}.
string_division(Wei_str, Decimals, Divisor) ->
Wei_len = string:length(Wei_str),
case Wei_len of
Len when Len =< Decimals ->
case gleam_stdlib:parse_int(Wei_str) of
{ok, Wei_int} ->
{ok, case Divisor of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> erlang:float(Wei_int) / Gleam@denominator
end};
{error, _} ->
{error, nil}
end;
Len@1 ->
Whole_part = gleam@string:drop_end(Wei_str, Decimals),
Frac_part = gleam@string:drop_start(Wei_str, Len@1 - Decimals),
case gleam_stdlib:parse_int(Whole_part) of
{ok, Whole_int} ->
Whole_float = erlang:float(Whole_int),
case gleam_stdlib:parse_int(Frac_part) of
{ok, Frac_int} ->
{ok, Whole_float + (case Divisor of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@1 -> erlang:float(
Frac_int
)
/ Gleam@denominator@1
end)};
{error, _} ->
{ok, Whole_float}
end;
{error, _} ->
{error, nil}
end
end.
-file("src/gleeth/utils/hex.gleam", 130).
-spec wei_to_ether_string_division(binary()) -> {ok, float()} | {error, nil}.
wei_to_ether_string_division(Wei_str) ->
string_division(Wei_str, 18, 1000000000000000000.0).
-file("src/gleeth/utils/hex.gleam", 59).
-spec wei_to_ether(binary()) -> {ok, float()} | {error, nil}.
wei_to_ether(Wei_hex) ->
gleam@result:'try'(
hex_to_bigint(Wei_hex),
fun(Wei_bigint) ->
Wei_str = erlang:integer_to_binary(Wei_bigint),
case gleam_stdlib:parse_int(Wei_str) of
{ok, Wei_int} ->
Wei_float = erlang:float(Wei_int),
Ether = Wei_float / 1000000000000000000.0,
{ok, Ether};
{error, _} ->
wei_to_ether_string_division(Wei_str)
end
end
).
-file("src/gleeth/utils/hex.gleam", 134).
-spec wei_to_gwei_string_division(binary()) -> {ok, float()} | {error, nil}.
wei_to_gwei_string_division(Wei_str) ->
string_division(Wei_str, 9, 1000000000.0).
-file("src/gleeth/utils/hex.gleam", 78).
-spec wei_to_gwei(binary()) -> {ok, float()} | {error, nil}.
wei_to_gwei(Wei_hex) ->
gleam@result:'try'(
hex_to_bigint(Wei_hex),
fun(Wei_bigint) ->
Wei_str = erlang:integer_to_binary(Wei_bigint),
case gleam_stdlib:parse_int(Wei_str) of
{ok, Wei_int} ->
Wei_float = erlang:float(Wei_int),
Gwei = Wei_float / 1000000000.0,
{ok, Gwei};
{error, _} ->
wei_to_gwei_string_division(Wei_str)
end
end
).
-file("src/gleeth/utils/hex.gleam", 139).
-spec format_wei_to_ether(binary()) -> binary().
format_wei_to_ether(Wei_hex) ->
case wei_to_ether(Wei_hex) of
{ok, Ether} ->
Ether_str = gleam_stdlib:float_to_string(Ether),
case Ether > 0.001 of
true ->
<<Ether_str/binary, " ETH"/utf8>>;
false ->
<<<<<<Ether_str/binary, " ETH ("/utf8>>/binary,
Wei_hex/binary>>/binary,
" Wei)"/utf8>>
end;
{error, _} ->
<<Wei_hex/binary, " Wei (conversion failed)"/utf8>>
end.
-file("src/gleeth/utils/hex.gleam", 156).
-spec format_wei_to_gwei(binary()) -> binary().
format_wei_to_gwei(Wei_hex) ->
case wei_to_gwei(Wei_hex) of
{ok, Gwei} ->
Gwei_str = gleam_stdlib:float_to_string(Gwei),
<<Gwei_str/binary, " gwei"/utf8>>;
{error, _} ->
<<Wei_hex/binary, " wei (gwei conversion failed)"/utf8>>
end.
-file("src/gleeth/utils/hex.gleam", 167).
-spec format_block_number(binary()) -> binary().
format_block_number(Block_hex) ->
case hex_to_bigint(Block_hex) of
{ok, Block_bigint} ->
erlang:integer_to_binary(Block_bigint);
{error, _} ->
Block_hex
end.
-file("src/gleeth/utils/hex.gleam", 175).
-spec is_valid_hex(binary()) -> boolean().
is_valid_hex(Hex_string) ->
case hex_to_bigint(Hex_string) of
{ok, _} ->
true;
{error, _} ->
false
end.
-file("src/gleeth/utils/hex.gleam", 206).
-spec decode_hex_chars_to_bytes(list(binary()), list(integer())) -> {ok,
list(integer())} |
{error, binary()}.
decode_hex_chars_to_bytes(Chars, Acc) ->
case Chars of
[] ->
{ok, lists:reverse(Acc)};
[High, Low | Rest] ->
gleam@result:'try'(
begin
_pipe = char_to_hex_value(High),
gleam@result:map_error(
_pipe,
fun(_) ->
<<"Invalid hex character: "/utf8, High/binary>>
end
)
end,
fun(High_val) ->
gleam@result:'try'(
begin
_pipe@1 = char_to_hex_value(Low),
gleam@result:map_error(
_pipe@1,
fun(_) ->
<<"Invalid hex character: "/utf8,
Low/binary>>
end
)
end,
fun(Low_val) ->
Byte_val = (High_val * 16) + Low_val,
decode_hex_chars_to_bytes(Rest, [Byte_val | Acc])
end
)
end
);
[_] ->
{error,
<<"Hex string must have an even number of characters"/utf8>>}
end.
-file("src/gleeth/utils/hex.gleam", 196).
-spec decode_hex_pairs(binary()) -> {ok, bitstring()} | {error, binary()}.
decode_hex_pairs(Hex) ->
Chars = gleam@string:to_graphemes(Hex),
gleam@result:'try'(
decode_hex_chars_to_bytes(Chars, []),
fun(Bytes) ->
Bit_pattern = gleam@list:fold(
Bytes,
<<>>,
fun(Acc, Byte) -> <<Acc/bitstring, Byte:8>> end
),
{ok, Bit_pattern}
end
).
-file("src/gleeth/utils/hex.gleam", 183).
-spec decode(binary()) -> {ok, bitstring()} | {error, binary()}.
decode(Hex_string) ->
Clean_hex = case gleam_stdlib:string_starts_with(Hex_string, <<"0x"/utf8>>) of
true ->
gleam@string:drop_start(Hex_string, 2);
false ->
Hex_string
end,
case string:length(Clean_hex) rem 2 of
0 ->
decode_hex_pairs(Clean_hex);
_ ->
{error,
<<"Hex string must have an even number of characters"/utf8>>}
end.
-file("src/gleeth/utils/hex.gleam", 229).
-spec encode(bitstring()) -> binary().
encode(Data) ->
<<"0x"/utf8,
(begin
_pipe = gleam_stdlib:base16_encode(Data),
string:lowercase(_pipe)
end)/binary>>.
-file("src/gleeth/utils/hex.gleam", 238).
?DOC(" Remove 0x prefix from hex string if present\n").
-spec strip_prefix(binary()) -> binary().
strip_prefix(Hex_string) ->
case gleam_stdlib:string_starts_with(Hex_string, <<"0x"/utf8>>) of
true ->
gleam@string:drop_start(Hex_string, 2);
false ->
Hex_string
end.
-file("src/gleeth/utils/hex.gleam", 246).
?DOC(" Add 0x prefix to hex string if not present\n").
-spec ensure_prefix(binary()) -> binary().
ensure_prefix(Hex_string) ->
case gleam_stdlib:string_starts_with(Hex_string, <<"0x"/utf8>>) of
true ->
Hex_string;
false ->
<<"0x"/utf8, Hex_string/binary>>
end.
-file("src/gleeth/utils/hex.gleam", 254).
?DOC(" Normalize hex string to lowercase with 0x prefix\n").
-spec normalize(binary()) -> binary().
normalize(Hex_string) ->
Clean = strip_prefix(Hex_string),
<<"0x"/utf8, (string:lowercase(Clean))/binary>>.
-file("src/gleeth/utils/hex.gleam", 260).
?DOC(" Convert integer to hex string with 0x prefix\n").
-spec from_int(integer()) -> binary().
from_int(Value) ->
<<"0x"/utf8,
(begin
_pipe = gleam@int:to_base16(Value),
string:lowercase(_pipe)
end)/binary>>.
-file("src/gleeth/utils/hex.gleam", 265).
?DOC(" Parse hex string to integer (with or without 0x prefix)\n").
-spec to_int(binary()) -> {ok, integer()} | {error, nil}.
to_int(Hex_string) ->
gleam@result:'try'(
hex_to_bigint(Hex_string),
fun(Bigint) -> bigi_ffi:to(Bigint) end
).
-file("src/gleeth/utils/hex.gleam", 277).
?DOC(" Check if a single character is a valid hex digit\n").
-spec is_hex_char(binary()) -> boolean().
is_hex_char(Char) ->
case Char of
<<"0"/utf8>> ->
true;
<<"1"/utf8>> ->
true;
<<"2"/utf8>> ->
true;
<<"3"/utf8>> ->
true;
<<"4"/utf8>> ->
true;
<<"5"/utf8>> ->
true;
<<"6"/utf8>> ->
true;
<<"7"/utf8>> ->
true;
<<"8"/utf8>> ->
true;
<<"9"/utf8>> ->
true;
<<"a"/utf8>> ->
true;
<<"b"/utf8>> ->
true;
<<"c"/utf8>> ->
true;
<<"d"/utf8>> ->
true;
<<"e"/utf8>> ->
true;
<<"f"/utf8>> ->
true;
<<"A"/utf8>> ->
true;
<<"B"/utf8>> ->
true;
<<"C"/utf8>> ->
true;
<<"D"/utf8>> ->
true;
<<"E"/utf8>> ->
true;
<<"F"/utf8>> ->
true;
_ ->
false
end.
-file("src/gleeth/utils/hex.gleam", 271).
?DOC(" Validate that a string contains only valid hex characters (after stripping 0x)\n").
-spec is_valid_hex_chars(binary()) -> boolean().
is_valid_hex_chars(Hex_string) ->
Clean = strip_prefix(Hex_string),
_pipe = gleam@string:to_graphemes(Clean),
gleam@list:all(_pipe, fun is_hex_char/1).
-file("src/gleeth/utils/hex.gleam", 287).
?DOC(" Format a hex value with decimal equivalent for display\n").
-spec format_with_decimal(binary()) -> binary().
format_with_decimal(Hex_string) ->
case to_int(Hex_string) of
{ok, Decimal_value} ->
<<<<<<(erlang:integer_to_binary(Decimal_value))/binary, " ("/utf8>>/binary,
(normalize(Hex_string))/binary>>/binary,
")"/utf8>>;
{error, _} ->
normalize(Hex_string)
end.
-file("src/gleeth/utils/hex.gleam", 296).
?DOC(" Pad hex string to specified length (without 0x prefix)\n").
-spec pad_left(binary(), integer()) -> binary().
pad_left(Hex_string, Target_length) ->
Clean = strip_prefix(Hex_string),
Current_length = string:length(Clean),
case Current_length >= Target_length of
true ->
Clean;
false ->
Padding_needed = Target_length - Current_length,
Padding = gleam@string:repeat(<<"0"/utf8>>, Padding_needed),
<<Padding/binary, Clean/binary>>
end.
-file("src/gleeth/utils/hex.gleam", 310).
?DOC(" Validate hex string has correct length for specific data types\n").
-spec validate_length(binary(), integer()) -> {ok, binary()} | {error, binary()}.
validate_length(Hex_string, Expected_bytes) ->
Clean = strip_prefix(Hex_string),
Expected_chars = Expected_bytes * 2,
case string:length(Clean) of
Actual_chars when Actual_chars =:= Expected_chars ->
{ok, Clean};
Actual_chars@1 ->
{error,
<<<<<<"Expected "/utf8,
(erlang:integer_to_binary(Expected_chars))/binary>>/binary,
" hex characters, got "/utf8>>/binary,
(erlang:integer_to_binary(Actual_chars@1))/binary>>}
end.