Current section
Files
Jump to
Current section
Files
src/gleeth@wei.erl
-module(gleeth@wei).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeth/wei.gleam").
-export([from_int/1, from_ether/1, from_gwei/1, to_int/1, to_ether/1, to_gwei/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Convert between human-readable values (ETH, gwei, integers) and the\n"
" `0x`-prefixed hex strings used by the Ethereum JSON-RPC wire format.\n"
"\n"
" All RPC methods in gleeth accept and return hex strings. This module\n"
" bridges the gap so users don't have to construct hex manually.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" let assert Ok(hex) = wei.from_ether(\"1.0\")\n"
" // hex = \"0xde0b6b3a7640000\"\n"
"\n"
" let assert Ok(eth) = wei.to_ether(\"0xde0b6b3a7640000\")\n"
" // eth = \"1.0\"\n"
" ```\n"
).
-file("src/gleeth/wei.gleam", 81).
?DOC(
" Convert a decimal integer to a hex string.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" wei.from_int(21000) // -> \"0x5208\"\n"
" wei.from_int(0) // -> \"0x0\"\n"
" ```\n"
).
-spec from_int(integer()) -> binary().
from_int(Value) ->
case Value of
0 ->
<<"0x0"/utf8>>;
_ ->
<<"0x"/utf8, (string:lowercase(gleam@int:to_base16(Value)))/binary>>
end.
-file("src/gleeth/wei.gleam", 218).
-spec nibble_to_char(integer()) -> binary().
nibble_to_char(N) ->
case N of
0 ->
<<"0"/utf8>>;
1 ->
<<"1"/utf8>>;
2 ->
<<"2"/utf8>>;
3 ->
<<"3"/utf8>>;
4 ->
<<"4"/utf8>>;
5 ->
<<"5"/utf8>>;
6 ->
<<"6"/utf8>>;
7 ->
<<"7"/utf8>>;
8 ->
<<"8"/utf8>>;
9 ->
<<"9"/utf8>>;
10 ->
<<"a"/utf8>>;
11 ->
<<"b"/utf8>>;
12 ->
<<"c"/utf8>>;
13 ->
<<"d"/utf8>>;
14 ->
<<"e"/utf8>>;
15 ->
<<"f"/utf8>>;
_ ->
<<"0"/utf8>>
end.
-file("src/gleeth/wei.gleam", 200).
-spec bigint_to_hex_loop(bigi:big_int(), binary()) -> binary().
bigint_to_hex_loop(Value, Acc) ->
Zero = bigi_ffi:from(0),
Sixteen = bigi_ffi:from(16),
case bigi_ffi:compare(Value, Zero) of
eq ->
Acc;
_ ->
Remainder = bigi_ffi:remainder(Value, Sixteen),
Quotient = bigi_ffi:divide(Value, Sixteen),
Nibble = case bigi_ffi:to(Remainder) of
{ok, N} ->
N;
{error, _} ->
0
end,
Hex_char = nibble_to_char(Nibble),
bigint_to_hex_loop(Quotient, <<Hex_char/binary, Acc/binary>>)
end.
-file("src/gleeth/wei.gleam", 189).
-spec bigint_to_hex(bigi:big_int()) -> binary().
bigint_to_hex(Value) ->
Zero = bigi_ffi:from(0),
case bigi_ffi:compare(Value, Zero) of
eq ->
<<"0x0"/utf8>>;
_ ->
Hex_str = bigint_to_hex_loop(Value, <<""/utf8>>),
<<"0x"/utf8, (string:lowercase(Hex_str))/binary>>
end.
-file("src/gleeth/wei.gleam", 240).
-spec power_of_10_string(integer()) -> binary().
power_of_10_string(N) ->
<<"1"/utf8, (gleam@string:repeat(<<"0"/utf8>>, N))/binary>>.
-file("src/gleeth/wei.gleam", 152).
?DOC(
" Parse a decimal string like \"1.5\" or \"100\" into a BigInt representing\n"
" wei (multiplied by 10^decimals).\n"
).
-spec parse_decimal_to_bigint(binary(), integer()) -> {ok, bigi:big_int()} |
{error, binary()}.
parse_decimal_to_bigint(Amount, Decimals) ->
case gleam@string:split(Amount, <<"."/utf8>>) of
[Whole] ->
gleam@result:'try'(
begin
_pipe = bigi_ffi:from_string(Whole),
gleam@result:map_error(
_pipe,
fun(_) -> <<"Invalid number: "/utf8, Amount/binary>> end
)
end,
fun(Whole_big) ->
gleam@result:'try'(
begin
_pipe@1 = bigi_ffi:from_string(
power_of_10_string(Decimals)
),
gleam@result:map_error(
_pipe@1,
fun(_) ->
<<"Failed to parse multiplier"/utf8>>
end
)
end,
fun(Multiplier) ->
{ok, bigi_ffi:multiply(Whole_big, Multiplier)}
end
)
end
);
[Whole@1, Frac] ->
Frac_len = string:length(Frac),
case Frac_len > Decimals of
true ->
{error,
<<<<"Too many decimal places (max "/utf8,
(erlang:integer_to_binary(Decimals))/binary>>/binary,
")"/utf8>>};
false ->
Padded_frac = <<Frac/binary,
(gleam@string:repeat(<<"0"/utf8>>, Decimals - Frac_len))/binary>>,
Combined = <<Whole@1/binary, Padded_frac/binary>>,
_pipe@2 = bigi_ffi:from_string(Combined),
gleam@result:map_error(
_pipe@2,
fun(_) -> <<"Invalid number: "/utf8, Amount/binary>> end
)
end;
_ ->
{error, <<"Invalid decimal format: "/utf8, Amount/binary>>}
end.
-file("src/gleeth/wei.gleam", 111).
?DOC(
" Parse a decimal string (possibly with fractional part) and multiply by\n"
" 10^decimals to get the wei value as a BigInt, then convert to hex.\n"
).
-spec decimal_to_wei(binary(), integer()) -> {ok, binary()} | {error, binary()}.
decimal_to_wei(Amount, Decimals) ->
Trimmed = gleam@string:trim(Amount),
case Trimmed of
<<""/utf8>> ->
{error, <<"Empty amount"/utf8>>};
_ ->
gleam@result:'try'(
parse_decimal_to_bigint(Trimmed, Decimals),
fun(Wei) ->
Zero = bigi_ffi:from(0),
case bigi_ffi:compare(Wei, Zero) of
lt ->
{error, <<"Negative amounts not supported"/utf8>>};
_ ->
{ok, bigint_to_hex(Wei)}
end
end
)
end.
-file("src/gleeth/wei.gleam", 34).
?DOC(
" Convert an ether amount string to a wei hex string.\n"
" Handles integers (\"1\", \"100\") and decimals (\"1.5\", \"0.001\").\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" wei.from_ether(\"1.0\") // -> Ok(\"0xde0b6b3a7640000\")\n"
" wei.from_ether(\"0.5\") // -> Ok(\"0x6f05b59d3b20000\")\n"
" wei.from_ether(\"0\") // -> Ok(\"0x0\")\n"
" ```\n"
).
-spec from_ether(binary()) -> {ok, binary()} | {error, binary()}.
from_ether(Ether) ->
decimal_to_wei(Ether, 18).
-file("src/gleeth/wei.gleam", 46).
?DOC(
" Convert a gwei amount string to a wei hex string.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" wei.from_gwei(\"1.0\") // -> Ok(\"0x3b9aca00\")\n"
" wei.from_gwei(\"20\") // -> Ok(\"0x4a817c800\")\n"
" ```\n"
).
-spec from_gwei(binary()) -> {ok, binary()} | {error, binary()}.
from_gwei(Gwei) ->
decimal_to_wei(Gwei, 9).
-file("src/gleeth/wei.gleam", 244).
-spec strip_0x(binary()) -> binary().
strip_0x(S) ->
case gleam_stdlib:string_starts_with(S, <<"0x"/utf8>>) of
true ->
gleam@string:drop_start(S, 2);
false ->
S
end.
-file("src/gleeth/wei.gleam", 95).
?DOC(
" Convert a hex string to a decimal integer.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" wei.to_int(\"0x5208\") // -> Ok(21000)\n"
" ```\n"
).
-spec to_int(binary()) -> {ok, integer()} | {error, binary()}.
to_int(Hex_string) ->
Clean = strip_0x(Hex_string),
case Clean of
<<""/utf8>> ->
{ok, 0};
_ ->
_pipe = gleam@int:base_parse(Clean, 16),
gleam@result:map_error(
_pipe,
fun(_) -> <<"Invalid hex: "/utf8, Hex_string/binary>> end
)
end.
-file("src/gleeth/wei.gleam", 251).
-spec trim_trailing_zeros(binary()) -> binary().
trim_trailing_zeros(S) ->
case gleam_stdlib:string_ends_with(S, <<"0"/utf8>>) of
true ->
Trimmed = gleam@string:drop_end(S, 1),
case Trimmed of
<<""/utf8>> ->
<<"0"/utf8>>;
_ ->
trim_trailing_zeros(Trimmed)
end;
false ->
case S of
<<""/utf8>> ->
<<"0"/utf8>>;
_ ->
S
end
end.
-file("src/gleeth/wei.gleam", 128).
?DOC(
" Convert wei BigInt back to a decimal string with the given number of\n"
" decimal places.\n"
).
-spec wei_to_decimal(binary(), integer()) -> {ok, binary()} | {error, binary()}.
wei_to_decimal(Hex_string, Decimals) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@hex:hex_to_bigint(Hex_string),
gleam@result:map_error(
_pipe,
fun(_) -> <<"Invalid hex: "/utf8, Hex_string/binary>> end
)
end,
fun(Wei) ->
Divisor_str = power_of_10_string(Decimals),
gleam@result:'try'(
begin
_pipe@1 = bigi_ffi:from_string(Divisor_str),
gleam@result:map_error(
_pipe@1,
fun(_) -> <<"Failed to parse divisor"/utf8>> end
)
end,
fun(Divisor) ->
Whole = bigi_ffi:divide(Wei, Divisor),
Remainder = bigi_ffi:remainder(Wei, Divisor),
Whole_str = erlang:integer_to_binary(Whole),
Remainder_str = erlang:integer_to_binary(Remainder),
Padded = <<(gleam@string:repeat(
<<"0"/utf8>>,
Decimals - string:length(Remainder_str)
))/binary,
Remainder_str/binary>>,
Trimmed = trim_trailing_zeros(Padded),
{ok,
<<<<Whole_str/binary, "."/utf8>>/binary,
Trimmed/binary>>}
end
)
end
).
-file("src/gleeth/wei.gleam", 58).
?DOC(
" Convert a wei hex string to an ether decimal string.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" wei.to_ether(\"0xde0b6b3a7640000\") // -> Ok(\"1.0\")\n"
" wei.to_ether(\"0x0\") // -> Ok(\"0.0\")\n"
" ```\n"
).
-spec to_ether(binary()) -> {ok, binary()} | {error, binary()}.
to_ether(Wei_hex) ->
wei_to_decimal(Wei_hex, 18).
-file("src/gleeth/wei.gleam", 69).
?DOC(
" Convert a wei hex string to a gwei decimal string.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" wei.to_gwei(\"0x3b9aca00\") // -> Ok(\"1.0\")\n"
" ```\n"
).
-spec to_gwei(binary()) -> {ok, binary()} | {error, binary()}.
to_gwei(Wei_hex) ->
wei_to_decimal(Wei_hex, 9).