-module(gleeth@rpc@client). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/gleeth/rpc/client.gleam"). -export([make_request/3, make_request_with_retry/4, make_batch_request/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/rpc/client.gleam", 122). -spec encode_request(gleeth@rpc@types:json_rpc_request()) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. encode_request(Req) -> Json_object = gleam@json:object( [{<<"jsonrpc"/utf8>>, gleam@json:string(erlang:element(2, Req))}, {<<"method"/utf8>>, gleam@json:string(erlang:element(3, Req))}, {<<"params"/utf8>>, gleam@json:array(erlang:element(4, Req), fun(X) -> X end)}, {<<"id"/utf8>>, gleam@json:int(erlang:element(5, Req))}] ), {ok, gleam@json:to_string(Json_object)}. -file("src/gleeth/rpc/client.gleam", 185). -spec parse_url(binary()) -> {ok, {binary(), binary(), binary()}} | {error, gleeth@rpc@types:gleeth_error()}. parse_url(Url) -> case gleam@string:split(Url, <<"://"/utf8>>) of [Scheme, Rest] -> case gleam@string:split_once(Rest, <<"/"/utf8>>) of {ok, {Host, Path}} -> {ok, {Scheme, Host, <<"/"/utf8, Path/binary>>}}; {error, _} -> {ok, {Scheme, Rest, <<"/"/utf8>>}} end; _ -> {error, {invalid_rpc_url, <<"Invalid URL format - must include scheme (http:// or https://)"/utf8>>}} end. -file("src/gleeth/rpc/client.gleam", 137). -spec send_http_request(binary(), binary()) -> {ok, gleam@http@response:response(binary())} | {error, gleeth@rpc@types:gleeth_error()}. send_http_request(Rpc_url, Body) -> Req = begin _pipe = gleam@http@request:new(), _pipe@1 = gleam@http@request:set_method(_pipe, post), _pipe@2 = gleam@http@request:set_body(_pipe@1, Body), _pipe@3 = gleam@http@request:set_header( _pipe@2, <<"content-type"/utf8>>, <<"application/json"/utf8>> ), gleam@http@request:set_header( _pipe@3, <<"user-agent"/utf8>>, <<"gleeth/1.0"/utf8>> ) end, case parse_url(Rpc_url) of {ok, {Scheme, Host, Path}} -> Req_with_scheme = case Scheme of <<"https"/utf8>> -> gleam@http@request:set_scheme(Req, https); _ -> gleam@http@request:set_scheme(Req, http) end, Req_with_host = gleam@http@request:set_host(Req_with_scheme, Host), Req_with_path = gleam@http@request:set_path(Req_with_host, Path), case gleam@httpc:send(Req_with_path) of {ok, Response} -> {ok, Response}; {error, _} -> {error, {network_error, <<"Failed to send HTTP request"/utf8>>}} end; {error, Err} -> {error, Err} end. -file("src/gleeth/rpc/client.gleam", 15). -spec make_request(binary(), binary(), list(gleam@json:json())) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. make_request(Rpc_url, Method, Params) -> Json_rpc_request = {json_rpc_request, <<"2.0"/utf8>>, Method, Params, 1}, gleam@result:'try'( encode_request(Json_rpc_request), fun(Request_json) -> gleam@result:'try'( send_http_request(Rpc_url, Request_json), fun(Http_response) -> case erlang:element(2, Http_response) of 200 -> {ok, erlang:element(4, Http_response)}; Status -> {error, {network_error, <<"HTTP request failed with status: "/utf8, (erlang:integer_to_binary(Status))/binary>>}} end end ) end ). -file("src/gleeth/rpc/client.gleam", 60). -spec do_request_with_retry( binary(), binary(), list(gleam@json:json()), integer(), integer(), integer(), integer() ) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. do_request_with_retry( Rpc_url, Method, Params, Max_retries, Backoff_ms, Max_backoff_ms, Attempt ) -> Json_rpc_request = {json_rpc_request, <<"2.0"/utf8>>, Method, Params, 1}, case encode_request(Json_rpc_request) of {error, E} -> {error, E}; {ok, Request_json} -> case send_http_request(Rpc_url, Request_json) of {ok, Http_response} -> case erlang:element(2, Http_response) of 200 -> {ok, erlang:element(4, Http_response)}; 429 when Attempt < Max_retries -> gleam_erlang_ffi:sleep(Backoff_ms), Next_backoff = gleam@int:min( Backoff_ms * 2, Max_backoff_ms ), do_request_with_retry( Rpc_url, Method, Params, Max_retries, Next_backoff, Max_backoff_ms, Attempt + 1 ); 503 when Attempt < Max_retries -> gleam_erlang_ffi:sleep(Backoff_ms), Next_backoff = gleam@int:min( Backoff_ms * 2, Max_backoff_ms ), do_request_with_retry( Rpc_url, Method, Params, Max_retries, Next_backoff, Max_backoff_ms, Attempt + 1 ); Status -> {error, {network_error, <<"HTTP request failed with status: "/utf8, (erlang:integer_to_binary(Status))/binary>>}} end; {error, _} when Attempt < Max_retries -> gleam_erlang_ffi:sleep(Backoff_ms), Next_backoff@1 = gleam@int:min( Backoff_ms * 2, Max_backoff_ms ), do_request_with_retry( Rpc_url, Method, Params, Max_retries, Next_backoff@1, Max_backoff_ms, Attempt + 1 ); {error, E@1} -> {error, E@1} end end. -file("src/gleeth/rpc/client.gleam", 43). ?DOC( " Make a JSON-RPC request with automatic retry on transient errors.\n" " Retries on HTTP 429 (rate limited), 503 (service unavailable), and\n" " connection failures, using exponential backoff from the retry config.\n" ). -spec make_request_with_retry( binary(), binary(), list(gleam@json:json()), gleeth@provider:retry_config() ) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. make_request_with_retry(Rpc_url, Method, Params, Retry_config) -> do_request_with_retry( Rpc_url, Method, Params, erlang:element(2, Retry_config), erlang:element(3, Retry_config), erlang:element(4, Retry_config), 0 ). -file("src/gleeth/rpc/client.gleam", 170). ?DOC( " Send a batch of JSON-RPC requests in a single HTTP call.\n" " The body should be a JSON array of request objects.\n" " Returns the raw response body (a JSON array of responses).\n" ). -spec make_batch_request(binary(), binary()) -> {ok, binary()} | {error, gleeth@rpc@types:gleeth_error()}. make_batch_request(Rpc_url, Batch_body) -> gleam@result:'try'( send_http_request(Rpc_url, Batch_body), fun(Http_response) -> case erlang:element(2, Http_response) of 200 -> {ok, erlang:element(4, Http_response)}; Status -> {error, {network_error, <<"HTTP request failed with status: "/utf8, (erlang:integer_to_binary(Status))/binary>>}} end end ).