xylabs/sdk-react

View on GitHub
packages/crypto/src/wallets/third-party/EIP6963/classes/EthWalletConnections.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { BrowserProvider } from 'ethers'

import { isEIP6963AnnounceProviderEvent } from '../../../lib'
import { EIP6963Connector } from './EIP6963Connector'
import { DiscoveredWallets } from './types'

export type WalletListener = () => void

export class EthWalletConnections {
  private discoveredWallets: DiscoveredWallets = {}
  private listeners: WalletListener[] = []

  constructor() {
    this.setupListeners()
  }

  addWallet(wallet: EIP6963Connector) {
    const walletName = wallet.providerInfo?.rdns
    if (walletName && !this.discoveredWallets[walletName]) {
      this.discoveredWallets = {
        [walletName]: wallet,
        ...this.discoveredWallets,
      }
      this.emitChange()
    }
  }

  onDestroy() {
    // eslint-disable-next-line unicorn/no-invalid-remove-event-listener
    window.removeEventListener('eip6963:announceProvider', this.newWalletListener.bind(this))
  }

  removeWallet(wallet: EIP6963Connector) {
    const walletName = wallet.providerInfo?.rdns
    if (walletName && this.discoveredWallets[walletName]) {
      delete this.discoveredWallets[walletName]
      this.discoveredWallets = { ...this.discoveredWallets }
      this.emitChange()
    }
  }

  subscribe(listener: WalletListener) {
    this.listeners = [...this.listeners, listener]
    return () => {
      this.listeners = this.listeners.filter((existingListener) => existingListener !== listener)
    }
  }

  wallets() {
    return this.discoveredWallets
  }

  private emitChange() {
    for (const listener of this.listeners) {
      listener()
    }
  }

  private newWalletListener(event: Event) {
    if (isEIP6963AnnounceProviderEvent(event)) {
      const { info, provider } = event.detail
      // capture installed wallets as they come in
      this.addWallet(new EIP6963Connector(new BrowserProvider(provider), provider, info))
    }
  }

  private setupListeners() {
    // listen when providers announce themselves
    window.addEventListener('eip6963:announceProvider', this.newWalletListener.bind(this))

    // dispatch an event to ask all installed providers to identify themselves
    window.dispatchEvent(new Event('eip6963:requestProvider'))
  }
}