📄 src/web3/wallet/walletMeta.ts
D-OPEN SOVEREIGN
1import { Browser, parseUserAgent, Platform } from './browsers';
2import { type WalletType } from '../client/types';
3
4export interface WalletMeta {
5  readonly displayName: string;
6  readonly logoUrl: string;
7  readonly description: string;
8  readonly website: string;
9  getInstallUrl(browser?: Browser): string;
10  isInstalled(): boolean;
11  isInstallable(): boolean;
12}
13
14const METAMASK_LOGO_BASE64 =
15  'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLQogIC0gICAvKgogIC0gICAgKiBDb3B5cmlnaHQgKGMpIDIwMjYgRGF0YVBvbmQgRC1MaWJyYXJ5IFB0eSBMdGQuICgiVGhlIFNhbmN0dWFyeSIpCiAgLSAgICAqIE5vbi1Qcm9maXQgUHVibGljIExpYnJhcnkg4oCUIFRoZSBXb3JsZCBMaWJyYXJ5CiAgLSAgICAqCiAgLSAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBELU9wZW4gQ29kZSBTb3ZlcmVpZ24gTGljZW5jZSB2MS4wCiAgLSAgICAqIGh0dHBzOi8vcmVnaXN0cnkud29ybGQuYmlibGlvdGVjaC5jb20vbGljZW5jZQogIC0gICAgKgogIC0gICAgKiBUZWNobmljYWwgR3VhcmRpYW4gKCJUaGUgU2hpZWxkIik6IFBvbmQgRW50ZXJwcmlzZSBQdHkgTHRkLiAoQUNOIDY5NCA3NDcgOTg3KQogIC0gICAgKiBBbGwgbGlhYmlsaXR5IGNsYWltcyBkaXJlY3RlZCB0byBQb25kIEVudGVycHJpc2UgUHR5IEx0ZC4KICAtICAgICogTW9kaWZpY2F0aW9uIGF1dG9tYXRpY2FsbHkgdm9pZHMgdGhlIGNlcnRpZmllZCBsaWFiaWxpdHkgcHJvdGVjdGlvbi4KICAtICAgICogR292ZXJuaW5nIGxhdzogU291dGggQXVzdHJhbGlhLgogIC0gICAgKi8KICAtCiAgLS0+Cgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgaWQ9IkxheWVyXzEiIHg9IjAiIHk9IjAiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDMxOC42IDMxOC42Ij4KICA8c3R5bGU+CiAgICAuc3QxLC5zdDZ7ZmlsbDojZTQ3NjFiO3N0cm9rZTojZTQ3NjFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uc3Q2e2ZpbGw6I2Y2ODUxYjtzdHJva2U6I2Y2ODUxYn0KICA8L3N0eWxlPgogIDxwYXRoIGZpbGw9IiNlMjc2MWIiIHN0cm9rZT0iI2UyNzYxYiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJtMjc0LjEgMzUuNS05OS41IDczLjlMMTkzIDY1Ljh6Ii8+CiAgPHBhdGggZD0ibTQ0LjQgMzUuNSA5OC43IDc0LjYtMTcuNS00NC4zem0xOTMuOSAxNzEuMy0yNi41IDQwLjYgNTYuNyAxNS42IDE2LjMtNTUuM3ptLTIwNC40LjlMNTAuMSAyNjNsNTYuNy0xNS42LTI2LjUtNDAuNnoiIGNsYXNzPSJzdDEiLz4KICA8cGF0aCBkPSJtMTAzLjYgMTM4LjItMTUuOCAyMy45IDU2LjMgMi41LTItNjAuNXptMTExLjMgMC0zOS0zNC44LTEuMyA2MS4yIDU2LjItMi41ek0xMDYuOCAyNDcuNGwzMy44LTE2LjUtMjkuMi0yMi44em03MS4xLTE2LjUgMzMuOSAxNi41LTQuNy0zOS4zeiIgY2xhc3M9InN0MSIvPgogIDxwYXRoIGZpbGw9IiNkN2MxYjMiIHN0cm9rZT0iI2Q3YzFiMyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJtMjExLjggMjQ3LjQtMzMuOS0xNi41IDIuNyAyMi4xLS4zIDkuM3ptLTEwNSAwIDMxLjUgMTQuOS0uMi05LjMgMi41LTIyLjF6Ii8+CiAgPHBhdGggZmlsbD0iIzIzMzQ0NyIgc3Ryb2tlPSIjMjMzNDQ3IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Im0xMzguOCAxOTMuNS0yOC4yLTguMyAxOS45LTkuMXptNDAuOSAwIDguMy0xNy40IDIwIDkuMXoiLz4KICA8cGF0aCBmaWxsPSIjY2Q2MTE2IiBzdHJva2U9IiNjZDYxMTYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0ibTEwNi44IDI0Ny40IDQuOC00MC42LTMxLjMuOXpNMjA3IDIwNi44bDQuOCA0MC42IDI2LjUtMzkuN3ptMjMuOC00NC43LTU2LjIgMi41IDUuMiAyOC45IDguMy0xNy40IDIwIDkuMXptLTEyMC4yIDIzLjEgMjAtOS4xIDguMiAxNy40IDUuMy0yOC45LTU2LjMtMi41eiIvPgogIDxwYXRoIGZpbGw9IiNlNDc1MWYiIHN0cm9rZT0iI2U0NzUxZiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJtODcuOCAxNjIuMSAyMy42IDQ2LS44LTIyLjl6bTEyMC4zIDIzLjEtMSAyMi45IDIzLjctNDZ6bS02NC0yMC42LTUuMyAyOC45IDYuNiAzNC4xIDEuNS00NC45em0zMC41IDAtMi43IDE4IDEuMiA0NSA2LjctMzQuMXoiLz4KICA8cGF0aCBkPSJtMTc5LjggMTkzLjUtNi43IDM0LjEgNC44IDMuMyAyOS4yLTIyLjggMS0yMi45em0tNjkuMi04LjMuOCAyMi45IDI5LjIgMjIuOCA0LjgtMy4zLTYuNi0zNC4xeiIgY2xhc3M9InN0NiIvPgogIDxwYXRoIGZpbGw9IiNjMGFkOWUiIHN0cm9rZT0iI2MwYWQ5ZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJtMTgwLjMgMjYyLjMuMy05LjMtMi41LTIuMmgtMzcuN2wtMi4zIDIuMi4yIDkuMy0zMS41LTE0LjkgMTEgOSAyMi4zIDE1LjVoMzguM2wyMi40LTE1LjUgMTEtOXoiLz4KICA8cGF0aCBmaWxsPSIjMTYxNjE2IiBzdHJva2U9IiMxNjE2MTYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0ibTE3Ny45IDIzMC45LTQuOC0zLjNoLTI3LjdsLTQuOCAzLjMtMi41LIUyLjEgMi4zLTIuMmgzNy43bDIuNSAyLjJ6Ii8+CiAgPHBhdGggZmlsbD0iIzc2M2QxNiIgc3Ryb2tlPSIjNzYzZDE2IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Im0yNzguMyAxMTQuMiA4LjUtNDAuOC0xMi43LTM3LjktOTYuMiA3MS40IDM3IDMxLjMgNTIuMyAxNS4zIDExLjYtMTMuNS01LTMuNiA4LTcuMy02LjItNC44IDgtNi4xek0zMS44IDczLjRsOC41IDQwLjgtNS40IDQgOCA2LjEtNi4xIDQuOCA4IDcuMy01IDMuNiAxMS41IDEzLjUgNTIuMy0xNS4zID3LTMxLjMtOTYuMi03MS40eiIvPgogIDxwYXRoIGQ9Im0yNjcuMiAxNTMuNS01Mi4zLTE1LjMgMTUuOSAyMy45LTIzLjcgNDYgMzEuMi0uNGg0Ni41em0tMTYzLjYtMTUuMy01Mi4zIDE1LjMtMTcuNCA1NC4yaDQ2LjRsMzEuMS40LTIzLjYtNDZ6bTcxIDI2LjQgMy4zLTU3LjcgMTUuMi00MS4xaC02Ny41bDE1IDQxLjEgMy41IDU3LjcgMS4yIDE4LjIuMSA0NC44aDI3LjdsLjItNDQuOHoiIGNsYXNzPSJzdDYiLz4KPC9zdmc+';
16
17export const walletMeta: Record<WalletType, WalletMeta> = {
18  metamask: {
19    displayName: 'MetaMask',
20    logoUrl: METAMASK_LOGO_BASE64,
21    description: 'The most popular Ethereum wallet extension',
22    website: 'https://metamask.io/',
23    isInstalled(): boolean {
24      return (
25        typeof window !== 'undefined' &&
26        typeof (window as any).ethereum !== 'undefined' &&
27        (window as any).ethereum.isMetaMask
28      );
29    },
30    isInstallable(): boolean {
31      try {
32        this.getInstallUrl();
33        return true;
34      } catch {
35        return false;
36      }
37    },
38    getInstallUrl(customBrowser?: Browser): string {
39      const { browser, platform } = parseUserAgent();
40      const targetBrowser = customBrowser || browser;
41
42      switch (platform) {
43        case Platform.android:
44          return 'https://play.google.com/store/apps/details?id=io.metamask';
45        case Platform.ios:
46          return 'https://apps.apple.com/us/app/metamask-crypto-wallet/id1438144202';
47        case Platform.browsers:
48          switch (targetBrowser) {
49            case Browser.chromium:
50            case Browser.brave:
51              return 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn';
52            case Browser.firefox:
53              return 'https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/';
54            case Browser.opera:
55              return 'https://addons.opera.com/en/extensions/details/metamask/';
56            case Browser.edge:
57              return 'https://microsoftedge.microsoft.com/addons/detail/metamask/ejbalbakoplchlghecdalmeeeajnimhm';
58            default:
59              throw new Error(`Browser ${targetBrowser} is not supported for installation of MetaMask extension.`);
60          }
61        default:
62          throw new Error(`Platform ${platform} is not supported for MetaMask.`);
63      }
64    },
65  },
66  private_key: {
67    displayName: 'Private Key',
68    logoUrl: '',
69    description: 'Direct embedded wallet using a raw private key',
70    website: '',
71    isInstalled(): boolean {
72      return true;
73    },
74    isInstallable(): boolean {
75      return false;
76    },
77    getInstallUrl(): string {
78      return '';
79    },
80  },
81};
82