-module(gleeth@nonce). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/gleeth/nonce.gleam"). -export([new/2, next/1, reset/2]). -export_type([nonce_manager/0]). -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( " Nonce manager for tracking and auto-incrementing transaction nonces.\n" "\n" " Fetches the initial nonce from the network and increments locally on\n" " each call to `next`, avoiding redundant RPC round-trips when sending\n" " multiple transactions in sequence.\n" ). -type nonce_manager() :: {nonce_manager, binary(), gleam@option:option(integer()), binary()}. -file("src/gleeth/nonce.gleam", 31). ?DOC( " Create a new nonce manager for the given address.\n" " Fetches the current pending nonce from the network.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let assert Ok(p) = provider.new(\"http://localhost:8545\")\n" " let address = wallet.get_address(w)\n" "\n" " let assert Ok(nm) = nonce.new(p, address)\n" " ```\n" ). -spec new(gleeth@provider:provider(), binary()) -> {ok, nonce_manager()} | {error, gleeth@rpc@types:gleeth_error()}. new(Provider, Address) -> gleam@result:'try'( gleeth@rpc@methods:get_transaction_count( Provider, Address, <<"pending"/utf8>> ), fun(Nonce_hex) -> gleam@result:'try'( begin _pipe = gleeth@wei:to_int(Nonce_hex), gleam@result:map_error( _pipe, fun(Msg) -> {parse_error, Msg} end ) end, fun(Nonce_int) -> {ok, {nonce_manager, Address, {some, Nonce_int}, gleeth@provider:rpc_url(Provider)}} end ) end ). -file("src/gleeth/nonce.gleam", 68). ?DOC( " Get the next nonce as a hex string and return an updated manager.\n" " The first call returns the nonce fetched during `new`.\n" " Subsequent calls increment locally without an RPC call.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let assert Ok(nm) = nonce.new(provider, address)\n" "\n" " // First call returns the nonce fetched from the network\n" " let assert Ok(#(nm, nonce_hex)) = nonce.next(nm)\n" " // nonce_hex is e.g. \"0x5\"\n" "\n" " // Second call increments locally - no RPC round-trip\n" " let assert Ok(#(nm, next_hex)) = nonce.next(nm)\n" " // next_hex is \"0x6\"\n" " ```\n" ). -spec next(nonce_manager()) -> {ok, {nonce_manager(), binary()}} | {error, gleeth@rpc@types:gleeth_error()}. next(Manager) -> case erlang:element(3, Manager) of {some, N} -> Hex_nonce = gleeth@wei:from_int(N), Updated = {nonce_manager, erlang:element(2, Manager), {some, N + 1}, erlang:element(4, Manager)}, {ok, {Updated, Hex_nonce}}; none -> {error, {parse_error, <<"Nonce manager not initialized - call new() first"/utf8>>}} end. -file("src/gleeth/nonce.gleam", 97). ?DOC( " Reset the nonce manager by re-fetching the nonce from the network.\n" " Useful after a transaction fails or when the on-chain nonce may have\n" " changed due to activity from another client.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " // After a failed transaction, resync with the network\n" " let assert Ok(nm) = nonce.reset(nm, provider)\n" "\n" " // Continue sending with the correct nonce\n" " let assert Ok(#(nm, nonce_hex)) = nonce.next(nm)\n" " ```\n" ). -spec reset(nonce_manager(), gleeth@provider:provider()) -> {ok, nonce_manager()} | {error, gleeth@rpc@types:gleeth_error()}. reset(Manager, Provider) -> gleam@result:'try'( gleeth@rpc@methods:get_transaction_count( Provider, erlang:element(2, Manager), <<"pending"/utf8>> ), fun(Nonce_hex) -> gleam@result:'try'( begin _pipe = gleeth@wei:to_int(Nonce_hex), gleam@result:map_error( _pipe, fun(Msg) -> {parse_error, Msg} end ) end, fun(Nonce_int) -> {ok, {nonce_manager, erlang:element(2, Manager), {some, Nonce_int}, gleeth@provider:rpc_url(Provider)}} end ) end ).