UNPKG

@pinax/graph-networks-registry

Version:

TypeScript types and helpers for The Graph Networks Registry

259 lines (258 loc) 9.85 kB
import { applyEnvVars } from "./env.js"; import { schemaVersion } from "./version.js"; const REGISTRY_BASE_URL = "https://networks-registry.thegraph.com"; const FALLBACK_BASE_URL = "https://raw.githubusercontent.com/graphprotocol/networks-registry/refs/heads/main/public"; let readFileSync; try { // Only import fs in Node.js environment const fs = require("fs"); readFileSync = fs.readFileSync; } catch { } /** * Client for interacting with The Graph Networks Registry. * Provides methods to load the registry from json, file or URL. */ export class NetworksRegistry { /** * Creates a new NetworksRegistry instance. * @param registry - The parsed NetworksRegistry data */ constructor(registry) { this.registry = registry; } /** * Gets all networks in the registry. * @returns Array of all network elements */ get networks() { return this.registry.networks; } /** * Gets the version of the loaded registry. * @returns Version string */ get version() { return this.registry.version; } /** * Gets the date of the last update of the registry. * @returns Date object */ get updatedAt() { return new Date(this.registry.updatedAt); } /** * Attempts to fetch the registry from a given URL, returns null if fetch fails * @internal */ static async tryFetchRegistry(url) { try { return await NetworksRegistry.fromUrl(url); } catch { return null; } } /** * Fetches and loads the latest version of the networks registry. First tries to fetch from * the primary registry URL at networks-registry.thegraph.com, then falls back to the fallback URL at GitHub * Uses the library version to determine the latest compatible registry URL. * Library version 0.5.x will use the latest registry version 0.5.y even if 0.6.z is available * * @returns Promise that resolves to a new NetworksRegistry instance * @throws Error if the registry fetch fails * * @example * ```typescript * const registry = await NetworksRegistry.fromLatestVersion(); * ``` */ static async fromLatestVersion() { const primaryUrl = NetworksRegistry.getLatestVersionUrl(); const primaryRegistry = await NetworksRegistry.tryFetchRegistry(primaryUrl); if (primaryRegistry) return primaryRegistry; const fallbackUrl = NetworksRegistry.getLatestVersionFallbackUrl(); const fallbackRegistry = await NetworksRegistry.tryFetchRegistry(fallbackUrl); if (fallbackRegistry) return fallbackRegistry; throw new Error(`Failed to fetch registry from ${primaryUrl}`); } /** * Fetches and loads a specific version of the networks registry. First tries to fetch from * the primary registry URL at networks-registry.thegraph.com, then falls back to the fallback URL at GitHub * * @param version - The exact version to fetch (e.g. "0.5.0") * @returns Promise that resolves to a new NetworksRegistry instance * @throws Error if the registry fetch fails * * @example * ```typescript * const registry = await NetworksRegistry.fromExactVersion("0.5.0"); * ``` */ static async fromExactVersion(version) { const primaryUrl = NetworksRegistry.getExactVersionUrl(version); const primaryRegistry = await NetworksRegistry.tryFetchRegistry(primaryUrl); if (primaryRegistry) return primaryRegistry; const fallbackUrl = NetworksRegistry.getExactVersionFallbackUrl(version); const fallbackRegistry = await NetworksRegistry.tryFetchRegistry(fallbackUrl); if (fallbackRegistry) return fallbackRegistry; throw new Error(`Failed to fetch registry from ${primaryUrl}`); } /** * Loads the networks registry from a URL. * * @param url - The URL to fetch the registry from * @returns Promise that resolves to a new NetworksRegistry instance * @throws Error if the fetch fails or the response is invalid */ static async fromUrl(url) { const response = await fetch(url); if (!response.ok) { throw new Error(`Failed to fetch registry: ${response.statusText}`); } const json = await response.text(); return NetworksRegistry.fromJson(json); } /** * Creates a new registry instance from a JSON string. * * @param json - The JSON string containing registry data * @returns A new NetworksRegistry instance * @throws Error if the JSON is invalid */ static fromJson(json) { const parsedData = JSON.parse(json); const networksRegistry = parsedData; return new NetworksRegistry(networksRegistry); } /** * Loads the networks registry from a local JSON file. * * @param path - Path to the JSON file * @returns A new NetworksRegistry instance * @throws Error if the file cannot be read or contains invalid data */ static fromFile(path) { if (!readFileSync) { throw new Error("File system operations are not supported in this environment"); } const contents = readFileSync(path, "utf-8"); return NetworksRegistry.fromJson(contents); } /** * Gets the URL for the latest compatible version of the registry. * Uses the major and minor version from package.json. * * @returns The URL string for the latest version */ static getLatestVersionUrl() { const [major, minor] = schemaVersion.split("."); return `${REGISTRY_BASE_URL}/TheGraphNetworksRegistry_v${major}_${minor}_x.json`; } /** * Gets the URL for the latest compatible version of the registry at GitHub. * Uses the major and minor version from package.json. * * @returns The URL string for the latest version */ static getLatestVersionFallbackUrl() { const [major, minor] = schemaVersion.split("."); return `${FALLBACK_BASE_URL}/TheGraphNetworksRegistry_v${major}_${minor}_x.json`; } /** * Gets the URL for a specific version of the registry. * * @param version - The exact version (e.g. "0.5.0") * @returns The URL string for the specified version */ static getExactVersionUrl(version) { return `${REGISTRY_BASE_URL}/TheGraphNetworksRegistry_v${version.replace(/\./g, "_")}.json`; } /** * Gets the URL for a specific version of the registry at GitHub. * * @param version - The exact version (e.g. "0.5.0") * @returns The URL string for the specified version */ static getExactVersionFallbackUrl(version) { return `${FALLBACK_BASE_URL}/TheGraphNetworksRegistry_v${version.replace(/\./g, "_")}.json`; } /** * Finds a network by its unique identifier. * * @param id - The network ID (e.g. "mainnet", "optimism") * @returns The network if found, undefined otherwise * * @example * ```typescript * const mainnet = registry.getNetworkById("mainnet"); * ``` */ getNetworkById(id) { return this.registry.networks.find((network) => network.id === id); } /** * Finds a network by its ID or one of its aliases. * * @param alias - The network ID or alias (e.g. "eth" for Ethereum mainnet) * @returns The network if found, undefined otherwise * * @example * ```typescript * const ethereum = registry.getNetworkByAlias("eth"); * ``` */ getNetworkByAlias(alias) { return this.registry.networks.find((network) => network.id === alias || network.aliases?.includes(alias)); } /** * Gets API URLs for a network, filtered by kind and with environment variables applied. * Environment variable placeholders in the format {VARIABLE_NAME} will be replaced with * actual environment variable values. URLs that reference non-existent environment * variables will be omitted from the result. * * @param networkId - The network ID or alias * @param kinds - Optional array of API URL kinds to filter by. If not provided or empty, returns all kinds * @returns Array of API URLs with environment variables applied * * @example * ```typescript * // Get all Etherscan API URLs * const etherscanUrls = registry.getApiUrls("mainnet", [APIURLKind.Etherscan]); * * // Get all API URLs for the network * const allUrls = registry.getApiUrls("mainnet"); * ``` */ getApiUrls(networkId, kinds = []) { const apis = this.getNetworkById(networkId)?.apiUrls ?? this.getNetworkByAlias(networkId)?.apiUrls ?? []; return apis .filter(({ kind }) => kinds.length === 0 || kinds.includes(kind)) .map(({ url }) => applyEnvVars(url)) .filter(Boolean); } /** * Gets RPC URLs for a network with environment variables applied. * Environment variable placeholders in the format {VARIABLE_NAME} will be replaced with * actual environment variable values. URLs that reference non-existent environment * variables will be omitted from the result. * * @param networkId - The network ID or alias * @returns Array of RPC URLs with environment variables applied * * @example * ```typescript * // Get all RPC URLs for ethereum mainnet * const rpcUrls = registry.getRpcUrls("mainnet"); * ``` */ getRpcUrls(networkId) { const urls = this.getNetworkById(networkId)?.rpcUrls ?? this.getNetworkByAlias(networkId)?.rpcUrls ?? []; return urls.map((url) => applyEnvVars(url)).filter(Boolean); } }