account/ChainRpcEndpointProvider.cpp¶
Implementation of the ChainList RPC endpoint loading and validator wiring. More...
Namespaces¶
| Name |
|---|
| sgns |
Detailed Description¶
Implementation of the ChainList RPC endpoint loading and validator wiring.
Date: 2026-05-27 SuperGenius
Source code¶
#include "account/ChainRpcEndpointProvider.hpp"
#include <fstream>
#include <iterator>
#include <unordered_map>
#include <vector>
#include <eth/chainlist_provider.hpp>
namespace sgns
{
ChainRpcEndpointProvider::ChainRpcEndpointProvider( ChainIdMap chain_id_map )
: chain_id_map_( std::move( chain_id_map ) )
{
}
bool ChainRpcEndpointProvider::Initialize( PublicChainInputValidator &validator,
const ChainRpcProviderConfig &config,
const base::Logger &logger ) const
{
if ( chain_id_map_.empty() )
{
logger->warn( "ChainRpcEndpointProvider: no chain ID mappings configured" );
return false;
}
// Collect the numeric chain IDs we care about.
std::vector<uint64_t> configured_chain_ids;
for ( const auto &[name, chain_id] : chain_id_map_ )
{
(void)name;
configured_chain_ids.push_back( chain_id );
}
static constexpr uint8_t kPublicEndpointWeight = 25;
static constexpr uint8_t kDirectEndpointWeight = 50;
std::unordered_map<uint64_t, std::vector<WeightedRpcEndpoint>> endpoints_by_chain;
// ── Public endpoints from the ChainList provider ──────────────
if ( !config.chains_json_path.empty() )
{
std::ifstream file( config.chains_json_path, std::ios::binary );
if ( !file.is_open() )
{
logger->warn( "ChainRpcEndpointProvider: chains.json not found at {}",
config.chains_json_path.string() );
// Continue — direct endpoints may still be available.
}
else
{
std::string json_text( ( std::istreambuf_iterator<char>( file ) ),
std::istreambuf_iterator<char>() );
file.close();
if ( json_text.empty() )
{
logger->warn( "ChainRpcEndpointProvider: chains.json is empty at {}",
config.chains_json_path.string() );
}
else
{
auto parse_result = eth::rpc::load_chainlist_from_json_text( json_text );
if ( !parse_result )
{
logger->warn( "ChainRpcEndpointProvider: failed to parse chains.json: {}",
parse_result.error().field );
}
else
{
auto filtered = eth::rpc::filter_to_configured_chains(
std::move( parse_result.value() ), configured_chain_ids );
for ( const auto &ep : filtered )
{
endpoints_by_chain[ep.chain_id].push_back(
{ ep.url_template, kPublicEndpointWeight } );
}
}
}
}
}
// ── Direct API-key endpoints from the app layer ───────────────
for ( const auto &[chain_id_str, eps] : config.direct_endpoints )
{
uint64_t chain_id = 0;
try
{
chain_id = std::stoull( chain_id_str );
}
catch ( ... )
{
logger->warn( "ChainRpcEndpointProvider: invalid chain ID '{}' in direct endpoints",
chain_id_str );
continue;
}
auto &target = endpoints_by_chain[chain_id];
for ( const auto &ep : eps )
{
target.push_back( { ep.url, kDirectEndpointWeight } );
}
}
// ── Wire endpoints into the validator ─────────────────────────
bool any_wired = false;
for ( auto &[chain_id, endpoints] : endpoints_by_chain )
{
const auto count = endpoints.size();
validator.SetRpcEndpoints( std::to_string( chain_id ), std::move( endpoints ) );
logger->info( "ChainRpcEndpointProvider: wired {} RPC endpoints for chain_id={}",
count, chain_id );
any_wired = true;
}
if ( !any_wired )
{
logger->warn( "ChainRpcEndpointProvider: no RPC endpoints found for any configured chain" );
}
return any_wired;
}
} // namespace sgns
Updated on 2026-06-05 at 17:22:19 -0700