{"version":3,"file":"index.mjs","names":["packageJson.name"],"sources":["../package.json","../src/log.ts","../src/dot/ChainConnectorDot.ts","../src/dot/ChainConnectorDotStub.ts","../src/eth/getChainFromEvmNetwork.ts","../src/eth/getTransportForEvmNetwork.ts","../src/eth/getEvmNetworkPublicClient.ts","../src/eth/getEvmNetworkWalletClient.ts","../src/eth/ChainConnectorEth.ts","../src/eth/ChainConnectorEthStub.ts","../src/sol/getSolRpc.ts","../src/sol/ChainConnectorSol.ts","../src/sol/ChainConnectorSolStub.ts"],"sourcesContent":["","import anylogger from \"anylogger\"\n\nimport packageJson from \"../package.json\"\n\nexport default anylogger(packageJson.name)\n","import { createClient, type SubstrateClient } from \"@polkadot-api/substrate-client\"\nimport {\n  getWsProvider,\n  type StatusChange,\n  WsEvent,\n  type WsJsonRpcProvider,\n} from \"@polkadot-api/ws-provider\"\nimport type { DotNetworkId, IChaindataNetworkProvider } from \"@talismn/chaindata-provider\"\n\nimport log from \"../log\"\nimport type { IChainConnectorDot, SubscriptionCallback } from \"./IChainConnectorDot\"\n\n// errors that require an rpc fallback\n// https://docs.blastapi.io/blast-documentation/things-you-need-to-know/error-reference\nconst BAD_RPC_ERRORS: Record<string, string> = {\n  \"-32097\": \"Rate limit exceeded\",\n  \"-32098\": \"Capacity exceeded\",\n}\n\nconst RESPONSE_TIMEOUT = 30_000 // max wait for an rpc response (including connection time)\nconst KEEP_ALIVE_INTERVAL = 20_000 // periodic system_health to keep idle sockets alive (ws-provider kills quiet sockets after its 40s heartbeat)\n\n/** in-flight requests reject with DestroyedError when a connection is torn down - expected, not worth logging */\nconst isDestroyedError = (error: unknown): boolean =>\n  error instanceof Error && error.name === \"DestroyedError\"\nconst STALE_NOTIFY_TIMEOUT = 30_000 // how long a chain can be disconnected before subscribers are notified\n\nexport class ChainConnectionError extends Error {\n  type: \"CHAIN_CONNECTION_ERROR\"\n  chainId: string\n\n  constructor(chainId: string, options?: ErrorOptions) {\n    super(`Unable to connect to chain ${chainId}`, options)\n\n    this.type = \"CHAIN_CONNECTION_ERROR\"\n    this.chainId = chainId\n  }\n}\n\nexport class StaleRpcError extends Error {\n  type: \"STALE_RPC_ERROR\"\n  chainId: string\n\n  constructor(chainId: string, options?: ErrorOptions) {\n    super(`RPCs are stale/unavailable for chain ${chainId}`, options)\n\n    this.type = \"STALE_RPC_ERROR\"\n    this.chainId = chainId\n  }\n}\n\ntype SocketUserId = number\n\ntype Subscription = {\n  subscribeMethod: string\n  params: unknown[]\n  callback: SubscriptionCallback\n  /** cancels the pending subscribe request, if any */\n  cancelRequest: (() => void) | null\n  /** stops routing notifications to the callback */\n  stopFollow: (() => void) | null\n  serverSubId: string | number | null\n  unsubscribed: boolean\n}\n\ntype Connection = {\n  chainId: DotNetworkId\n  provider: WsJsonRpcProvider\n  client: SubstrateClient\n  users: Set<SocketUserId>\n  subscriptions: Set<Subscription>\n  wasConnected: boolean\n  keepAliveInterval: ReturnType<typeof setInterval> | null\n  staleTimeout: ReturnType<typeof setTimeout> | null\n}\n\n/**\n * ChainConnector provides an interface similar to a websocket JSON-RPC provider, but with three points of difference:\n *\n * 1. ChainConnector methods all accept a `chainId` instead of an array of RPCs. RPCs are then fetched internally from chaindata.\n * 2. ChainConnector creates only one socket connection per chain (via polkadot-api's ws-provider, which handles\n *    endpoint rotation, reconnection and stale-socket detection) and ensures that all downstream requests to a chain\n *    share that connection.\n * 3. Subscriptions return a callable `unsubscribe` method instead of an id, and are automatically re-established\n *    when the provider reconnects (possibly to another endpoint).\n *\n * Additionally, when run on the clientside of a dapp where `window.talismanSub` is available, instead of spinning up new websocket\n * connections this class will forward all requests through to the wallet backend - where another instance of this class will\n * handle the websocket connections.\n */\nexport class ChainConnectorDot implements IChainConnectorDot {\n  #chaindataChainProvider: IChaindataNetworkProvider\n\n  #connections: Record<DotNetworkId, Connection> = {}\n  #pendingConnections: Record<DotNetworkId, Promise<Connection>> = {}\n\n  constructor(chaindataChainProvider: IChaindataNetworkProvider) {\n    this.#chaindataChainProvider = chaindataChainProvider\n  }\n\n  // biome-ignore lint/suspicious/noExplicitAny: legacy\n  async send<T = any>(\n    chainId: DotNetworkId,\n    method: string,\n    params: unknown[],\n    _isCacheable?: boolean | undefined,\n    extraOptions?: {\n      /**\n       * Set to `true` if this query is speculative, i.e. if on some chains it's expected that it will raise a wasm unreachable error of the form:\n       *\n       *     4003: Client error: Execution failed: Execution aborted due to trap: wasm trap: wasm `unreachable` instruction executed\n       *\n       * By setting expectErrors to true, this method won't pollute the logs with errors we intend to have happen.\n       * An example use case of this is when you plan to catch the wasm unreachable error on chains that don't support the query, and then fall back\n       * to another query or perhaps an empty result.\n       */\n      expectErrors?: boolean\n    }\n  ): Promise<T> {\n    const talismanSub = this.getTalismanSub()\n    if (talismanSub !== undefined) {\n      try {\n        const genesisHash = await this.getGenesisHash(chainId)\n        return await talismanSub.send(genesisHash, method, params)\n      } catch (error) {\n        log.warn(\n          `Failed to make wallet-proxied send request for chain ${chainId}. Falling back to plain websocket`,\n          error\n        )\n      }\n    }\n\n    let socketUserId: SocketUserId\n    let connection: Connection\n    try {\n      ;[socketUserId, connection] = await this.acquireConnection(chainId)\n    } catch (error) {\n      throw new StaleRpcError(chainId, { cause: error })\n    }\n\n    try {\n      return await this.request<T>(connection, method, params)\n    } catch (err) {\n      const error = err as (Error & { code?: number; data?: unknown }) | null\n\n      if (error?.message === \"TIMEOUT\") {\n        log.error(`ChainConnector timeout`, { chainId, error })\n        connection.provider.switch()\n        throw new Error(\"Timeout\")\n      }\n\n      const badRpcError = BAD_RPC_ERRORS[error?.code?.toString() ?? \"\"]\n      if (badRpcError) {\n        log.error(`ChainConnector ${badRpcError}`, { error, chainId })\n        connection.provider.switch()\n        throw new Error(badRpcError)\n      }\n\n      if (!extraOptions?.expectErrors)\n        log.error(\n          `Failed to send ${method} on chain ${chainId}\\nparams: ${JSON.stringify(params)}`,\n          {\n            error,\n          }\n        )\n\n      throw error\n    } finally {\n      this.releaseConnection(chainId, socketUserId)\n    }\n  }\n\n  async subscribe(\n    chainId: DotNetworkId,\n    subscribeMethod: string,\n    responseMethod: string,\n    params: unknown[],\n    callback: SubscriptionCallback,\n    timeout: number | false = 30_000 // 30 seconds in milliseconds\n  ): Promise<(unsubscribeMethod: string) => void> {\n    const talismanSub = this.getTalismanSub()\n    if (talismanSub !== undefined) {\n      try {\n        const genesisHash = await this.getGenesisHash(chainId)\n\n        const subscriptionId = await talismanSub.subscribe(\n          genesisHash,\n          subscribeMethod,\n          responseMethod,\n          params,\n          callback,\n          timeout\n        )\n\n        return (unsubscribeMethod: string) =>\n          talismanSub.unsubscribe(subscriptionId, unsubscribeMethod)\n      } catch (error) {\n        log.warn(\n          `Failed to create wallet-proxied subscription for chain ${chainId}. Falling back to plain websocket`,\n          error\n        )\n      }\n    }\n\n    let socketUserId: SocketUserId\n    let connection: Connection\n    try {\n      ;[socketUserId, connection] = await this.acquireConnection(chainId)\n    } catch (error) {\n      throw new StaleRpcError(chainId, { cause: error })\n    }\n\n    const subscription: Subscription = {\n      subscribeMethod,\n      params,\n      callback,\n      cancelRequest: null,\n      stopFollow: null,\n      serverSubId: null,\n      unsubscribed: false,\n    }\n    connection.subscriptions.add(subscription)\n\n    // if the chain can't be reached at all, let the caller know after a while (the provider keeps retrying)\n    if (timeout && !connection.wasConnected) {\n      const staleWarning = setTimeout(() => {\n        if (!subscription.unsubscribed && !connection.wasConnected)\n          callback(new StaleRpcError(chainId), null)\n      }, timeout)\n      const clear = () => clearTimeout(staleWarning)\n      // piggyback on the follow setup to clear the warning once anything happens\n      const originalCallback = subscription.callback\n      subscription.callback = (error, result) => {\n        clear()\n        subscription.callback = originalCallback\n        originalCallback(error, result)\n      }\n    }\n\n    this.startSubscription(connection, subscription)\n\n    return (unsubscribeMethod: string) => {\n      if (subscription.unsubscribed) return\n      subscription.unsubscribed = true\n\n      subscription.cancelRequest?.()\n      subscription.stopFollow?.()\n\n      // the connection may have been replaced by a reset() since we subscribed\n      const current = this.#connections[chainId]\n      // if we are the last user the connection is about to be destroyed: skip the\n      // unsubscribe call, server-side subscriptions die with the socket anyway\n      const isLastUser = !!current && current.users.size === 1 && current.users.has(socketUserId)\n      if (subscription.serverSubId !== null && current && !isLastUser)\n        try {\n          current.client.request(unsubscribeMethod, [subscription.serverSubId]).catch((error) => {\n            if (!isDestroyedError(error)) log.warn(`Failed to unsubscribe from ${chainId}`, error)\n          })\n        } catch (error) {\n          if (!isDestroyedError(error)) log.warn(`Failed to unsubscribe from ${chainId}`, error)\n        }\n\n      current?.subscriptions.delete(subscription)\n      this.releaseConnection(chainId, socketUserId)\n    }\n  }\n\n  /**\n   * Kills and recreates the connection for a chain, if any.\n   * Useful after changing a network's rpcs to make sure the new list is applied for further requests.\n   * Active subscriptions are automatically re-established on the new connection.\n   */\n  async reset(chainId: DotNetworkId) {\n    log.info(\"ChainConnector reset\", chainId)\n    const connection = this.#connections[chainId]\n    if (!connection) return\n\n    this.destroyConnection(connection)\n    delete this.#connections[chainId]\n\n    // recreate a connection for the active subscriptions, if any\n    if (connection.subscriptions.size) {\n      try {\n        const fresh = await this.createConnection(chainId)\n        fresh.users = connection.users\n        fresh.subscriptions = connection.subscriptions\n        this.#connections[chainId] = fresh\n        for (const subscription of fresh.subscriptions) this.startSubscription(fresh, subscription)\n      } catch (error) {\n        log.warn(`Failed to recreate connection for ${chainId} after reset`, error)\n        for (const subscription of connection.subscriptions)\n          subscription.callback(new StaleRpcError(chainId, { cause: error }), null)\n      }\n    }\n  }\n\n  /** Sends a request over a connection, throwing `Error(\"TIMEOUT\")` if no response arrives in time */\n  private request<T>(\n    connection: Connection,\n    method: string,\n    params: unknown[],\n    timeoutMs = RESPONSE_TIMEOUT\n  ): Promise<T> {\n    return new Promise<T>((resolve, reject) => {\n      const timer = setTimeout(() => {\n        cancel()\n        reject(new Error(\"TIMEOUT\"))\n      }, timeoutMs)\n\n      const cancel = connection.client._request<T, unknown>(method, params, {\n        onSuccess: (result) => {\n          clearTimeout(timer)\n          resolve(result)\n        },\n        onError: (error) => {\n          clearTimeout(timer)\n          reject(error)\n        },\n      })\n    })\n  }\n\n  /** Issues the subscribe request and routes notifications to the subscription callback */\n  private startSubscription(connection: Connection, subscription: Subscription) {\n    subscription.serverSubId = null\n    subscription.stopFollow = null\n\n    subscription.cancelRequest = connection.client._request<string | number, unknown>(\n      subscription.subscribeMethod,\n      subscription.params,\n      {\n        onSuccess: (serverSubId, follow) => {\n          subscription.cancelRequest = null\n          if (subscription.unsubscribed) return\n\n          subscription.serverSubId = serverSubId\n          // raw-client matches notifications by the raw (not stringified) subscription id, but types it as string\n          subscription.stopFollow = follow(serverSubId as string, {\n            next: (result) => subscription.callback(null, result),\n            error: (error) => subscription.callback(error, null),\n          })\n        },\n        onError: (error) => {\n          subscription.cancelRequest = null\n          if (!subscription.unsubscribed) subscription.callback(error, null)\n        },\n      }\n    )\n  }\n\n  /**\n   * Get (or create) the shared connection for a chain.\n   *\n   * The caller must call releaseConnection with the returned SocketUserId once they are finished with it.\n   */\n  private async acquireConnection(chainId: DotNetworkId): Promise<[SocketUserId, Connection]> {\n    // a single creation promise per chain guarantees that concurrent callers share the same connection\n    let connection = this.#connections[chainId]\n    if (!connection) {\n      if (!this.#pendingConnections[chainId]) {\n        this.#pendingConnections[chainId] = this.createConnection(chainId)\n          .then((created) => {\n            this.#connections[chainId] = created\n            return created\n          })\n          .finally(() => {\n            delete this.#pendingConnections[chainId]\n          })\n      }\n      connection = await this.#pendingConnections[chainId]\n    }\n\n    const socketUserId = this.getExclusiveRandomId([...connection.users])\n    connection.users.add(socketUserId)\n\n    return [socketUserId, connection]\n  }\n\n  private async createConnection(chainId: DotNetworkId): Promise<Connection> {\n    const chain = await this.#chaindataChainProvider.getNetworkById(chainId, \"polkadot\")\n    if (!chain) throw new Error(`Chain ${chainId} not found in store`)\n\n    const rpcs = chain.rpcs.concat()\n    if (!rpcs.length) throw new Error(`No healthy RPCs available for chain ${chainId}`)\n\n    // will be assigned below - the provider config needs to reference the connection\n    let connection: Connection = null as unknown as Connection\n\n    const provider = getWsProvider(rpcs, {\n      onStatusChanged: (status: StatusChange) => this.handleStatusChange(connection, status),\n    })\n\n    const client = createClient(provider)\n\n    connection = {\n      chainId,\n      provider,\n      client,\n      users: new Set(),\n      subscriptions: new Set(),\n      wasConnected: false,\n      keepAliveInterval: null,\n      staleTimeout: null,\n    }\n\n    return connection\n  }\n\n  private handleStatusChange(connection: Connection, status: StatusChange) {\n    // connection is still being constructed on the initial CONNECTING event\n    if (!connection) return\n    // ignore events from a connection that has been reset/destroyed\n    if (this.#connections[connection.chainId] !== connection) return\n\n    if (status.type === WsEvent.CONNECTED) {\n      if (connection.staleTimeout) {\n        clearTimeout(connection.staleTimeout)\n        connection.staleTimeout = null\n      }\n\n      const isReconnect = connection.wasConnected\n      connection.wasConnected = true\n\n      // periodically send a request to keep the socket alive when there is no other traffic\n      if (connection.keepAliveInterval) clearInterval(connection.keepAliveInterval)\n      connection.keepAliveInterval = setInterval(() => {\n        this.request(connection, \"system_health\", [], KEEP_ALIVE_INTERVAL).catch((error) => {\n          if (!isDestroyedError(error))\n            log.warn(`Failed keep-alive for socket ${connection.chainId}`, error)\n        })\n      }, KEEP_ALIVE_INTERVAL)\n\n      // server-side subscriptions died with the previous socket : re-establish them\n      // (skip author_* subscriptions : resubmitting an extrinsic is not safe)\n      if (isReconnect)\n        for (const subscription of connection.subscriptions) {\n          if (subscription.unsubscribed) continue\n          if (subscription.subscribeMethod.startsWith(\"author_\")) continue\n          subscription.stopFollow?.()\n          subscription.cancelRequest?.()\n          this.startSubscription(connection, subscription)\n        }\n    } else {\n      if (connection.keepAliveInterval) {\n        clearInterval(connection.keepAliveInterval)\n        connection.keepAliveInterval = null\n      }\n\n      // notify subscribers if the chain stays unreachable for too long\n      if (!connection.staleTimeout && connection.subscriptions.size) {\n        connection.staleTimeout = setTimeout(() => {\n          connection.staleTimeout = null\n          for (const subscription of connection.subscriptions)\n            if (!subscription.unsubscribed)\n              subscription.callback(new StaleRpcError(connection.chainId), null)\n        }, STALE_NOTIFY_TIMEOUT)\n      }\n    }\n  }\n\n  private releaseConnection(chainId: DotNetworkId, socketUserId: SocketUserId): void {\n    const connection = this.#connections[chainId]\n    if (!connection) return\n\n    connection.users.delete(socketUserId)\n    if (connection.users.size > 0) return\n\n    this.destroyConnection(connection)\n    delete this.#connections[chainId]\n  }\n\n  private destroyConnection(connection: Connection): void {\n    if (connection.keepAliveInterval) clearInterval(connection.keepAliveInterval)\n    if (connection.staleTimeout) clearTimeout(connection.staleTimeout)\n    connection.keepAliveInterval = null\n    connection.staleTimeout = null\n\n    // detach subscriptions before destroying the client so their callbacks don't receive a DestroyedError\n    for (const subscription of connection.subscriptions) {\n      subscription.stopFollow?.()\n      subscription.cancelRequest?.()\n      subscription.stopFollow = null\n      subscription.cancelRequest = null\n      subscription.serverSubId = null\n    }\n\n    try {\n      connection.client.destroy()\n    } catch (error) {\n      log.warn(`Error occurred destroying connection ${connection.chainId}`, error)\n    }\n  }\n\n  private async getGenesisHash(chainId: DotNetworkId): Promise<string> {\n    const chain = await this.#chaindataChainProvider.getNetworkById(chainId, \"polkadot\")\n    if (!chain) throw new Error(`Chain ${chainId} not found in store`)\n\n    const { genesisHash } = chain\n    if (typeof genesisHash !== \"string\")\n      throw new Error(`Chain ${chainId} has no genesisHash in store`)\n\n    return genesisHash\n  }\n\n  /** continues to generate a random number until it finds one which is not present in the exclude list */\n  private getExclusiveRandomId(exclude: number[] = []): number {\n    let id = this.getRandomId()\n    while (exclude.includes(id)) {\n      id = this.getRandomId()\n    }\n    return id\n  }\n  /** generates a random number */\n  private getRandomId(): number {\n    return Math.trunc(Math.random() * 10 ** 8)\n  }\n\n  private getTalismanSub() {\n    // biome-ignore lint/suspicious/noExplicitAny: legacy\n    const talismanSub = typeof window !== \"undefined\" && (window as any).talismanSub\n\n    // biome-ignore lint/complexity/noBannedTypes: legacy\n    const rpcByGenesisHashSend: Function | undefined = talismanSub?.rpcByGenesisHashSend\n    // biome-ignore lint/complexity/noBannedTypes: legacy\n    const rpcByGenesisHashSubscribe: Function | undefined = talismanSub?.rpcByGenesisHashSubscribe\n    // biome-ignore lint/complexity/noBannedTypes: legacy\n    const rpcByGenesisHashUnsubscribe: Function | undefined =\n      talismanSub?.rpcByGenesisHashUnsubscribe\n\n    if (typeof rpcByGenesisHashSend !== \"function\") return\n    if (typeof rpcByGenesisHashSubscribe !== \"function\") return\n    if (typeof rpcByGenesisHashUnsubscribe !== \"function\") return\n\n    return {\n      // biome-ignore lint/suspicious/noExplicitAny: legacy\n      send: <T = any>(genesisHash: string, method: string, params: unknown[]): Promise<T> =>\n        rpcByGenesisHashSend(genesisHash, method, params),\n\n      subscribe: (\n        genesisHash: string,\n        subscribeMethod: string,\n        responseMethod: string,\n        params: unknown[],\n        callback: SubscriptionCallback,\n        timeout: number | false\n      ): Promise<string> =>\n        rpcByGenesisHashSubscribe(\n          genesisHash,\n          subscribeMethod,\n          responseMethod,\n          params,\n          callback,\n          timeout\n        ),\n\n      unsubscribe: (subscriptionId: string, unsubscribeMethod: string): Promise<void> =>\n        rpcByGenesisHashUnsubscribe(subscriptionId, unsubscribeMethod),\n    }\n  }\n}\n","import { createClient, type SubstrateClient } from \"@polkadot-api/substrate-client\"\nimport { getWsProvider } from \"@polkadot-api/ws-provider\"\nimport type { DotNetwork, DotNetworkId } from \"@talismn/chaindata-provider\"\nimport { throwAfter } from \"@talismn/util\"\n\nimport type { IChainConnectorDot, SubscriptionCallback } from \"./IChainConnectorDot\"\n\nconst TIMEOUT = 10_000\n\nexport class ChainConnectorDotStub implements IChainConnectorDot {\n  #client: SubstrateClient\n\n  constructor(network: DotNetwork) {\n    this.#client = createClient(getWsProvider(network.rpcs.concat()))\n  }\n\n  async send<T = unknown>(\n    _chainId: DotNetworkId,\n    method: string,\n    params: unknown[],\n    _isCacheable?: boolean\n  ): Promise<T> {\n    return await Promise.race([\n      this.#client.request<T>(method, params),\n      throwAfter(TIMEOUT, `Request ${method} timed out after ${TIMEOUT}ms`),\n    ])\n  }\n\n  async subscribe(\n    _chainId: DotNetworkId,\n    subscribeMethod: string,\n    _responseMethod: string,\n    params: unknown[],\n    callback: SubscriptionCallback,\n    timeout?: number | false\n  ): Promise<(unsubscribeMethod: string) => void> {\n    let stopFollow: (() => void) | null = null\n    let unsubscribed = false\n\n    const serverSubId = await Promise.race([\n      new Promise<string | number>((resolve, reject) => {\n        this.#client._request<string | number, unknown>(subscribeMethod, params, {\n          onSuccess: (subId, follow) => {\n            stopFollow = follow(subId as string, {\n              next: (result) => callback(null, result),\n              error: (error) => callback(error, null),\n            })\n            resolve(subId)\n          },\n          onError: reject,\n        })\n      }),\n      throwAfter(timeout || TIMEOUT, `Subscription timed out after ${timeout || TIMEOUT}ms`),\n    ])\n\n    return (unsubscribeMethod: string) => {\n      if (unsubscribed) return\n      unsubscribed = true\n      stopFollow?.()\n      this.#client.request(unsubscribeMethod, [serverSubId]).catch(() => {}) // connection may already be gone\n    }\n  }\n\n  reset(): Promise<void> {\n    throw new Error(\"ChainConnectorDotStub does not implement reset\")\n  }\n\n  destroy() {\n    this.#client.destroy()\n  }\n}\n","import type { EthNetwork, EthNetworkId } from \"@talismn/chaindata-provider\"\nimport { camelCase, fromPairs, toPairs } from \"lodash-es\"\nimport type { Chain, ChainContract } from \"viem\"\nimport * as viemChains from \"viem/chains\"\n\n// exclude zoraTestnet which uses Hyperliquid's chain id\nconst { zoraTestnet, ...validViemChains } = viemChains\n\n// viem chains benefit from multicall config & other viem goodies\nconst VIEM_CHAINS = Object.keys(validViemChains).reduce(\n  (acc, curr) => {\n    const chain = validViemChains[curr as keyof typeof validViemChains]\n    acc[chain.id] = chain\n    return acc\n  },\n  {} as Record<number, Chain>\n)\n\nconst chainsCache = new Map<string, Chain>()\n\nexport const clearChainsCache = (networkId?: EthNetworkId) => {\n  if (networkId) chainsCache.delete(networkId)\n  else chainsCache.clear()\n}\n\nexport const getChainFromEvmNetwork = (network: EthNetwork): Chain => {\n  const { symbol, decimals } = network.nativeCurrency\n\n  if (!chainsCache.has(network.id)) {\n    const chainRpcs = network.rpcs ?? []\n\n    const viemChain = VIEM_CHAINS[Number(network.id)] ?? {}\n\n    const chain: Chain = {\n      ...viemChain,\n      id: Number(network.id),\n      name: network.name ?? `Ethereum Chain ${network.id}`,\n      rpcUrls: {\n        public: { http: chainRpcs },\n        default: { http: chainRpcs },\n      },\n      nativeCurrency: {\n        symbol,\n        decimals,\n        name: symbol,\n      },\n      contracts: {\n        ...viemChain.contracts,\n        ...(network.contracts\n          ? fromPairs(\n              toPairs(network.contracts).map(([name, address]): [string, ChainContract] => [\n                camelCase(name),\n                { address },\n              ])\n            )\n          : {}),\n      },\n    }\n\n    chainsCache.set(network.id, chain)\n  }\n\n  return chainsCache.get(network.id) as Chain\n}\n","import type { EthNetwork } from \"@talismn/chaindata-provider\"\nimport { fallback, http, shouldThrow } from \"viem\"\n\nexport type TransportOptions = {\n  batch?:\n    | boolean\n    | {\n        batchSize?: number | undefined\n        wait?: number | undefined\n      }\n}\n\n// Frontier nodes report reverts with a message viem does not recognize, which makes fallback retry every rpc\nconst FRONTIER_EXECUTION_ERROR = /VM Exception while processing transaction/\n\nconst isFinalError = (error: Error) =>\n  shouldThrow(error) || FRONTIER_EXECUTION_ERROR.test(error.message)\n\nexport const getTransportForEvmNetwork = (\n  evmNetwork: EthNetwork,\n  options: TransportOptions = {}\n) => {\n  if (!evmNetwork.rpcs?.length) throw new Error(\"No RPCs found for EVM network\")\n\n  const { batch } = options\n\n  return fallback(\n    evmNetwork.rpcs.map((url) => http(url, { batch, retryCount: 0 })),\n    { retryCount: 0, shouldThrow: isFinalError }\n  )\n}\n","import type { EthNetwork } from \"@talismn/chaindata-provider\"\nimport { createPublicClient, type PublicClient } from \"viem\"\n\nimport { clearChainsCache, getChainFromEvmNetwork } from \"./getChainFromEvmNetwork\"\nimport { getTransportForEvmNetwork, type TransportOptions } from \"./getTransportForEvmNetwork\"\n\nconst MUTLICALL_BATCH_WAIT = 25\nconst MUTLICALL_BATCH_SIZE = 100\n\nconst HTTP_BATCH_WAIT = 25\nconst HTTP_BATCH_SIZE_WITH_MULTICALL = 10\nconst HTTP_BATCH_SIZE_WITHOUT_MULTICALL = 30\n\n// cache to reuse previously created public clients\nconst publicClientCache = new Map<string, PublicClient>()\n\nexport const clearPublicClientCache = (evmNetworkId?: string) => {\n  clearChainsCache(evmNetworkId)\n\n  if (evmNetworkId) publicClientCache.delete(evmNetworkId)\n  else publicClientCache.clear()\n}\n\nexport const getEvmNetworkPublicClient = (network: EthNetwork): PublicClient => {\n  const chain = getChainFromEvmNetwork(network)\n\n  if (!publicClientCache.has(network.id)) {\n    if (!network.rpcs.length) throw new Error(\"No RPCs found for Ethereum network\")\n\n    const batch = chain.contracts?.multicall3\n      ? { multicall: { wait: MUTLICALL_BATCH_WAIT, batchSize: MUTLICALL_BATCH_SIZE } }\n      : undefined\n\n    const transportOptions: TransportOptions = {\n      batch: {\n        batchSize: chain.contracts?.multicall3\n          ? HTTP_BATCH_SIZE_WITH_MULTICALL\n          : HTTP_BATCH_SIZE_WITHOUT_MULTICALL,\n        wait: HTTP_BATCH_WAIT,\n      },\n    }\n\n    const transport = getTransportForEvmNetwork(network, transportOptions)\n\n    publicClientCache.set(\n      network.id,\n      createPublicClient({\n        chain,\n        transport,\n        batch,\n      })\n    )\n  }\n\n  return publicClientCache.get(network.id) as PublicClient\n}\n","import type { EthNetwork } from \"@talismn/chaindata-provider\"\nimport { type Account, createWalletClient, type WalletClient } from \"viem\"\n\nimport { getChainFromEvmNetwork } from \"./getChainFromEvmNetwork\"\nimport { getTransportForEvmNetwork } from \"./getTransportForEvmNetwork\"\n\ntype WalletClientOptions = {\n  account?: `0x${string}` | Account\n}\n\nexport const getEvmNetworkWalletClient = (\n  network: EthNetwork,\n  options: WalletClientOptions = {}\n): WalletClient => {\n  const chain = getChainFromEvmNetwork(network)\n\n  const transport = getTransportForEvmNetwork(network)\n\n  return createWalletClient({ chain, transport, account: options.account })\n}\n","import type {\n  EthNetworkId,\n  IChaindataNetworkProvider,\n  IChaindataTokenProvider,\n} from \"@talismn/chaindata-provider\"\nimport type { Account, PublicClient, WalletClient } from \"viem\"\n\nimport { clearPublicClientCache, getEvmNetworkPublicClient } from \"./getEvmNetworkPublicClient\"\nimport { getEvmNetworkWalletClient } from \"./getEvmNetworkWalletClient\"\nimport type { IChainConnectorEth } from \"./IChainConnectorEth\"\n\nexport class ChainConnectorEth implements IChainConnectorEth {\n  #chaindataProvider: IChaindataNetworkProvider & IChaindataTokenProvider\n\n  constructor(chaindataProvider: IChaindataNetworkProvider & IChaindataTokenProvider) {\n    this.#chaindataProvider = chaindataProvider\n  }\n\n  async getPublicClientForEvmNetwork(evmNetworkId: EthNetworkId): Promise<PublicClient | null> {\n    const network = await this.#chaindataProvider.getNetworkById(evmNetworkId, \"ethereum\")\n    if (!network) return null\n\n    return getEvmNetworkPublicClient(network)\n  }\n\n  async getWalletClientForEvmNetwork(\n    evmNetworkId: EthNetworkId,\n    account?: `0x${string}` | Account\n  ): Promise<WalletClient | null> {\n    const network = await this.#chaindataProvider.getNetworkById(evmNetworkId, \"ethereum\")\n    if (!network) return null\n\n    return getEvmNetworkWalletClient(network, { account })\n  }\n\n  public clearRpcProvidersCache(evmNetworkId?: EthNetworkId) {\n    clearPublicClientCache(evmNetworkId)\n  }\n}\n","import type { EthNetwork, EthNetworkId } from \"@talismn/chaindata-provider\"\nimport type { Account, PublicClient, WalletClient } from \"viem\"\n\nimport { getEvmNetworkPublicClient } from \"./getEvmNetworkPublicClient\"\nimport { getEvmNetworkWalletClient } from \"./getEvmNetworkWalletClient\"\nimport type { IChainConnectorEth } from \"./IChainConnectorEth\"\n\nexport class ChainConnectorEthStub implements IChainConnectorEth {\n  #network: EthNetwork\n\n  constructor(network: EthNetwork) {\n    this.#network = network\n  }\n\n  async getPublicClientForEvmNetwork(): Promise<PublicClient | null> {\n    return getEvmNetworkPublicClient(this.#network)\n  }\n\n  async getWalletClientForEvmNetwork(\n    _networkId: EthNetworkId,\n    account?: `0x${string}` | Account\n  ): Promise<WalletClient | null> {\n    return getEvmNetworkWalletClient(this.#network, { account })\n  }\n\n  clearRpcProvidersCache(): void {\n    // No-op for stub\n  }\n}\n","import type { Rpc, RpcTransport, SolanaRpcApi } from \"@solana/kit\"\nimport { createDefaultRpcTransport, createSolanaRpcFromTransport, isSolanaError } from \"@solana/kit\"\nimport type { SolNetworkId } from \"@talismn/chaindata-provider\"\n\nexport type SolRpc = Rpc<SolanaRpcApi>\n\n// Public Solana RPC nodes rate-limit aggressively with HTTP 429. kit's default transport is\n// single-shot, unlike the old web3.js `Connection` which retried 429 up to 5x with backoff, so a\n// single 429 would fail an otherwise-valid request (e.g. a user's transaction submission, or token\n// discovery silently returning no tokens). This wrapper restores that behaviour.\nconst MAX_429_RETRIES = 5\nconst BASE_BACKOFF_MS = 500\n\n/** Returns the delay to wait before retrying, or `null` if the error is not a retryable 429. */\nconst get429RetryDelay = (error: unknown, attempt: number): number | null => {\n  if (!isSolanaError(error)) return null\n\n  const context = error.context as { statusCode?: number; headers?: Headers }\n  if (context.statusCode !== 429) return null\n\n  // honour the server's Retry-After header (delta-seconds) when present\n  const retryAfter = Number(context.headers?.get(\"retry-after\"))\n  if (Number.isFinite(retryAfter) && retryAfter > 0) return retryAfter * 1000\n\n  // otherwise exponential backoff: 500ms, 1s, 2s, 4s, 8s\n  return BASE_BACKOFF_MS * 2 ** attempt\n}\n\nconst sleep = (ms: number, signal?: AbortSignal): Promise<void> =>\n  new Promise((resolve, reject) => {\n    if (signal?.aborted) return reject(signal.reason)\n\n    const onAbort = () => {\n      clearTimeout(timeout)\n      reject(signal?.reason)\n    }\n    const timeout = setTimeout(() => {\n      signal?.removeEventListener(\"abort\", onAbort)\n      resolve()\n    }, ms)\n    signal?.addEventListener(\"abort\", onAbort, { once: true })\n  })\n\n/**\n * Wraps a transport so HTTP 429 responses are retried with backoff. Solana RPC requests are\n * idempotent (`sendTransaction` is keyed by signature), so replaying a rate-limited request is safe.\n */\nconst withRetryOn429 = (transport: RpcTransport): RpcTransport => {\n  const wrapped = async (config: Parameters<RpcTransport>[0]) => {\n    for (let attempt = 0; ; attempt++) {\n      try {\n        return await transport(config)\n      } catch (error) {\n        const delay = attempt < MAX_429_RETRIES ? get429RetryDelay(error, attempt) : null\n        if (delay === null) throw error\n        await sleep(delay, config.signal)\n      }\n    }\n  }\n  return wrapped as RpcTransport\n}\n\n// TODO leverage multiple rpcs with fallback\nexport const getSolTransport = (_networkId: SolNetworkId, rpcs: string[]): RpcTransport =>\n  withRetryOn429(createDefaultRpcTransport({ url: rpcs[0] }))\n\nexport const getSolRpc = (networkId: SolNetworkId, rpcs: string[]): SolRpc =>\n  createSolanaRpcFromTransport(getSolTransport(networkId, rpcs))\n","import type { RpcTransport } from \"@solana/kit\"\nimport { createSolanaRpcFromTransport } from \"@solana/kit\"\nimport type {\n  IChaindataNetworkProvider,\n  IChaindataTokenProvider,\n  SolNetworkId,\n} from \"@talismn/chaindata-provider\"\n\nimport type { SolRpc } from \"./getSolRpc\"\nimport { getSolTransport } from \"./getSolRpc\"\nimport type { IChainConnectorSol } from \"./IChainConnectorSol\"\n\nexport class ChainConnectorSol implements IChainConnectorSol {\n  #chaindataProvider: IChaindataNetworkProvider & IChaindataTokenProvider\n  #transports = new Map<SolNetworkId, RpcTransport>()\n  #rpcs = new Map<SolNetworkId, SolRpc>()\n\n  constructor(chaindataProvider: IChaindataNetworkProvider & IChaindataTokenProvider) {\n    this.#chaindataProvider = chaindataProvider\n  }\n\n  async #getNetworkRpcs(networkId: SolNetworkId): Promise<string[]> {\n    const network = await this.#chaindataProvider.getNetworkById(networkId, \"solana\")\n    if (!network) throw new Error(`Network not found: ${networkId}`)\n\n    return network.rpcs\n  }\n\n  async getTransport(networkId: SolNetworkId): Promise<RpcTransport> {\n    if (!this.#transports.has(networkId))\n      this.#transports.set(\n        networkId,\n        getSolTransport(networkId, await this.#getNetworkRpcs(networkId))\n      )\n\n    return this.#transports.get(networkId)!\n  }\n\n  async getRpc(networkId: SolNetworkId): Promise<SolRpc> {\n    if (!this.#rpcs.has(networkId))\n      this.#rpcs.set(networkId, createSolanaRpcFromTransport(await this.getTransport(networkId)))\n\n    return this.#rpcs.get(networkId)!\n  }\n\n  /** Drops cached transports/rpcs so the next call re-reads the network's rpcs from chaindata */\n  clearRpcProvidersCache(networkId?: SolNetworkId) {\n    if (networkId) {\n      this.#transports.delete(networkId)\n      this.#rpcs.delete(networkId)\n    } else {\n      this.#transports.clear()\n      this.#rpcs.clear()\n    }\n  }\n}\n","import type { RpcTransport } from \"@solana/kit\"\nimport { createSolanaRpcFromTransport } from \"@solana/kit\"\nimport type { SolNetwork } from \"@talismn/chaindata-provider\"\n\nimport type { SolRpc } from \"./getSolRpc\"\nimport { getSolTransport } from \"./getSolRpc\"\nimport type { IChainConnectorSol } from \"./IChainConnectorSol\"\n\nexport class ChainConnectorSolStub implements IChainConnectorSol {\n  #transport: RpcTransport\n  #rpc: SolRpc\n\n  constructor(network: Pick<SolNetwork, \"id\" | \"rpcs\">) {\n    this.#transport = getSolTransport(network.id, network.rpcs)\n    this.#rpc = createSolanaRpcFromTransport(this.#transport)\n  }\n\n  async getRpc(): Promise<SolRpc> {\n    return this.#rpc\n  }\n\n  async getTransport(): Promise<RpcTransport> {\n    return this.#transport\n  }\n}\n"],"mappings":"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"}