-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).