{"version":3,"file":"StreamProvider.mjs","sourceRoot":"","sources":["../src/StreamProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine';\nimport { createStreamMiddleware } from '@metamask/json-rpc-middleware-stream';\nimport type SafeEventEmitter from '@metamask/safe-event-emitter';\nimport type { Json, JsonRpcParams } from '@metamask/utils';\nimport { duplex as isDuplex } from 'is-stream';\nimport { pipeline } from 'readable-stream';\nimport type { Duplex } from 'readable-stream';\n\nimport type { BaseProviderOptions } from './BaseProvider';\nimport { BaseProvider } from './BaseProvider';\nimport messages from './messages';\nimport {\n  EMITTED_NOTIFICATIONS,\n  isValidChainId,\n  isValidNetworkVersion,\n} from './utils';\n\nexport type StreamProviderOptions = BaseProviderOptions;\n\nexport type JsonRpcConnection = {\n  events: SafeEventEmitter;\n  middleware: JsonRpcMiddleware<JsonRpcParams, Json>;\n  stream: Duplex;\n};\n\n/**\n * An abstract EIP-1193 provider wired to some duplex stream via a\n * `json-rpc-middleware-stream` JSON-RPC stream middleware. Implementers must\n * call {@link AbstractStreamProvider._initializeStateAsync} after instantiation\n * to initialize the provider's state.\n */\nexport abstract class AbstractStreamProvider extends BaseProvider {\n  protected _jsonRpcConnection: JsonRpcConnection;\n\n  /**\n   * Creates a new AbstractStreamProvider instance.\n   *\n   * @param connectionStream - A Node.js duplex stream.\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 to use.\n   */\n  constructor(\n    connectionStream: Duplex,\n    {\n      logger = console,\n      maxEventListeners = 100,\n      rpcMiddleware = [],\n    }: StreamProviderOptions = {},\n  ) {\n    super({ logger, maxEventListeners, rpcMiddleware });\n\n    if (!isDuplex(connectionStream)) {\n      throw new Error(messages.errors.invalidDuplexStream());\n    }\n\n    // Bind functions to prevent consumers from making unbound calls\n    this._handleStreamDisconnect = this._handleStreamDisconnect.bind(this);\n\n    // Set up RPC connection\n    // Typecast: The type of `Duplex` is incompatible with the type of\n    // `JsonRpcConnection`.\n    this._jsonRpcConnection = createStreamMiddleware({\n      retryOnMessage: 'METAMASK_EXTENSION_CONNECT_CAN_RETRY',\n    }) as unknown as JsonRpcConnection;\n\n    pipeline(\n      connectionStream,\n      this._jsonRpcConnection.stream,\n      connectionStream,\n      this._handleStreamDisconnect.bind(this, 'MetaMask RpcProvider'),\n    );\n\n    // Wire up the JsonRpcEngine to the JSON-RPC connection stream\n    this._rpcEngine.push(this._jsonRpcConnection.middleware);\n\n    // Handle JSON-RPC notifications\n    this._jsonRpcConnection.events.on('notification', (payload) => {\n      const { method, params } = payload;\n      if (method === 'metamask_accountsChanged') {\n        this._handleAccountsChanged(params);\n      } else if (method === 'metamask_chainChanged') {\n        this._handleChainChanged(params);\n      } else if (EMITTED_NOTIFICATIONS.includes(method)) {\n        this.emit('message', {\n          type: method,\n          data: params,\n        });\n      } else if (method === 'METAMASK_STREAM_FAILURE') {\n        connectionStream.destroy(\n          new Error(messages.errors.permanentlyDisconnected()),\n        );\n      }\n    });\n  }\n\n  //====================\n  // Private Methods\n  //====================\n\n  /**\n   * MUST be called by child classes.\n   *\n   * Calls `metamask_getProviderState` and passes the result to\n   * {@link BaseProvider._initializeState}. Logs an error if getting initial state\n   * fails. Throws if called after initialization has completed.\n   */\n  protected async _initializeStateAsync() {\n    let initialState: Parameters<BaseProvider['_initializeState']>[0];\n\n    try {\n      initialState = (await this.request({\n        method: 'metamask_getProviderState',\n      })) as Parameters<BaseProvider['_initializeState']>[0];\n    } catch (error) {\n      this._log.error(\n        'MetaMask: Failed to get initial state. Please report this bug.',\n        error,\n      );\n    }\n    this._initializeState(initialState);\n  }\n\n  /**\n   * Called when connection is lost to critical streams. Emits an 'error' event\n   * from the provider with the error message and stack if present.\n   *\n   * @param streamName - The name of the stream that disconnected.\n   * @param error - The error that caused the disconnection.\n   * @fires BaseProvider#disconnect - If the provider is not already\n   * disconnected.\n   */\n  // eslint-disable-next-line no-restricted-syntax\n  private _handleStreamDisconnect(streamName: string, error: Error | null) {\n    let warningMsg = `MetaMask: Lost connection to \"${streamName}\".`;\n    if (error?.stack) {\n      warningMsg += `\\n${error.stack}`;\n    }\n\n    this._log.warn(warningMsg);\n    if (this.listenerCount('error') > 0) {\n      this.emit('error', warningMsg);\n    }\n\n    this._handleDisconnect(false, error ? error.message : undefined);\n  }\n\n  /**\n   * Upon receipt of a new chainId and networkVersion, emits corresponding\n   * events and sets relevant public state. Child classes that use the\n   * `networkVersion` for other purposes must implement additional handling.\n   *\n   * @fires BaseProvider#chainChanged\n   * @param networkInfo - An object with network info.\n   * @param networkInfo.chainId - The latest chain ID.\n   * @param networkInfo.networkVersion - The latest network ID.\n   * @param networkInfo.isConnected - Whether the network is available.\n   */\n  protected _handleChainChanged({\n    chainId,\n    networkVersion,\n    isConnected,\n  }: {\n    chainId?: string | undefined;\n    networkVersion?: string | undefined;\n    isConnected?: boolean | undefined;\n  } = {}) {\n    if (!isValidChainId(chainId) || !isValidNetworkVersion(networkVersion)) {\n      this._log.error(messages.errors.invalidNetworkParams(), {\n        chainId,\n        networkVersion,\n      });\n      return;\n    }\n\n    super._handleChainChanged({ chainId, isConnected });\n\n    if (!isConnected) {\n      this._handleDisconnect(true);\n    }\n  }\n}\n\n/**\n * An EIP-1193 provider wired to some duplex stream via a\n * `json-rpc-middleware-stream` JSON-RPC stream middleware. Consumers must\n * call {@link StreamProvider.initialize} after instantiation to complete\n * initialization.\n */\nexport class StreamProvider extends AbstractStreamProvider {\n  /**\n   * MUST be called after instantiation to complete initialization.\n   *\n   * Calls `metamask_getProviderState` and passes the result to\n   * {@link BaseProvider._initializeState}. Logs an error if getting initial state\n   * fails. Throws if called after initialization has completed.\n   */\n  async initialize() {\n    return this._initializeStateAsync();\n  }\n}\n"]}