{"version":3,"file":"registry.mjs","names":[],"sources":["../../src/providers/index.ts","../../src/core/registry.ts"],"sourcesContent":["/** Built-in providers: registry metadata plus a loader for the implementation */\n\nimport type { ProviderCapability, ProviderEntry } from \"../core/provider.js\";\nimport { ARWEAVE_GATEWAY_URL, DCRDATA_INSIGHT_URL, HORIZON_URL } from \"../core/endpoints.js\";\n\ntype BuiltinProviderEntry = ProviderEntry & {\n  capabilities: readonly ProviderCapability[];\n};\n\n/**\n * Every provider shipped with the package, in registration order.\n *\n * A provider missing here is invisible to `create()`. `test/unit/registry.test.ts` compares each\n * entry against the class it loads, so metadata cannot drift away from the implementation.\n */\nexport const builtins: readonly ProviderEntry[] = [\n  {\n    key: \"etherscan\",\n    chains: [\n      \"ethereum\",\n      \"base\",\n      \"arbitrum\",\n      \"optimism\",\n      \"polygon\",\n      \"bsc\",\n      \"avalanche\",\n      \"gnosis\",\n      \"linea\",\n      \"berachain\",\n    ],\n    capabilities: [\n      \"balances\",\n      \"txHistory\",\n      \"txDetail\",\n      \"contractInfo\",\n      \"tokenBalances\",\n      \"tokenTransfers\",\n      \"gasData\",\n      \"blockInfo\",\n    ],\n    defaultURL: \"https://api.etherscan.io/v2/api\",\n    load: () => import(\"./etherscan.js\").then((m) => m.Etherscan),\n  },\n  {\n    key: \"blockscout\",\n    chains: [\n      \"ethereum\",\n      \"base\",\n      \"arbitrum\",\n      \"optimism\",\n      \"polygon\",\n      \"gnosis\",\n      \"linea\",\n      \"scroll\",\n      \"zksync\",\n      \"avalanche\",\n    ],\n    capabilities: [\n      \"balances\",\n      \"txHistory\",\n      \"txDetail\",\n      \"contractInfo\",\n      \"tokenBalances\",\n      \"tokenTransfers\",\n      \"gasData\",\n      \"blockInfo\",\n    ],\n    defaultURL: \"https://eth.blockscout.com\",\n    load: () => import(\"./blockscout.js\").then((m) => m.Blockscout),\n  },\n  {\n    key: \"blockchair\",\n    chains: [\"bitcoin\", \"ethereum\", \"ecash\"],\n    capabilities: [\"balances\", \"txHistory\", \"txDetail\", \"blockInfo\"],\n    defaultURL: \"https://api.blockchair.com\",\n    load: () => import(\"./blockchair.js\").then((m) => m.Blockchair),\n  },\n  {\n    key: \"mempool\",\n    chains: [\"bitcoin\", \"litecoin\", \"pepecoin\"],\n    capabilities: [\"balances\", \"txHistory\", \"txDetail\", \"utxos\", \"gasData\", \"blockInfo\"],\n    defaultURL: \"https://mempool.space\",\n    load: () => import(\"./mempool.js\").then((m) => m.Mempool),\n  },\n  {\n    key: \"blockstream\",\n    chains: [\"bitcoin\"],\n    capabilities: [\"balances\", \"txHistory\", \"txDetail\", \"utxos\", \"blockInfo\"],\n    defaultURL: \"https://blockstream.info\",\n    load: () => import(\"./blockstream.js\").then((m) => m.Blockstream),\n  },\n  {\n    key: \"solscan\",\n    chains: [\"solana\"],\n    capabilities: [\"balances\", \"txHistory\", \"txDetail\", \"blockInfo\"],\n    defaultURL: \"https://pro-api.solscan.io/v2.0\",\n    load: () => import(\"./solscan.js\").then((m) => m.Solscan),\n  },\n  {\n    key: \"helius\",\n    chains: [\"solana\"],\n    capabilities: [\"txHistory\", \"txDetail\", \"tokenBalances\"],\n    defaultURL: \"https://mainnet.helius-rpc.com\",\n    load: () => import(\"./helius.js\").then((m) => m.Helius),\n  },\n  {\n    key: \"ton\",\n    chains: [\"ton\"],\n    capabilities: [\"balances\", \"txHistory\"],\n    defaultURL: \"https://tonapi.io\",\n    load: () => import(\"./ton.js\").then((m) => m.Ton),\n  },\n  {\n    key: \"tronscan\",\n    chains: [\"tron\"],\n    capabilities: [\"balances\", \"txHistory\", \"txDetail\", \"blockInfo\"],\n    defaultURL: \"https://apilist.tronscanapi.com\",\n    load: () => import(\"./tronscan.js\").then((m) => m.Tronscan),\n  },\n  {\n    key: \"aptos\",\n    chains: [\"aptos\"],\n    capabilities: [],\n    load: () => import(\"./aptos.js\").then((m) => m.Aptos),\n  },\n  {\n    key: \"blockberry\",\n    chains: [\"sui\"],\n    capabilities: [\"balances\", \"txHistory\"],\n    defaultURL: \"https://api.blockberry.one/sui\",\n    load: () => import(\"./blockberry.js\").then((m) => m.Blockberry),\n  },\n  {\n    key: \"koios\",\n    chains: [\"cardano\"],\n    capabilities: [\"balances\", \"txHistory\", \"txDetail\", \"tokenBalances\"],\n    defaultURL: \"https://api.koios.rest/api/v1\",\n    load: () => import(\"./koios.js\").then((m) => m.Koios),\n  },\n  {\n    key: \"arweave\",\n    chains: [\"arweave\"],\n    capabilities: [\"balances\", \"txHistory\", \"txDetail\", \"blockInfo\"],\n    defaultURL: ARWEAVE_GATEWAY_URL,\n    load: () => import(\"./arweave.js\").then((m) => m.Arweave),\n  },\n  {\n    key: \"dcrdata\",\n    chains: [\"decred\"],\n    capabilities: [\"balances\", \"txHistory\", \"txDetail\", \"blockInfo\"],\n    defaultURL: DCRDATA_INSIGHT_URL,\n    load: () => import(\"./dcrdata.js\").then((m) => m.Dcrdata),\n  },\n  {\n    key: \"horizon\",\n    chains: [\"stellar\"],\n    capabilities: [\n      \"balances\",\n      \"txHistory\",\n      \"txDetail\",\n      \"tokenBalances\",\n      \"tokenTransfers\",\n      \"gasData\",\n      \"blockInfo\",\n    ],\n    defaultURL: HORIZON_URL,\n    load: () => import(\"./horizon.js\").then((m) => m.Horizon),\n  },\n] satisfies readonly BuiltinProviderEntry[];\n","/** Provider registry for Explorers, built from the built-in list on first use */\n\nimport { builtins } from \"../providers/index.js\";\nimport type {\n  Provider,\n  ProviderCapability,\n  ProviderConstructor,\n  ProviderMeta,\n} from \"./provider.js\";\nimport type { ChainKey, ProviderCapabilities, ProviderConfig } from \"./types.js\";\nimport { UnknownProviderError } from \"./errors.js\";\n\ninterface RegistryEntry extends ProviderMeta {\n  load: () => Promise<ProviderConstructor>;\n  providerClass?: ProviderConstructor;\n  providerClassPromise?: Promise<ProviderConstructor>;\n}\n\n/** One registered provider as its registry metadata describes it. */\nexport interface ProviderListing {\n  /** Registry key accepted by `create()` and the `provider` option. */\n  readonly name: string;\n  /** Chains the provider declares. */\n  readonly chains: readonly ChainKey[];\n  /** Public endpoint advertised for the provider. */\n  readonly defaultUrl?: string;\n  /**\n   * Operations the provider declares, in the shape of the instance getter.\n   *\n   * Declared for the provider as a whole, not per chain: a provider can still refuse one of them on\n   * one of its chains at call time. Absent when an external registration left capability metadata\n   * out.\n   */\n  readonly capabilities?: Readonly<ProviderCapabilities>;\n}\n\nlet registry: Map<string, RegistryEntry> | undefined;\n\n/*\n * Return the registry map, filling it with the built-in metadata on the first call.\n *\n * Only the metadata lands here. Provider modules stay unloaded until `create()` asks for one, so a\n * bundle that lists or resolves providers never pulls in ten explorer clients.\n */\nfunction entries(): Map<string, RegistryEntry> {\n  registry ??= new Map(\n    builtins.map(({ key, chains, capabilities, defaultURL, load }): [string, RegistryEntry] => [\n      key,\n      { chains, capabilities, defaultURL, load },\n    ]),\n  );\n  return registry;\n}\n\n/**\n * Register a provider class under its stable `key`.\n *\n * Built-in providers are already registered; this is the entry point for classes living outside the\n * package, and their class is kept as is instead of being loaded on demand. Registering the same\n * name again replaces the previous entry. That is useful in tests, but easy to do by accident in\n * application code.\n *\n * @param {ProviderConstructor} providerClass - The `providerClass` value.\n * @param {Readonly<ProviderMeta>} meta - The `meta` value.\n */\nexport function register(providerClass: ProviderConstructor, meta: Readonly<ProviderMeta>): void {\n  entries().set(providerClass.key, {\n    chains: meta.chains,\n    capabilities: meta.capabilities,\n    defaultURL: meta.defaultURL,\n    load: () => Promise.resolve(providerClass),\n    providerClass,\n  });\n}\n\n/**\n * Create a registered provider with optional backend configuration.\n *\n * The first call for a built-in provider imports its module; later calls reuse the loaded class.\n *\n * @example\n *   ```ts\n *   import { create } from \"@agntn/explorers\";\n *\n *   const provider = await create(\"blockscout\");\n *   const balance = await provider.getBalance(\"0x0000000000000000000000000000000000000000\", \"ethereum\");\n *   ```\n *\n * @throws {UnknownProviderError} When `name` has not been registered.\n *\n * @param {string} name - The `name` value.\n * @param {Readonly<ProviderConfig>} config - The `config` value.\n * @returns {Promise<Provider>} The resulting value.\n */\nexport async function create(name: string, config?: Readonly<ProviderConfig>): Promise<Provider> {\n  const entry = entries().get(name);\n  if (!entry) {\n    throw new UnknownProviderError(name);\n  }\n  if (!entry.providerClass) {\n    entry.providerClassPromise ??= entry.load();\n    try {\n      entry.providerClass = await entry.providerClassPromise;\n    } catch (error) {\n      entry.providerClassPromise = undefined;\n      throw error;\n    }\n  }\n  return new entry.providerClass(config ?? {});\n}\n\n/**\n * Return registered provider names in registration order.\n *\n * @returns {string[]} The resulting value.\n */\nexport function providers(): string[] {\n  return Array.from(entries().keys());\n}\n\n/*\n * Expand a declared capability list into the boolean map `Provider.capabilities` returns. The\n * literal keeps the two shapes in step: a flag added to `ProviderCapabilities` fails to compile here.\n */\nfunction capabilityFlags(declared: readonly ProviderCapability[]): ProviderCapabilities {\n  const supports = (capability: ProviderCapability) => declared.includes(capability);\n  return {\n    balances: supports(\"balances\"),\n    txHistory: supports(\"txHistory\"),\n    txDetail: supports(\"txDetail\"),\n    utxos: supports(\"utxos\"),\n    contractInfo: supports(\"contractInfo\"),\n    tokenBalances: supports(\"tokenBalances\"),\n    tokenTransfers: supports(\"tokenTransfers\"),\n    gasData: supports(\"gasData\"),\n    blockInfo: supports(\"blockInfo\"),\n  };\n}\n\n/**\n * Describe every registered provider from registry metadata alone.\n *\n * Nothing here imports a provider module, so discovery stays cheap and answers the same on every\n * host. A provider whose constructor demands credentials is listed like any other; the credential\n * error waits for the first real read.\n *\n * @returns {ProviderListing[]} One record per provider, in registration order.\n */\nexport function listProviders(): ProviderListing[] {\n  return Array.from(entries(), ([name, entry]) => ({\n    name,\n    chains: [...entry.chains],\n    defaultUrl: entry.defaultURL,\n    capabilities:\n      entry.capabilities === undefined ? undefined : capabilityFlags(entry.capabilities),\n  }));\n}\n\n/**\n * Check whether a name can be passed to `create`.\n *\n * @param {string} name - The `name` value.\n * @returns {boolean} The resulting value.\n */\nexport function has(name: string): boolean {\n  return entries().has(name);\n}\n\n/**\n * Check whether a registered provider declares support for `chain`.\n *\n * @param {string} name - The `name` value.\n * @param {ChainKey} chain - The `chain` value.\n * @returns {boolean} The resulting value.\n */\nexport function supportsChain(name: string, chain: ChainKey): boolean {\n  const entry = entries().get(name);\n  return entry !== undefined && entry.chains.includes(chain);\n}\n\n/**\n * Check whether a registered provider declares support for `capability`.\n *\n * External registrations without capability metadata remain eligible so adding this routing hint\n * does not silently remove existing providers from auto-selection.\n *\n * @param {string} name - The `name` value.\n * @param {ProviderCapability} capability - The required operation.\n * @returns {boolean} Whether the provider can be considered for the operation.\n */\nexport function supportsCapability(name: string, capability: ProviderCapability): boolean {\n  const entry = entries().get(name);\n  return entry !== undefined && (entry.capabilities?.includes(capability) ?? true);\n}\n\n/**\n * Return the public endpoint advertised for a provider.\n *\n * Per-instance `baseUrl` overrides are deliberately not reflected here.\n *\n * @param {string} name - The `name` value.\n * @returns {string | undefined} The resulting value.\n */\nexport function getDefaultURL(name: string): string | undefined {\n  return entries().get(name)?.defaultURL;\n}\n"],"mappings":"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"}