{"version":3,"file":"BaseProvider.mjs","sourceRoot":"","sources":["../src/BaseProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine';\nimport { JsonRpcEngine } from '@metamask/json-rpc-engine';\nimport { rpcErrors, JsonRpcError } from '@metamask/rpc-errors';\nimport SafeEventEmitter from '@metamask/safe-event-emitter';\nimport type {\n  JsonRpcRequest,\n  JsonRpcId,\n  JsonRpcVersion2,\n  JsonRpcSuccess,\n  JsonRpcParams,\n  Json,\n} from '@metamask/utils';\nimport dequal from 'fast-deep-equal';\n\nimport messages from './messages';\nimport type { ConsoleLike, Maybe } from './utils';\nimport { getRpcPromiseCallback, isValidChainId } from './utils';\n\nexport type UnvalidatedJsonRpcRequest = {\n  id?: JsonRpcId;\n  jsonrpc?: JsonRpcVersion2;\n  method: string;\n  params?: unknown;\n};\n\nexport type BaseProviderOptions = {\n  /**\n   * The logging API to use.\n   */\n  logger?: ConsoleLike;\n\n  /**\n   * The maximum number of event listeners.\n   */\n  maxEventListeners?: number;\n\n  /**\n   * `@metamask/json-rpc-engine` middleware. The middleware will be inserted in the given\n   * order immediately after engine initialization.\n   */\n  rpcMiddleware?: JsonRpcMiddleware<JsonRpcParams, Json>[];\n};\n\nexport type RequestArguments = {\n  /** The RPC method to request. */\n  method: string;\n\n  /** The params of the RPC method, if any. */\n  params?: unknown[] | Record<string, unknown>;\n};\n\nexport type BaseProviderState = {\n  accounts: null | string[];\n  isConnected: boolean;\n  initialized: boolean;\n  isPermanentlyDisconnected: boolean;\n};\n\n/**\n * An abstract class implementing the EIP-1193 interface. Implementers must:\n *\n * 1. At initialization, push a middleware to the internal `_rpcEngine` that\n * hands off requests to the server and receives responses in return.\n * 2. At initialization, retrieve initial state and call\n * {@link BaseProvider._initializeState} **once**.\n * 3. Ensure that the provider's state is synchronized with the wallet.\n * 4. Ensure that notifications are received and emitted as appropriate.\n */\nexport abstract class BaseProvider extends SafeEventEmitter {\n  protected readonly _log: ConsoleLike;\n\n  protected _state: BaseProviderState;\n\n  protected _rpcEngine: JsonRpcEngine;\n\n  protected static _defaultState: BaseProviderState = {\n    accounts: null,\n    isConnected: false,\n    initialized: false,\n    isPermanentlyDisconnected: false,\n  };\n\n  /**\n   * The chain ID of the currently connected Ethereum chain.\n   * See [chainId.network]{@link https://chainid.network} for more information.\n   */\n  #chainId: string | null;\n\n  /**\n   * The user's currently selected Ethereum address.\n   * If null, MetaMask is either locked or the user has not permitted any\n   * addresses to be viewed.\n   */\n  #selectedAddress: string | null;\n\n  /**\n   * Create a new instance of the provider.\n   *\n   * @param options - An options bag.\n   * @param options.logger - The logging API to use. Default: `console`.\n   * @param options.maxEventListeners - The maximum number of event\n   * listeners. Default: 100.\n   * @param options.rpcMiddleware - The RPC middleware stack. Default: [].\n   */\n  constructor({\n    logger = console,\n    maxEventListeners = 100,\n    rpcMiddleware = [],\n  }: BaseProviderOptions = {}) {\n    super();\n\n    this._log = logger;\n\n    this.setMaxListeners(maxEventListeners);\n\n    // Private state\n    this._state = {\n      ...BaseProvider._defaultState,\n    };\n\n    // Public state\n    this.#selectedAddress = null;\n    this.#chainId = null;\n\n    // Bind functions to prevent consumers from making unbound calls\n    this._handleAccountsChanged = this._handleAccountsChanged.bind(this);\n    this._handleConnect = this._handleConnect.bind(this);\n    this._handleChainChanged = this._handleChainChanged.bind(this);\n    this._handleDisconnect = this._handleDisconnect.bind(this);\n    this._rpcRequest = this._rpcRequest.bind(this);\n    this.request = this.request.bind(this);\n\n    // Handle RPC requests via dapp-side RPC engine.\n    //\n    // ATTN: Implementers must push a middleware that hands off requests to\n    // the server.\n    const rpcEngine = new JsonRpcEngine();\n    rpcMiddleware.forEach((middleware) => rpcEngine.push(middleware));\n    this._rpcEngine = rpcEngine;\n  }\n\n  //====================\n  // Public Properties\n  //====================\n\n  get chainId(): string | null {\n    return this.#chainId;\n  }\n\n  get selectedAddress(): string | null {\n    return this.#selectedAddress;\n  }\n\n  //====================\n  // Public Methods\n  //====================\n\n  /**\n   * Returns whether the provider can process RPC requests.\n   *\n   * @returns Whether the provider can process RPC requests.\n   */\n  isConnected(): boolean {\n    return this._state.isConnected;\n  }\n\n  /**\n   * Submits an RPC request for the given method, with the given params.\n   * Resolves with the result of the method call, or rejects on error.\n   *\n   * @param args - The RPC request arguments.\n   * @param args.method - The RPC method name.\n   * @param args.params - The parameters for the RPC method.\n   * @returns A Promise that resolves with the result of the RPC method,\n   * or rejects if an error is encountered.\n   */\n  async request<Type>(args: RequestArguments): Promise<Maybe<Type>> {\n    if (!args || typeof args !== 'object' || Array.isArray(args)) {\n      throw rpcErrors.invalidRequest({\n        message: messages.errors.invalidRequestArgs(),\n        data: args,\n      });\n    }\n\n    const { method, params } = args;\n\n    if (typeof method !== 'string' || method.length === 0) {\n      throw rpcErrors.invalidRequest({\n        message: messages.errors.invalidRequestMethod(),\n        data: args,\n      });\n    }\n\n    if (\n      params !== undefined &&\n      !Array.isArray(params) &&\n      (typeof params !== 'object' || params === null)\n    ) {\n      throw rpcErrors.invalidRequest({\n        message: messages.errors.invalidRequestParams(),\n        data: args,\n      });\n    }\n\n    const payload =\n      params === undefined || params === null\n        ? {\n            method,\n          }\n        : {\n            method,\n            params,\n          };\n\n    return new Promise<Type>((resolve, reject) => {\n      this._rpcRequest(payload, getRpcPromiseCallback(resolve, reject));\n    });\n  }\n\n  //====================\n  // Private Methods\n  //====================\n\n  /**\n   * MUST be called by child classes.\n   *\n   * Sets initial state if provided and marks this provider as initialized.\n   * Throws if called more than once.\n   *\n   * Permits the `networkVersion` field in the parameter object for\n   * compatibility with child classes that use this value.\n   *\n   * @param initialState - The provider's initial state.\n   * @param initialState.accounts - The user's accounts.\n   * @param initialState.chainId - The chain ID.\n   * @param initialState.networkVersion - The network version.\n   * @param initialState.isConnected - Whether the network is available.\n   * @fires BaseProvider#_initialized - If `initialState` is defined.\n   * @fires BaseProvider#connect - If `initialState` is defined.\n   */\n  protected _initializeState(initialState?: {\n    accounts: string[];\n    chainId: string;\n    networkVersion?: string;\n    isConnected?: boolean;\n  }) {\n    if (this._state.initialized) {\n      throw new Error('Provider already initialized.');\n    }\n\n    if (initialState) {\n      const { accounts, chainId, networkVersion, isConnected } = initialState;\n\n      // EIP-1193 connect\n      this._handleConnect({ chainId, isConnected });\n      this._handleChainChanged({ chainId, networkVersion, isConnected });\n      this._handleAccountsChanged(accounts);\n    }\n\n    // Mark provider as initialized regardless of whether initial state was\n    // retrieved.\n    this._state.initialized = true;\n    this.emit('_initialized');\n  }\n\n  /**\n   * Internal RPC method. Forwards requests to background via the RPC engine.\n   * Also remap ids inbound and outbound.\n   *\n   * @param payload - The RPC request object.\n   * @param callback - The consumer's callback.\n   * @returns The result of the RPC request.\n   */\n  protected _rpcRequest(\n    payload: UnvalidatedJsonRpcRequest | UnvalidatedJsonRpcRequest[],\n    callback: (...args: any[]) => void,\n  ) {\n    let callbackWrapper = callback;\n\n    if (!Array.isArray(payload)) {\n      if (!payload.jsonrpc) {\n        payload.jsonrpc = '2.0';\n      }\n\n      if (\n        payload.method === 'eth_accounts' ||\n        payload.method === 'eth_requestAccounts'\n      ) {\n        // handle accounts changing\n        callbackWrapper = (\n          error: Error,\n          response: JsonRpcSuccess<string[]>,\n        ) => {\n          this._handleAccountsChanged(\n            response.result ?? [],\n            payload.method === 'eth_accounts',\n          );\n          callback(error, response);\n        };\n      }\n      return this._rpcEngine.handle(payload as JsonRpcRequest, callbackWrapper);\n    }\n    return this._rpcEngine.handle(payload as JsonRpcRequest[], callbackWrapper);\n  }\n\n  /**\n   * When the provider becomes connected, updates internal state and emits\n   * required events. Idempotent.\n   *\n   * @param networkInfo - The options object.\n   * @param networkInfo.chainId - The ID of the newly connected chain.\n   * @param networkInfo.isConnected - Whether the network is available.\n   * @fires MetaMaskInpageProvider#connect\n   */\n  protected _handleConnect({\n    chainId,\n    isConnected,\n  }: {\n    chainId: string;\n    isConnected?: boolean | undefined;\n  }) {\n    if (!this._state.isConnected && isConnected) {\n      this._state.isConnected = true;\n      this.emit('connect', { chainId });\n      this._log.debug(messages.info.connected(chainId));\n    }\n  }\n\n  /**\n   * When the provider becomes disconnected, updates internal state and emits\n   * required events. Idempotent with respect to the isRecoverable parameter.\n   *\n   * Error codes per the CloseEvent status codes as required by EIP-1193:\n   * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes.\n   *\n   * @param isRecoverable - Whether the disconnection is recoverable.\n   * @param errorMessage - A custom error message.\n   * @fires BaseProvider#disconnect - If the disconnection is not recoverable.\n   */\n  protected _handleDisconnect(isRecoverable: boolean, errorMessage?: string) {\n    if (\n      this._state.isConnected ||\n      (!this._state.isPermanentlyDisconnected && !isRecoverable)\n    ) {\n      this._state.isConnected = false;\n\n      let error;\n      if (isRecoverable) {\n        error = new JsonRpcError(\n          1013, // Try again later\n          errorMessage ?? messages.errors.disconnected(),\n        );\n        this._log.debug(error);\n      } else {\n        error = new JsonRpcError(\n          1011, // Internal error\n          errorMessage ?? messages.errors.permanentlyDisconnected(),\n        );\n        this._log.error(error);\n        this.#chainId = null;\n        this._state.accounts = null;\n        this.#selectedAddress = null;\n        this._state.isPermanentlyDisconnected = true;\n      }\n\n      this.emit('disconnect', error);\n    }\n  }\n\n  /**\n   * Upon receipt of a new `chainId`, emits the corresponding event and sets\n   * and sets relevant public state. Does nothing if the given `chainId` is\n   * equivalent to the existing value.\n   *\n   * Permits the `networkVersion` field in the parameter object for\n   * compatibility with child classes that use this value.\n   *\n   * @fires BaseProvider#chainChanged\n   * @param networkInfo - An object with network info.\n   * @param networkInfo.chainId - The latest chain ID.\n   * @param networkInfo.isConnected - Whether the network is available.\n   */\n  protected _handleChainChanged({\n    chainId,\n    isConnected,\n  }:\n    | {\n        chainId?: string;\n        networkVersion?: string | undefined;\n        isConnected?: boolean | undefined;\n      }\n    | undefined = {}) {\n    if (!isValidChainId(chainId)) {\n      this._log.error(messages.errors.invalidNetworkParams(), { chainId });\n      return;\n    }\n\n    this._handleConnect({ chainId, isConnected });\n\n    if (chainId !== this.#chainId) {\n      this.#chainId = chainId;\n      if (this._state.initialized) {\n        this.emit('chainChanged', this.#chainId);\n      }\n    }\n  }\n\n  /**\n   * Called when accounts may have changed. Diffs the new accounts value with\n   * the current one, updates all state as necessary, and emits the\n   * accountsChanged event.\n   *\n   * @param accounts - The new accounts value.\n   * @param isEthAccounts - Whether the accounts value was returned by\n   * a call to eth_accounts.\n   */\n  protected _handleAccountsChanged(\n    accounts: unknown[],\n    isEthAccounts = false,\n  ): void {\n    let _accounts = accounts;\n\n    if (!Array.isArray(accounts)) {\n      this._log.error(\n        'MetaMask: Received invalid accounts parameter. Please report this bug.',\n        accounts,\n      );\n      _accounts = [];\n    }\n\n    for (const account of accounts) {\n      if (typeof account !== 'string') {\n        this._log.error(\n          'MetaMask: Received non-string account. Please report this bug.',\n          accounts,\n        );\n        _accounts = [];\n        break;\n      }\n    }\n\n    // emit accountsChanged if anything about the accounts array has changed\n    if (!dequal(this._state.accounts, _accounts)) {\n      // we should always have the correct accounts even before eth_accounts\n      // returns\n      if (isEthAccounts && this._state.accounts !== null) {\n        this._log.error(\n          `MetaMask: 'eth_accounts' unexpectedly updated accounts. Please report this bug.`,\n          _accounts,\n        );\n      }\n\n      this._state.accounts = _accounts as string[];\n\n      // handle selectedAddress\n      if (this.#selectedAddress !== _accounts[0]) {\n        this.#selectedAddress = (_accounts[0] as string) || null;\n      }\n\n      // finally, after all state has been updated, emit the event\n      if (this._state.initialized) {\n        const _nextAccounts = [..._accounts];\n        this.emit('accountsChanged', _nextAccounts);\n      }\n    }\n  }\n}\n"]}