kodadot/nft-gallery

View on GitHub
utils/config/wallets.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { BaseDotsamaWallet } from './wallets/BaseDotsamaWallet'
import { isMobileDevice } from '~/utils/extension'

// wallet logo

export interface WalletConfig {
  img: string
  extensionName: SupportWalletExtension
  source: SupportWalletExtension
  name: string
  walletUrl: string
  guideUrl: string
  isBrowserExtension: boolean
  isMobileApp: boolean
}
type IWalletConfigMap = Partial<Record<SupportWalletExtension, WalletConfig>>

export enum SupportWalletExtension {
  PolkadotJs = 'polkadot-js',
  MetaMask = 'metamask',
  Clover = 'clover',
  Ledger = 'ledger',
  Math = 'mathwallet',
  Nova = 'nova',
  SubWallet = 'subwallet-js',
  Talisman = 'talisman',
  Enkrypt = 'enkrypt',
  PolkaGate = 'polkagate',
}

// source as 'polkadot-js' in mobile app
export const WalletExtensionProxyMap = {
  [SupportWalletExtension.Math]: SupportWalletExtension.PolkadotJs, // mathwallet
  [SupportWalletExtension.Nova]: SupportWalletExtension.PolkadotJs, // nova
}

const getWalletExtensionSource = (
  walletExtension: SupportWalletExtension,
): SupportWalletExtension => {
  return WalletExtensionProxyMap[walletExtension] || walletExtension
}

const buildWalletConfig = (
  walletExtension,
  img,
  name,
  walletUrl,
  guideUrl,
  isBrowserExtension = false,
  isMobileApp = false,
): WalletConfig => ({
  img,
  name,
  extensionName: walletExtension,
  source: getWalletExtensionSource(walletExtension),
  walletUrl,
  guideUrl,
  isBrowserExtension,
  isMobileApp,
})

export const WalletConfigMap: IWalletConfigMap = {
  [SupportWalletExtension.PolkadotJs]: buildWalletConfig(
    SupportWalletExtension.PolkadotJs,
    '/partners/logo-polkadot-js.png',
    'Polkadot.js',
    'https://polkadot.js.org/extension/',
    'https://www.youtube.com/watch?v=r-fAy7Ta_vY',
    true,
  ),
  [SupportWalletExtension.Clover]: buildWalletConfig(
    SupportWalletExtension.Clover,
    '/partners/logo-clover.png',
    'CLV Wallet',
    'https://chrome.google.com/webstore/detail/clv-wallet/nhnkbkgjikgcigadomkphalanndcapjk',
    'https://docs.clv.org/use-clv-wallet/clv-extension-wallet',
    true,
  ),
  [SupportWalletExtension.Ledger]: buildWalletConfig(
    SupportWalletExtension.Ledger,
    '/partners/logo-ledger.svg',
    'Ledger',
    'https://www.ledger.com/ledger-live',
    'https://www.ledger.com/ledger-live',
  ),
  [SupportWalletExtension.Math]: buildWalletConfig(
    SupportWalletExtension.Math,
    '/partners/logo-mathwallet.png',
    'Math Wallet',
    'https://mathwallet.org/en-us/',
    'https://blog.mathwallet.org/?p=540',
    false,
    true,
  ),
  [SupportWalletExtension.Nova]: buildWalletConfig(
    SupportWalletExtension.Nova,
    '/partners/logo-nova.png',
    'Nova',
    'https://novawallet.io/',
    'https://novawallet.io/',
    false,
    true,
  ),
  [SupportWalletExtension.SubWallet]: buildWalletConfig(
    SupportWalletExtension.SubWallet,
    '/partners/logo-subwallet.svg',
    'SubWallet',
    'https://chrome.google.com/webstore/detail/subwallet/onhogfjeacnfoofkfgppdlbmlmnplgbn?hl=en&authuser=0',
    'https://connect.subwallet.app/#/welcome',
    true,
    true,
  ),
  [SupportWalletExtension.Talisman]: buildWalletConfig(
    SupportWalletExtension.Talisman,
    '/partners/logo-talisman.svg',
    'Talisman',
    'https://app.talisman.xyz/spiritkeys',
    'https://app.talisman.xyz/',
    true,
  ),
  [SupportWalletExtension.Enkrypt]: buildWalletConfig(
    SupportWalletExtension.Enkrypt,
    '/partners/logo-enkrypt.png',
    'Enkrypt',
    'https://www.enkrypt.com/#downloads',
    'https://www.enkrypt.com/',
    true,
  ),
  [SupportWalletExtension.PolkaGate]: buildWalletConfig(
    SupportWalletExtension.PolkaGate,
    '/partners/logo-polkagate.svg',
    'PolkaGate',
    'https://chromewebstore.google.com/detail/polkagate-the-gateway-to/ginchbkmljhldofnbjabmeophlhdldgp?hl=en',
    'https://polkagate.xyz/',
    true,
  ),
}

const MobileWalletExtensionList = [
  SupportWalletExtension.Nova,
  SupportWalletExtension.SubWallet,
  SupportWalletExtension.Math,
]
const PCWalletExtensionList = [
  SupportWalletExtension.Talisman,
  SupportWalletExtension.SubWallet,
  SupportWalletExtension.PolkadotJs,
  SupportWalletExtension.PolkaGate,
  SupportWalletExtension.Enkrypt,
  SupportWalletExtension.Clover,
]

const createWalletInstance = (
  walletExtension: SupportWalletExtension,
): BaseDotsamaWallet => {
  const config = WalletConfigMap[walletExtension]
  return new BaseDotsamaWallet(config)
}

const createWalletInstanceList = (
  walletList: SupportWalletExtension[],
): BaseDotsamaWallet[] => {
  return walletList.map(walletExtension =>
    createWalletInstance(walletExtension),
  )
}

export const SupportedWallets = () => {
  if (isMobileDevice) {
    return createWalletInstanceList(MobileWalletExtensionList)
  }
  const allWallets = createWalletInstanceList(PCWalletExtensionList)
  const wallets = allWallets.filter(wallet => wallet.installed)
  const sourceIds = new Set(wallets.map(d => d.source))
  const allWalletsUpdates = [
    ...wallets,
    ...allWallets.filter(d => !sourceIds.has(d.source)),
  ]
  return allWalletsUpdates
}

export function getWalletBySource(
  source: string | unknown,
): Wallet | undefined {
  return SupportedWallets().find((wallet) => {
    return wallet.extensionName === source
  })
}

export type SubscriptionFn = (
  accounts: WalletAccount[] | undefined,
) => void | Promise<void>

export interface WalletAccount {
  address: string
  source: string
  name?: string
  wallet?: Wallet
  signer?: unknown
}

interface WalletData {
  extensionName: string
  source: string
  name: string
  walletUrl: string
  guideUrl: string
  img: string
  isBrowserExtension: boolean
  isMobileApp: boolean
}

interface WalletExtension {
  installed: boolean | undefined

  // The raw extension object which will have everything a dapp developer needs.
  // Refer to a specific wallet's extension documentation
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  extension: any

  // The raw signer object for convenience. Usually the implementer can derive this from the extension object.
  // Refer to a specific wallet's extension documentation
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  signer: any
}

interface Signer {
  // Sign function
  sign?: (address: string, payload: string) => unknown
}

interface Connector {
  enable: () => unknown

  // The subscribe to accounts function
  subscribeAccounts: (callback: SubscriptionFn) => unknown
}

export interface Wallet
  extends WalletData,
  WalletExtension,
  Connector,
  Signer {}