@pinax/graph-networks-registry
Version:
TypeScript types and helpers for The Graph Networks Registry
654 lines (649 loc) • 22.6 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
APIURLKind: () => APIURLKind,
BytesEncoding: () => BytesEncoding,
Convert: () => Convert,
Feature: () => Feature,
NetworkType: () => NetworkType,
NetworksRegistry: () => NetworksRegistry,
Protocol: () => Protocol,
RelationKind: () => RelationKind
});
module.exports = __toCommonJS(index_exports);
// src/types.ts
var APIURLKind = /* @__PURE__ */ ((APIURLKind2) => {
APIURLKind2["Blockscout"] = "blockscout";
APIURLKind2["Etherscan"] = "etherscan";
APIURLKind2["Ethplorer"] = "ethplorer";
APIURLKind2["Other"] = "other";
APIURLKind2["Subscan"] = "subscan";
return APIURLKind2;
})(APIURLKind || {});
var BytesEncoding = /* @__PURE__ */ ((BytesEncoding2) => {
BytesEncoding2["Base58"] = "base58";
BytesEncoding2["Base64"] = "base64";
BytesEncoding2["Hex"] = "hex";
BytesEncoding2["Other"] = "other";
BytesEncoding2["The0Xhex"] = "0xhex";
return BytesEncoding2;
})(BytesEncoding || {});
var Protocol = /* @__PURE__ */ ((Protocol2) => {
Protocol2["Arweave"] = "arweave";
Protocol2["Cosmos"] = "cosmos";
Protocol2["Ethereum"] = "ethereum";
Protocol2["Near"] = "near";
Protocol2["Other"] = "other";
Protocol2["Starknet"] = "starknet";
return Protocol2;
})(Protocol || {});
var NetworkType = /* @__PURE__ */ ((NetworkType2) => {
NetworkType2["Beacon"] = "beacon";
NetworkType2["Devnet"] = "devnet";
NetworkType2["Mainnet"] = "mainnet";
NetworkType2["Testnet"] = "testnet";
return NetworkType2;
})(NetworkType || {});
var RelationKind = /* @__PURE__ */ ((RelationKind2) => {
RelationKind2["BeaconOf"] = "beaconOf";
RelationKind2["EvmOf"] = "evmOf";
RelationKind2["ForkedFrom"] = "forkedFrom";
RelationKind2["L2Of"] = "l2Of";
RelationKind2["Other"] = "other";
RelationKind2["ShardOf"] = "shardOf";
RelationKind2["SvmOf"] = "svmOf";
RelationKind2["TestnetOf"] = "testnetOf";
return RelationKind2;
})(RelationKind || {});
var Feature = /* @__PURE__ */ ((Feature2) => {
Feature2["Dexes"] = "dexes";
Feature2["Nfts"] = "nfts";
Feature2["Other"] = "other";
Feature2["Tokens"] = "tokens";
return Feature2;
})(Feature || {});
var Convert = class {
static toNetworksRegistryInner(json) {
return cast(JSON.parse(json), r("NetworksRegistryInner"));
}
static networksRegistryInnerToJson(value) {
return JSON.stringify(uncast(value, r("NetworksRegistryInner")), null, 2);
}
};
function invalidValue(typ, val, key, parent = "") {
const prettyTyp = prettyTypeName(typ);
const parentText = parent ? ` on ${parent}` : "";
const keyText = key ? ` for key "${key}"` : "";
throw Error(`Invalid value${keyText}${parentText}. Expected ${prettyTyp} but got ${JSON.stringify(val)}`);
}
function prettyTypeName(typ) {
if (Array.isArray(typ)) {
if (typ.length === 2 && typ[0] === void 0) {
return `an optional ${prettyTypeName(typ[1])}`;
} else {
return `one of [${typ.map((a2) => {
return prettyTypeName(a2);
}).join(", ")}]`;
}
} else if (typeof typ === "object" && typ.literal !== void 0) {
return typ.literal;
} else {
return typeof typ;
}
}
function jsonToJSProps(typ) {
if (typ.jsonToJS === void 0) {
const map = {};
typ.props.forEach((p) => map[p.json] = { key: p.js, typ: p.typ });
typ.jsonToJS = map;
}
return typ.jsonToJS;
}
function jsToJSONProps(typ) {
if (typ.jsToJSON === void 0) {
const map = {};
typ.props.forEach((p) => map[p.js] = { key: p.json, typ: p.typ });
typ.jsToJSON = map;
}
return typ.jsToJSON;
}
function transform(val, typ, getProps, key = "", parent = "") {
function transformPrimitive(typ2, val2) {
if (typeof typ2 === typeof val2) return val2;
return invalidValue(typ2, val2, key, parent);
}
function transformUnion(typs, val2) {
const l2 = typs.length;
for (let i = 0; i < l2; i++) {
const typ2 = typs[i];
try {
return transform(val2, typ2, getProps);
} catch (_) {
}
}
return invalidValue(typs, val2, key, parent);
}
function transformEnum(cases, val2) {
if (cases.indexOf(val2) !== -1) return val2;
return invalidValue(cases.map((a2) => {
return l(a2);
}), val2, key, parent);
}
function transformArray(typ2, val2) {
if (!Array.isArray(val2)) return invalidValue(l("array"), val2, key, parent);
return val2.map((el) => transform(el, typ2, getProps));
}
function transformDate(val2) {
if (val2 === null) {
return null;
}
const d = new Date(val2);
if (isNaN(d.valueOf())) {
return invalidValue(l("Date"), val2, key, parent);
}
return d;
}
function transformObject(props, additional, val2) {
if (val2 === null || typeof val2 !== "object" || Array.isArray(val2)) {
return invalidValue(l(ref || "object"), val2, key, parent);
}
const result = {};
Object.getOwnPropertyNames(props).forEach((key2) => {
const prop = props[key2];
const v = Object.prototype.hasOwnProperty.call(val2, key2) ? val2[key2] : void 0;
result[prop.key] = transform(v, prop.typ, getProps, key2, ref);
});
Object.getOwnPropertyNames(val2).forEach((key2) => {
if (!Object.prototype.hasOwnProperty.call(props, key2)) {
result[key2] = transform(val2[key2], additional, getProps, key2, ref);
}
});
return result;
}
if (typ === "any") return val;
if (typ === null) {
if (val === null) return val;
return invalidValue(typ, val, key, parent);
}
if (typ === false) return invalidValue(typ, val, key, parent);
let ref = void 0;
while (typeof typ === "object" && typ.ref !== void 0) {
ref = typ.ref;
typ = typeMap[typ.ref];
}
if (Array.isArray(typ)) return transformEnum(typ, val);
if (typeof typ === "object") {
return typ.hasOwnProperty("unionMembers") ? transformUnion(typ.unionMembers, val) : typ.hasOwnProperty("arrayItems") ? transformArray(typ.arrayItems, val) : typ.hasOwnProperty("props") ? transformObject(getProps(typ), typ.additional, val) : invalidValue(typ, val, key, parent);
}
if (typ === Date && typeof val !== "number") return transformDate(val);
return transformPrimitive(typ, val);
}
function cast(val, typ) {
return transform(val, typ, jsonToJSProps);
}
function uncast(val, typ) {
return transform(val, typ, jsToJSONProps);
}
function l(typ) {
return { literal: typ };
}
function a(typ) {
return { arrayItems: typ };
}
function u(...typs) {
return { unionMembers: typs };
}
function o(props, additional) {
return { props, additional };
}
function r(name) {
return { ref: name };
}
var typeMap = {
"NetworksRegistryInner": o([
{ json: "$schema", js: "$schema", typ: "" },
{ json: "description", js: "description", typ: "" },
{ json: "networks", js: "networks", typ: a(r("Network")) },
{ json: "title", js: "title", typ: "" },
{ json: "updatedAt", js: "updatedAt", typ: Date },
{ json: "version", js: "version", typ: "" }
], false),
"Network": o([
{ json: "aliases", js: "aliases", typ: u(void 0, a("")) },
{ json: "apiUrls", js: "apiUrls", typ: u(void 0, a(r("APIURL"))) },
{ json: "caip2Id", js: "caip2Id", typ: "" },
{ json: "docsUrl", js: "docsUrl", typ: u(void 0, "") },
{ json: "explorerUrls", js: "explorerUrls", typ: u(void 0, a("")) },
{ json: "firehose", js: "firehose", typ: u(void 0, r("Firehose")) },
{ json: "fullName", js: "fullName", typ: "" },
{ json: "graphNode", js: "graphNode", typ: u(void 0, r("GraphNode")) },
{ json: "icon", js: "icon", typ: u(void 0, r("Icon")) },
{ json: "id", js: "id", typ: "" },
{ json: "indexerDocsUrls", js: "indexerDocsUrls", typ: u(void 0, a(r("IndexerDocsURL"))) },
{ json: "issuanceRewards", js: "issuanceRewards", typ: true },
{ json: "nativeToken", js: "nativeToken", typ: u(void 0, "") },
{ json: "networkType", js: "networkType", typ: r("NetworkType") },
{ json: "relations", js: "relations", typ: u(void 0, a(r("Relation"))) },
{ json: "rpcUrls", js: "rpcUrls", typ: u(void 0, a("")) },
{ json: "secondName", js: "secondName", typ: u(void 0, "") },
{ json: "services", js: "services", typ: r("Services") },
{ json: "shortName", js: "shortName", typ: "" },
{ json: "tokenApi", js: "tokenApi", typ: u(void 0, r("TokenAPI")) }
], false),
"APIURL": o([
{ json: "kind", js: "kind", typ: r("APIURLKind") },
{ json: "url", js: "url", typ: "" }
], false),
"Firehose": o([
{ json: "blockFeatures", js: "blockFeatures", typ: u(void 0, a("")) },
{ json: "blockType", js: "blockType", typ: "" },
{ json: "bufUrl", js: "bufUrl", typ: "" },
{ json: "bytesEncoding", js: "bytesEncoding", typ: r("BytesEncoding") },
{ json: "deprecatedAt", js: "deprecatedAt", typ: u(void 0, Date) },
{ json: "evmExtendedModel", js: "evmExtendedModel", typ: u(void 0, true) },
{ json: "firstStreamableBlock", js: "firstStreamableBlock", typ: u(void 0, r("FirstStreamableBlock")) }
], false),
"FirstStreamableBlock": o([
{ json: "height", js: "height", typ: 0 },
{ json: "id", js: "id", typ: "" }
], false),
"GraphNode": o([
{ json: "deprecatedAt", js: "deprecatedAt", typ: u(void 0, Date) },
{ json: "protocol", js: "protocol", typ: u(void 0, r("Protocol")) }
], false),
"Icon": o([
{ json: "web3Icons", js: "web3Icons", typ: u(void 0, r("Web3Icons")) }
], false),
"Web3Icons": o([
{ json: "name", js: "name", typ: "" },
{ json: "variants", js: "variants", typ: u(void 0, a("")) }
], false),
"IndexerDocsURL": o([
{ json: "description", js: "description", typ: u(void 0, "") },
{ json: "url", js: "url", typ: "" }
], false),
"Relation": o([
{ json: "kind", js: "kind", typ: r("RelationKind") },
{ json: "network", js: "network", typ: "" }
], false),
"Services": o([
{ json: "firehose", js: "firehose", typ: u(void 0, a("")) },
{ json: "sps", js: "sps", typ: u(void 0, a("")) },
{ json: "subgraphs", js: "subgraphs", typ: u(void 0, a("")) },
{ json: "substreams", js: "substreams", typ: u(void 0, a("")) },
{ json: "tokenApi", js: "tokenApi", typ: u(void 0, a("")) }
], false),
"TokenAPI": o([
{ json: "deprecatedAt", js: "deprecatedAt", typ: u(void 0, Date) },
{ json: "features", js: "features", typ: u(void 0, a(r("Feature"))) },
{ json: "networkId", js: "networkId", typ: u(void 0, "") }
], false),
"APIURLKind": [
"blockscout",
"etherscan",
"ethplorer",
"other",
"subscan"
],
"BytesEncoding": [
"base58",
"base64",
"hex",
"other",
"0xhex"
],
"Protocol": [
"arweave",
"cosmos",
"ethereum",
"near",
"other",
"starknet"
],
"NetworkType": [
"beacon",
"devnet",
"mainnet",
"testnet"
],
"RelationKind": [
"beaconOf",
"evmOf",
"forkedFrom",
"l2Of",
"other",
"shardOf",
"svmOf",
"testnetOf"
],
"Feature": [
"dexes",
"nfts",
"other",
"tokens"
]
};
// src/env.ts
function applyEnvVars(url) {
const envVars = url.match(/\{([^}]+)\}/g);
if (!envVars) return url;
for (const envVar of envVars) {
const value = process?.env?.[envVar.slice(1, -1)];
if (!value) {
return "";
}
url = url.replace(envVar, value);
}
return url;
}
// src/version.ts
var schemaVersion = "0.7";
// src/client.ts
var REGISTRY_BASE_URL = "https://networks-registry.thegraph.com";
var FALLBACK_BASE_URL = "https://raw.githubusercontent.com/graphprotocol/networks-registry/refs/heads/main/public";
var readFileSync;
try {
const fs = require("fs");
readFileSync = fs.readFileSync;
} catch {
}
var NetworksRegistry = 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
* @deprecated Use getNetworkByGraphId instead
*
* @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
* @deprecated Use getNetworkByGraphId instead
*
* @example
* ```typescript
* const ethereum = registry.getNetworkByAlias("eth");
* ```
*/
getNetworkByAlias(alias) {
return this.registry.networks.find((network) => network.id === alias || network.aliases?.includes(alias));
}
/**
* Finds a network by its graph ID (either its ID field or one of its aliases).
*
* @param id - The graph ID, which could be either the network's ID or one of its aliases
* @returns The network if found, undefined otherwise
*
* @example
* ```typescript
* const mainnet = registry.getNetworkByGraphId("mainnet");
* const ethereum = registry.getNetworkByGraphId("eth");
* ```
*/
getNetworkByGraphId(id) {
return this.registry.networks.find((network) => network.id === id || network.aliases?.includes(id));
}
/**
* Finds a network by its CAIP-2 chain ID.
*
* @param chainId - The CAIP-2 chain ID in the format "[namespace]:[reference]" (e.g., "eip155:1")
* @returns The network if found, undefined otherwise
*
* @example
* ```typescript
* const ethereum = registry.getNetworkByCaip2Id("eip155:1");
* ```
*/
getNetworkByCaip2Id(chainId) {
if (!chainId.includes(":")) {
console.warn("Warning: CAIP-2 Chain ID should be in the format '[namespace]:[reference]', e.g., 'eip155:1'");
return void 0;
}
return this.registry.networks.find((network) => network.caip2Id === chainId);
}
/**
* 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);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
APIURLKind,
BytesEncoding,
Convert,
Feature,
NetworkType,
NetworksRegistry,
Protocol,
RelationKind
});
//# sourceMappingURL=index.js.map