-module(gleeth@commands@call). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/gleeth/commands/call.gleam"). -export([execute/5]). -file("src/gleeth/commands/call.gleam", 60). -spec parse_parameters(list(binary())) -> {ok, list({gleeth@ethereum@abi@types:abi_type(), gleeth@ethereum@abi@types:abi_value()})} | {error, gleeth@rpc@types:gleeth_error()}. parse_parameters(Param_strings) -> gleam@list:try_map( Param_strings, fun gleeth@ethereum@contract:parse_parameter/1 ). -file("src/gleeth/commands/call.gleam", 200). -spec abi_error_message(gleeth@ethereum@abi@types:abi_error()) -> binary(). abi_error_message(Err) -> case Err of {encode_error, Msg} -> Msg; {decode_error, Msg@1} -> Msg@1; {type_parse_error, Msg@2} -> Msg@2; {invalid_abi_json, Msg@3} -> Msg@3 end. -file("src/gleeth/commands/call.gleam", 233). -spec decode_uint256(binary()) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. decode_uint256(Hex_data) -> case string:length(Hex_data) >= 64 of true -> Value_hex = gleam@string:slice(Hex_data, 0, 64), case gleeth@utils@hex:hex_to_int(Value_hex) of {ok, Int_value} -> {ok, erlang:list_to_binary( [erlang:integer_to_binary(Int_value), <<" (0x"/utf8>>, Value_hex, <<")"/utf8>>] )}; {error, _} -> {ok, <<"0x"/utf8, Value_hex/binary>>} end; false -> {error, {parse_error, <<"Response too short for uint256"/utf8>>}} end. -file("src/gleeth/commands/call.gleam", 247). -spec decode_address(binary()) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. decode_address(Hex_data) -> case string:length(Hex_data) >= 64 of true -> Address_hex = gleam@string:slice(Hex_data, 24, 40), {ok, <<"0x"/utf8, Address_hex/binary>>}; false -> {error, {parse_error, <<"Response too short for address"/utf8>>}} end. -file("src/gleeth/commands/call.gleam", 257). -spec decode_bool(binary()) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. decode_bool(Hex_data) -> case string:length(Hex_data) >= 64 of true -> Value_hex = gleam@string:slice(Hex_data, 63, 1), case Value_hex of <<"0"/utf8>> -> {ok, <<"false"/utf8>>}; <<"1"/utf8>> -> {ok, <<"true"/utf8>>}; _ -> {ok, <<"0x"/utf8, (gleam@string:slice(Hex_data, 0, 64))/binary>>} end; false -> {error, {parse_error, <<"Response too short for boolean"/utf8>>}} end. -file("src/gleeth/commands/call.gleam", 271). -spec decode_string_abi(binary()) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. decode_string_abi(Hex_data) -> case string:length(Hex_data) >= 192 of true -> Length_hex = gleam@string:slice(Hex_data, 64, 64), case gleeth@utils@hex:hex_to_int(Length_hex) of {ok, Length} -> Data_hex = gleam@string:slice(Hex_data, 128, Length * 2), case gleeth@utils@hex:decode(<<"0x"/utf8, Data_hex/binary>>) of {ok, Bytes} -> case gleam@bit_array:to_string(Bytes) of {ok, S} -> {ok, <<<<"\""/utf8, S/binary>>/binary, "\""/utf8>>}; {error, _} -> {ok, <<<<"0x"/utf8, Data_hex/binary>>/binary, " (non-UTF-8)"/utf8>>} end; {error, _} -> {ok, <<"0x"/utf8, (gleam@string:slice(Hex_data, 0, 64))/binary>>} end; {error, _} -> {ok, <<"0x"/utf8, (gleam@string:slice(Hex_data, 0, 64))/binary>>} end; false -> case string:length(Hex_data) >= 64 of true -> {ok, <<"0x"/utf8, (gleam@string:slice(Hex_data, 0, 64))/binary>>}; false -> {error, {parse_error, <<"Response too short for string"/utf8>>}} end end. -file("src/gleeth/commands/call.gleam", 303). -spec decode_reserves(binary()) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. decode_reserves(Hex_data) -> case string:length(Hex_data) >= 192 of true -> Reserve0_hex = gleam@string:slice(Hex_data, 0, 64), Reserve1_hex = gleam@string:slice(Hex_data, 64, 64), Timestamp_hex = gleam@string:slice(Hex_data, 128, 64), case {gleeth@utils@hex:hex_to_int(Reserve0_hex), gleeth@utils@hex:hex_to_int(Reserve1_hex), gleeth@utils@hex:hex_to_int(Timestamp_hex)} of {{ok, R0}, {ok, R1}, {ok, Ts}} -> {ok, <<<<<<<<<<"Reserve0: "/utf8, (erlang:integer_to_binary(R0))/binary>>/binary, ", Reserve1: "/utf8>>/binary, (erlang:integer_to_binary(R1))/binary>>/binary, ", Timestamp: "/utf8>>/binary, (erlang:integer_to_binary(Ts))/binary>>}; {_, _, _} -> {ok, <<"0x"/utf8, Hex_data/binary>>} end; false -> {error, {parse_error, <<"Response too short for reserves"/utf8>>}} end. -file("src/gleeth/commands/call.gleam", 213). -spec decode_response(binary(), binary()) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. decode_response(Function_name, Response) -> Clean_response = gleeth@utils@hex:strip_prefix(Response), case Function_name of <<"balanceOf"/utf8>> -> decode_uint256(Clean_response); <<"totalSupply"/utf8>> -> decode_uint256(Clean_response); <<"allowance"/utf8>> -> decode_uint256(Clean_response); <<"decimals"/utf8>> -> decode_uint256(Clean_response); <<"owner"/utf8>> -> decode_address(Clean_response); <<"token0"/utf8>> -> decode_address(Clean_response); <<"token1"/utf8>> -> decode_address(Clean_response); <<"name"/utf8>> -> decode_string_abi(Clean_response); <<"symbol"/utf8>> -> decode_string_abi(Clean_response); <<"approve"/utf8>> -> decode_bool(Clean_response); <<"transfer"/utf8>> -> decode_bool(Clean_response); <<"getReserves"/utf8>> -> decode_reserves(Clean_response); _ -> {error, {parse_error, <<"Unknown return type for function: "/utf8, Function_name/binary>>}} end. -file("src/gleeth/commands/call.gleam", 172). -spec format_single_value( gleeth@ethereum@abi@types:abi_type(), gleeth@ethereum@abi@types:abi_value() ) -> binary(). format_single_value(T, V) -> case {T, V} of {{uint, _}, {uint_value, N}} -> erlang:integer_to_binary(N); {{int, _}, {int_value, N@1}} -> erlang:integer_to_binary(N@1); {address, {address_value, Addr}} -> Addr; {bool, {bool_value, B}} -> case B of true -> <<"true"/utf8>>; false -> <<"false"/utf8>> end; {{fixed_bytes, Size}, {fixed_bytes_value, Data}} -> <<"0x"/utf8, (begin _pipe = string:lowercase(gleam_stdlib:base16_encode(Data)), gleam@string:slice(_pipe, 0, 2 + (Size * 2)) end)/binary>>; {bytes, {bytes_value, Data@1}} -> <<"0x"/utf8, (string:lowercase(gleam_stdlib:base16_encode(Data@1)))/binary>>; {string, {string_value, S}} -> <<<<"\""/utf8, S/binary>>/binary, "\""/utf8>>; {{array, Element_type}, {array_value, Elements}} -> Inner = gleam@list:map( Elements, fun(El) -> format_single_value(Element_type, El) end ), <<<<"["/utf8, (gleam@string:join(Inner, <<", "/utf8>>))/binary>>/binary, "]"/utf8>>; {{tuple, Element_types}, {tuple_value, Vals}} -> format_abi_values(Element_types, Vals); {_, _} -> <<""/utf8>> end. -file("src/gleeth/commands/call.gleam", 156). -spec format_abi_values( list(gleeth@ethereum@abi@types:abi_type()), list(gleeth@ethereum@abi@types:abi_value()) ) -> binary(). format_abi_values(Types, Values) -> Pairs = gleam@list:zip(Types, Values), Formatted = gleam@list:map( Pairs, fun(Pair) -> {T, V} = Pair, format_single_value(T, V) end ), case Formatted of [Single] -> Single; Multiple -> <<<<"("/utf8, (gleam@string:join(Multiple, <<", "/utf8>>))/binary>>/binary, ")"/utf8>> end. -file("src/gleeth/commands/call.gleam", 119). -spec decode_with_abi(binary(), binary(), binary()) -> {ok, binary()} | {error, gleeth@ethereum@abi@types:abi_error()}. decode_with_abi(Abi_file, Function_name, Response) -> gleam@result:'try'( begin _pipe = simplifile:read(Abi_file), gleam@result:map_error( _pipe, fun(_) -> {invalid_abi_json, <<"Cannot read ABI file: "/utf8, Abi_file/binary>>} end ) end, fun(Abi_json_str) -> gleam@result:'try'( gleeth@ethereum@abi@json:parse_abi(Abi_json_str), fun(Entries) -> gleam@result:'try'( gleeth@ethereum@abi@json:find_function( Entries, Function_name ), fun(Entry) -> Output_types = gleeth@ethereum@abi@json:output_types( Entry ), case Output_types of [] -> {ok, <<"(void)"/utf8>>}; _ -> gleam@result:'try'( begin _pipe@1 = gleeth@utils@hex:decode( Response ), gleam@result:map_error( _pipe@1, fun(_) -> {decode_error, <<"Invalid hex in response"/utf8>>} end ) end, fun(Data) -> gleam@result:'try'( gleeth@ethereum@abi@decode:decode( Output_types, Data ), fun(Values) -> {ok, format_abi_values( Output_types, Values )} end ) end ) end end ) end ) end ). -file("src/gleeth/commands/call.gleam", 70). -spec print_contract_response( binary(), binary(), list(binary()), binary(), gleam@option:option(binary()) ) -> nil. print_contract_response( Contract_address, Function_name, Parameters, Response, Abi_file ) -> gleam_stdlib:println(<<"Contract Call Results:"/utf8>>), gleam_stdlib:println(<<" Contract: "/utf8, Contract_address/binary>>), gleam_stdlib:println( <<<<" Function: "/utf8, Function_name/binary>>/binary, "()"/utf8>> ), case Parameters of [] -> nil; Params -> gleam_stdlib:println(<<" Parameters:"/utf8>>), gleam@list:each( Params, fun(Param) -> gleam_stdlib:println(<<" "/utf8, Param/binary>>) end ) end, gleam_stdlib:println(<<" Raw Response: "/utf8, Response/binary>>), case Abi_file of {some, File} -> case decode_with_abi(File, Function_name, Response) of {ok, Decoded} -> gleam_stdlib:println(<<" Decoded: "/utf8, Decoded/binary>>); {error, Err} -> gleam_stdlib:println( <<" ABI decode failed: "/utf8, (abi_error_message(Err))/binary>> ), case decode_response(Function_name, Response) of {ok, Decoded@1} -> gleam_stdlib:println( <<" Decoded (heuristic): "/utf8, Decoded@1/binary>> ); {error, _} -> nil end end; none -> case decode_response(Function_name, Response) of {ok, Decoded@2} -> gleam_stdlib:println( <<" Decoded: "/utf8, Decoded@2/binary>> ); {error, _} -> nil end end. -file("src/gleeth/commands/call.gleam", 20). -spec execute( gleeth@provider:provider(), binary(), binary(), list(binary()), gleam@option:option(binary()) ) -> {ok, nil} | {error, gleeth@rpc@types:gleeth_error()}. execute(Provider, Contract_address, Function_call, Parameters, Abi_file) -> gleam@result:'try'( gleeth@utils@validation:validate_address(Contract_address), fun(Validated_address) -> gleam@result:'try'( parse_parameters(Parameters), fun(Parsed_params) -> gleam@result:'try'( gleeth@ethereum@contract:build_call_data( Function_call, Parsed_params ), fun(Call_data) -> gleam@result:'try'( gleeth@rpc@methods:call_contract( Provider, Validated_address, Call_data ), fun(Response) -> print_contract_response( Contract_address, Function_call, Parameters, Response, Abi_file ), {ok, nil} end ) end ) end ) end ).