Current section
Files
Jump to
Current section
Files
src/gleeth@chain.erl
-module(gleeth@chain).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeth/chain.gleam").
-export([by_id_in/2, to_provider/1, add/2, list/1, default_registry/0, by_id/1, by_name_in/2, by_name/1]).
-export_type([chain_config/0, registry/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(
" Multi-chain configuration registry.\n"
"\n"
" Pre-configured entries for common EVM networks with chain ID, name,\n"
" RPC URL, block explorer, and native currency. Data sourced from\n"
" ethereum-lists/chains (the canonical chain registry used by chainlist.org).\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" let assert Ok(config) = chain.by_name(\"arbitrum\")\n"
" let assert Ok(p) = chain.to_provider(config)\n"
"\n"
" // Or look up by chain ID\n"
" let assert Ok(config) = chain.by_id(137)\n"
" config.name // \"Polygon\"\n"
" ```\n"
).
-type chain_config() :: {chain_config,
integer(),
binary(),
binary(),
binary(),
binary(),
boolean()}.
-type registry() :: {registry, gleam@dict:dict(integer(), chain_config())}.
-file("src/gleeth/chain.gleam", 74).
?DOC(" Look up a chain by ID in a custom registry.\n").
-spec by_id_in(registry(), integer()) -> {ok, chain_config()} |
{error, binary()}.
by_id_in(Registry, Id) ->
_pipe = gleam_stdlib:map_get(erlang:element(2, Registry), Id),
gleam@result:map_error(
_pipe,
fun(_) ->
<<"Unknown chain ID: "/utf8, (gleam@string:inspect(Id))/binary>>
end
).
-file("src/gleeth/chain.gleam", 105).
?DOC(
" Create a Provider from a chain config. Uses the chain's default RPC URL\n"
" with retry enabled and chain ID set.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" let assert Ok(config) = chain.by_name(\"base\")\n"
" let assert Ok(p) = chain.to_provider(config)\n"
" ```\n"
).
-spec to_provider(chain_config()) -> {ok, gleeth@provider:provider()} |
{error, binary()}.
to_provider(Config) ->
case erlang:element(4, Config) of
<<""/utf8>> ->
{error,
<<"No RPC URL configured for "/utf8,
(erlang:element(3, Config))/binary>>};
Url ->
case gleeth@provider:new(Url) of
{ok, P} ->
{ok,
begin
_pipe = P,
_pipe@1 = gleeth@provider:with_chain_id(
_pipe,
erlang:element(2, Config)
),
gleeth@provider:with_retry(
_pipe@1,
gleeth@provider:default_retry()
)
end};
{error, _} ->
{error,
<<"Invalid RPC URL for "/utf8,
(erlang:element(3, Config))/binary>>}
end
end.
-file("src/gleeth/chain.gleam", 134).
?DOC(
" Add a custom chain to a registry.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" let registry = chain.default_registry()\n"
" |> chain.add(chain.ChainConfig(\n"
" id: 56, name: \"BNB Smart Chain\",\n"
" rpc_url: \"https://bsc-dataseed.binance.org\",\n"
" explorer_url: \"https://bscscan.com\",\n"
" native_currency: \"BNB\", testnet: False,\n"
" ))\n"
" ```\n"
).
-spec add(registry(), chain_config()) -> registry().
add(Registry, Config) ->
{registry,
gleam@dict:insert(
erlang:element(2, Registry),
erlang:element(2, Config),
Config
)}.
-file("src/gleeth/chain.gleam", 139).
?DOC(" List all chains in a registry.\n").
-spec list(registry()) -> list(chain_config()).
list(Registry) ->
maps:values(erlang:element(2, Registry)).
-file("src/gleeth/chain.gleam", 145).
?DOC(
" The default registry with common EVM networks.\n"
" RPC URLs and metadata sourced from ethereum-lists/chains.\n"
).
-spec default_registry() -> registry().
default_registry() ->
{registry,
maps:from_list(
[{1,
{chain_config,
1,
<<"Ethereum Mainnet"/utf8>>,
<<"https://ethereum-rpc.publicnode.com"/utf8>>,
<<"https://etherscan.io"/utf8>>,
<<"ETH"/utf8>>,
false}},
{11155111,
{chain_config,
11155111,
<<"Sepolia"/utf8>>,
<<"https://rpc.sepolia.org"/utf8>>,
<<"https://sepolia.etherscan.io"/utf8>>,
<<"ETH"/utf8>>,
true}},
{42161,
{chain_config,
42161,
<<"Arbitrum One"/utf8>>,
<<"https://arb1.arbitrum.io/rpc"/utf8>>,
<<"https://arbiscan.io"/utf8>>,
<<"ETH"/utf8>>,
false}},
{10,
{chain_config,
10,
<<"OP Mainnet"/utf8>>,
<<"https://mainnet.optimism.io"/utf8>>,
<<"https://optimistic.etherscan.io"/utf8>>,
<<"ETH"/utf8>>,
false}},
{137,
{chain_config,
137,
<<"Polygon"/utf8>>,
<<"https://polygon.drpc.org"/utf8>>,
<<"https://polygonscan.com"/utf8>>,
<<"POL"/utf8>>,
false}},
{8453,
{chain_config,
8453,
<<"Base"/utf8>>,
<<"https://mainnet.base.org"/utf8>>,
<<"https://basescan.org"/utf8>>,
<<"ETH"/utf8>>,
false}}]
)}.
-file("src/gleeth/chain.gleam", 56).
?DOC(
" Look up a chain by ID from the default registry.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" let assert Ok(config) = chain.by_id(1)\n"
" config.name // \"Ethereum Mainnet\"\n"
" ```\n"
).
-spec by_id(integer()) -> {ok, chain_config()} | {error, binary()}.
by_id(Id) ->
by_id_in(default_registry(), Id).
-file("src/gleeth/chain.gleam", 223).
?DOC(" Match common short names/aliases for chains.\n").
-spec matches_alias(chain_config(), binary()) -> boolean().
matches_alias(Config, Lower_name) ->
case erlang:element(2, Config) of
1 ->
(Lower_name =:= <<"mainnet"/utf8>>) orelse (Lower_name =:= <<"ethereum"/utf8>>);
11155111 ->
Lower_name =:= <<"sepolia"/utf8>>;
42161 ->
Lower_name =:= <<"arbitrum"/utf8>>;
10 ->
(Lower_name =:= <<"optimism"/utf8>>) orelse (Lower_name =:= <<"op"/utf8>>);
137 ->
(Lower_name =:= <<"polygon"/utf8>>) orelse (Lower_name =:= <<"matic"/utf8>>);
8453 ->
Lower_name =:= <<"base"/utf8>>;
_ ->
false
end.
-file("src/gleeth/chain.gleam", 80).
?DOC(" Look up a chain by name in a custom registry (case-insensitive).\n").
-spec by_name_in(registry(), binary()) -> {ok, chain_config()} |
{error, binary()}.
by_name_in(Registry, Name) ->
Lower = string:lowercase(Name),
Found = begin
_pipe = maps:values(erlang:element(2, Registry)),
gleam@list:find(
_pipe,
fun(C) ->
(string:lowercase(erlang:element(3, C)) =:= Lower) orelse matches_alias(
C,
Lower
)
end
)
end,
case Found of
{ok, Config} ->
{ok, Config};
{error, _} ->
{error, <<"Unknown chain: "/utf8, Name/binary>>}
end.
-file("src/gleeth/chain.gleam", 69).
?DOC(
" Look up a chain by name from the default registry (case-insensitive).\n"
" Matches against the full name or common short names.\n"
"\n"
" ## Examples\n"
"\n"
" ```gleam\n"
" let assert Ok(config) = chain.by_name(\"arbitrum\")\n"
" config.id // 42161\n"
" ```\n"
).
-spec by_name(binary()) -> {ok, chain_config()} | {error, binary()}.
by_name(Name) ->
by_name_in(default_registry(), Name).