{"version":3,"file":"create-auto-managed-network-client.mjs","sourceRoot":"","sources":["../src/create-auto-managed-network-client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NetworkClient } from './create-network-client';\nimport { createNetworkClient } from './create-network-client';\nimport type { NetworkControllerMessenger } from './NetworkController';\nimport type { RpcServiceOptions } from './rpc-service/rpc-service';\nimport type {\n  BlockTracker,\n  NetworkClientConfiguration,\n  Provider,\n} from './types';\n\n/**\n * The name of the method on both the provider and block tracker proxy which can\n * be used to get the underlying provider or block tracker from the network\n * client, when it is initialized.\n */\nconst REFLECTIVE_PROPERTY_NAME = '__target__';\n\n/**\n * Represents a proxy object which wraps a target object. As a proxy, it allows\n * for accessing and setting all of the properties that the target object\n * supports, but also supports an extra propertyName (`__target__`) to access\n * the target itself.\n *\n * @template Type - The type of the target object. It is assumed that this type\n * will be constant even when the target is swapped.\n */\nexport type ProxyWithAccessibleTarget<TargetType> = TargetType & {\n  [REFLECTIVE_PROPERTY_NAME]: TargetType;\n};\n\n/**\n * An object that provides the same interface as a network client but where the\n * network client is not initialized until either the provider or block tracker\n * is first accessed.\n */\nexport type AutoManagedNetworkClient<\n  Configuration extends NetworkClientConfiguration,\n> = {\n  configuration: Configuration;\n  provider: ProxyWithAccessibleTarget<Provider>;\n  blockTracker: ProxyWithAccessibleTarget<BlockTracker>;\n  destroy: () => void;\n};\n\n/**\n * By default, the provider and block provider proxies will point to nothing.\n * This is impossible when using the Proxy API, as the target object has to be\n * something, so this object represents that \"something\".\n */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst UNINITIALIZED_TARGET = { __UNINITIALIZED__: true };\n\n/**\n * This function creates two proxies, one that wraps a provider and another that\n * wraps a block tracker. These proxies are unique in that both will be \"empty\"\n * at first; that is, neither will point to a functional provider or block\n * tracker. Instead, as soon as a method or event is accessed on either object\n * that requires a network request to function, a network client is created on\n * the fly and the method or event in question is then forwarded to whichever\n * part of the network client is serving as the receiver. The network client is\n * then cached for subsequent usages.\n *\n * @param args - The arguments.\n * @param args.networkClientConfiguration - The configuration object that will be\n * used to instantiate the network client when it is needed.\n * @param args.getRpcServiceOptions - Factory for constructing RPC service\n * options. See {@link NetworkControllerOptions.getRpcServiceOptions}.\n * @param args.messenger - The network controller messenger.\n * @returns The auto-managed network client.\n */\nexport function createAutoManagedNetworkClient<\n  Configuration extends NetworkClientConfiguration,\n>({\n  networkClientConfiguration,\n  getRpcServiceOptions,\n  messenger,\n}: {\n  networkClientConfiguration: Configuration;\n  getRpcServiceOptions: (\n    rpcEndpointUrl: string,\n  ) => Omit<RpcServiceOptions, 'failoverService' | 'endpointUrl'>;\n  messenger: NetworkControllerMessenger;\n}): AutoManagedNetworkClient<Configuration> {\n  let networkClient: NetworkClient | undefined;\n\n  const providerProxy = new Proxy(UNINITIALIZED_TARGET, {\n    // TODO: Replace `any` with type\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    get(_target: any, propertyName: PropertyKey, receiver: unknown) {\n      if (propertyName === REFLECTIVE_PROPERTY_NAME) {\n        return networkClient?.provider;\n      }\n\n      networkClient ??= createNetworkClient({\n        configuration: networkClientConfiguration,\n        getRpcServiceOptions,\n        messenger,\n      });\n      if (networkClient === undefined) {\n        throw new Error(\n          \"It looks like `createNetworkClient` didn't return anything. Perhaps it's being mocked?\",\n        );\n      }\n      const { provider } = networkClient;\n\n      if (propertyName in provider) {\n        // Typecast: We know that `[propertyName]` is a propertyName on\n        // `provider`.\n        const value = provider[propertyName as keyof typeof provider];\n        if (typeof value === 'function') {\n          // Ensure that the method on the provider is called with `this` as\n          // the target, *not* the proxy (which happens by default) —\n          // this allows private properties to be accessed\n          // TODO: Replace `any` with type\n          // eslint-disable-next-line @typescript-eslint/no-explicit-any\n          return function (this: unknown, ...args: any[]) {\n            // @ts-expect-error We don't care that `this` may not be compatible\n            // with the signature of the method being called, as technically\n            // it can be anything.\n            return value.apply(this === receiver ? provider : this, args);\n          };\n        }\n        return value;\n      }\n\n      return undefined;\n    },\n\n    // TODO: Replace `any` with type\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    has(_target: any, propertyName: PropertyKey) {\n      if (propertyName === REFLECTIVE_PROPERTY_NAME) {\n        return true;\n      }\n      networkClient ??= createNetworkClient({\n        configuration: networkClientConfiguration,\n        getRpcServiceOptions,\n        messenger,\n      });\n      const { provider } = networkClient;\n      return propertyName in provider;\n    },\n  });\n\n  const blockTrackerProxy: ProxyWithAccessibleTarget<BlockTracker> = new Proxy(\n    UNINITIALIZED_TARGET,\n    {\n      // TODO: Replace `any` with type\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      get(_target: any, propertyName: PropertyKey, receiver: unknown) {\n        if (propertyName === REFLECTIVE_PROPERTY_NAME) {\n          return networkClient?.blockTracker;\n        }\n\n        networkClient ??= createNetworkClient({\n          configuration: networkClientConfiguration,\n          getRpcServiceOptions,\n          messenger,\n        });\n        if (networkClient === undefined) {\n          throw new Error(\n            \"It looks like createNetworkClient returned undefined. Perhaps it's mocked?\",\n          );\n        }\n        const { blockTracker } = networkClient;\n\n        if (propertyName in blockTracker) {\n          // Typecast: We know that `[propertyName]` is a propertyName on\n          // `provider`.\n          const value = blockTracker[propertyName as keyof typeof blockTracker];\n          if (typeof value === 'function') {\n            // Ensure that the method on the provider is called with `this` as\n            // the target, *not* the proxy (which happens by default) —\n            // this allows private properties to be accessed\n            // TODO: Replace `any` with type\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            return function (this: unknown, ...args: any[]) {\n              // @ts-expect-error We don't care that `this` may not be\n              // compatible with the signature of the method being called, as\n              // technically it can be anything.\n              return value.apply(this === receiver ? blockTracker : this, args);\n            };\n          }\n          return value;\n        }\n\n        return undefined;\n      },\n\n      // TODO: Replace `any` with type\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      has(_target: any, propertyName: PropertyKey) {\n        if (propertyName === REFLECTIVE_PROPERTY_NAME) {\n          return true;\n        }\n        networkClient ??= createNetworkClient({\n          configuration: networkClientConfiguration,\n          getRpcServiceOptions,\n          messenger,\n        });\n        const { blockTracker } = networkClient;\n        return propertyName in blockTracker;\n      },\n    },\n  );\n\n  const destroy = () => {\n    networkClient?.destroy();\n  };\n\n  return {\n    configuration: networkClientConfiguration,\n    provider: providerProxy,\n    blockTracker: blockTrackerProxy,\n    destroy,\n  };\n}\n"]}