@web3auth/modal 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ import { AdaptersModalConfig } from "./interface";
2
+ export declare const defaultSolanaDappModalConfig: AdaptersModalConfig;
3
+ export declare const defaultEvmDappModalConfig: AdaptersModalConfig;
4
+ export declare const defaultSolanaWalletModalConfig: AdaptersModalConfig;
5
+ export declare const defaultEvmWalletModalConfig: AdaptersModalConfig;
6
+ export declare const defaultOtherModalConfig: AdaptersModalConfig;
@@ -0,0 +1,6 @@
1
+ import { CustomChainConfig, IAdapter, WALLET_ADAPTER_TYPE } from "@web3auth/base";
2
+ export declare const getDefaultAdapterModule: (params: {
3
+ name: WALLET_ADAPTER_TYPE;
4
+ clientId: string;
5
+ customChainConfig: Partial<CustomChainConfig> & Pick<CustomChainConfig, "chainNamespace">;
6
+ }) => Promise<IAdapter<unknown>>;
@@ -0,0 +1,3 @@
1
+ export * from "./config";
2
+ export * from "./interface";
3
+ export * from "./modalManager";
@@ -0,0 +1,8 @@
1
+ import type { BaseAdapterConfig, ChainNamespaceType, LoginMethodConfig, WALLET_ADAPTER_TYPE } from "@web3auth/base";
2
+ export interface ModalConfig extends BaseAdapterConfig {
3
+ loginMethods?: LoginMethodConfig;
4
+ }
5
+ export interface AdaptersModalConfig {
6
+ chainNamespace: ChainNamespaceType;
7
+ adapters?: Record<WALLET_ADAPTER_TYPE, ModalConfig>;
8
+ }
@@ -0,0 +1,67 @@
1
+ import { SafeEventEmitterProvider, WALLET_ADAPTER_TYPE } from "@web3auth/base";
2
+ import { Web3AuthCore, Web3AuthCoreOptions } from "@web3auth/core";
3
+ import LoginModal from "@web3auth/ui";
4
+ import { ModalConfig } from "./interface";
5
+ export interface UIConfig {
6
+ /**
7
+ * Logo for your app.
8
+ */
9
+ appLogo?: string;
10
+ /**
11
+ * theme for the modal
12
+ *
13
+ * @defaultValue `light`
14
+ */
15
+ theme?: "light" | "dark";
16
+ /**
17
+ * order of how login methods are shown
18
+ *
19
+ * @defaultValue `["google", "facebook", "twitter", "reddit", "discord", "twitch", "apple", "line", "github", "kakao", "linkedin", "weibo", "wechat", "email_passwordless"]`
20
+ */
21
+ loginMethodsOrder?: string[];
22
+ /**
23
+ * language which will be used by web3auth. app will use browser language if not specified. if language is not supported it will use "en"
24
+ * en: english
25
+ * de: german
26
+ * ja: japanese
27
+ * ko: korean
28
+ * zh: mandarin
29
+ * es: spanish
30
+ *
31
+ */
32
+ defaultLanguage?: string;
33
+ }
34
+ export interface Web3AuthOptions extends Web3AuthCoreOptions {
35
+ /**
36
+ * web3auth instance provides different adapters for different type of usages. If you are dapp and want to
37
+ * use external wallets like metamask, then you can use the `DAPP` authMode.
38
+ * If you are a wallet and only want to use you own wallet implementations along with openlogin,
39
+ * then you should use `WALLET` authMode.
40
+ *
41
+ * @defaultValue `DAPP`
42
+ */
43
+ authMode?: "DAPP" | "WALLET";
44
+ /**
45
+ * Config for configuring modal ui display properties
46
+ */
47
+ uiConfig?: UIConfig;
48
+ /**
49
+ * Whether to show errors on Web3Auth modal.
50
+ *
51
+ * @defaultValue `true`
52
+ */
53
+ displayErrorsOnModal?: boolean;
54
+ }
55
+ export declare class Web3Auth extends Web3AuthCore {
56
+ loginModal: LoginModal;
57
+ readonly options: Web3AuthOptions;
58
+ private modalConfig;
59
+ constructor(options: Web3AuthOptions);
60
+ initModal(params?: {
61
+ modalConfig?: Record<WALLET_ADAPTER_TYPE, ModalConfig>;
62
+ }): Promise<void>;
63
+ connect(): Promise<SafeEventEmitterProvider | null>;
64
+ private initExternalWalletAdapters;
65
+ private initializeInAppWallet;
66
+ private subscribeToLoginModalEvents;
67
+ }
@@ -0,0 +1,9 @@
1
+ export declare const languageMap: {
2
+ en: string;
3
+ de: string;
4
+ ja: string;
5
+ ko: string;
6
+ zh: string;
7
+ es: string;
8
+ };
9
+ export declare const getUserLanguage: (defaultLanguage: string | undefined) => string;
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@web3auth/modal",
3
+ "version": "3.0.0",
4
+ "homepage": "https://github.com/Web3Auth/Web3Auth#readme",
5
+ "license": "ISC",
6
+ "main": "dist/modal.cjs.js",
7
+ "module": "dist/modal.esm.js",
8
+ "unpkg": "dist/modal.umd.min.js",
9
+ "jsdelivr": "dist/modal.umd.min.js",
10
+ "types": "dist/types/index.d.ts",
11
+ "author": "Torus Labs",
12
+ "scripts": {
13
+ "test": "mocha --config ../../.mocharc.json test/**.ts",
14
+ "test-debugger": "mocha --config ../../.mocharc.json --inspect-brk test/**.ts",
15
+ "dev": "torus-scripts start",
16
+ "build": "torus-scripts build",
17
+ "lint": "eslint --fix 'src/**/*.ts'",
18
+ "prepack": "yarn run build",
19
+ "pre-commit": "lint-staged --cwd ."
20
+ },
21
+ "dependencies": {
22
+ "@web3auth/base": "^3.0.0",
23
+ "@web3auth/core": "^3.0.0",
24
+ "@web3auth/metamask-adapter": "^3.0.0",
25
+ "@web3auth/openlogin-adapter": "^3.0.0",
26
+ "@web3auth/phantom-adapter": "^3.0.0",
27
+ "@web3auth/torus-evm-adapter": "^3.0.0",
28
+ "@web3auth/torus-solana-adapter": "^3.0.0",
29
+ "@web3auth/ui": "^3.0.0",
30
+ "@web3auth/wallet-connect-v1-adapter": "^3.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@svgr/webpack": "^6.5.0",
34
+ "@toruslabs/openlogin": "^2.7.0",
35
+ "css-loader": "^6.7.1",
36
+ "isomorphic-style-loader": "^5.3.2",
37
+ "style-loader": "^3.3.1",
38
+ "url-loader": "^4.1.1"
39
+ },
40
+ "peerDependencies": {
41
+ "@babel/runtime": "7.x"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "src"
46
+ ],
47
+ "lint-staged": {
48
+ "!(*d).ts": [
49
+ "eslint --cache --fix",
50
+ "prettier --write"
51
+ ]
52
+ },
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "git+https://github.com/Web3Auth/Web3Auth.git"
56
+ },
57
+ "bugs": {
58
+ "url": "https://github.com/Web3Auth/Web3Auth/issues"
59
+ },
60
+ "keywords": [],
61
+ "publishConfig": {
62
+ "access": "public"
63
+ },
64
+ "gitHead": "8716a03717f1ef663252c92816c97a42ef1b2d3a"
65
+ }
package/src/config.ts ADDED
@@ -0,0 +1,93 @@
1
+ import { CHAIN_NAMESPACES, EVM_ADAPTERS, SOLANA_ADAPTERS } from "@web3auth/base";
2
+
3
+ import { AdaptersModalConfig } from "./interface";
4
+
5
+ export const defaultSolanaDappModalConfig: AdaptersModalConfig = {
6
+ chainNamespace: CHAIN_NAMESPACES.SOLANA,
7
+ adapters: {
8
+ [SOLANA_ADAPTERS.TORUS_SOLANA]: {
9
+ label: "Torus Wallet",
10
+ showOnModal: true,
11
+ showOnMobile: true,
12
+ showOnDesktop: true,
13
+ },
14
+ [SOLANA_ADAPTERS.OPENLOGIN]: {
15
+ label: "OpenLogin",
16
+ showOnModal: true,
17
+ showOnMobile: true,
18
+ showOnDesktop: true,
19
+ },
20
+ [SOLANA_ADAPTERS.PHANTOM]: {
21
+ label: "Phantom",
22
+ showOnModal: true,
23
+ showOnMobile: false,
24
+ showOnDesktop: true,
25
+ },
26
+ },
27
+ };
28
+
29
+ export const defaultEvmDappModalConfig: AdaptersModalConfig = {
30
+ chainNamespace: CHAIN_NAMESPACES.EIP155,
31
+ adapters: {
32
+ [EVM_ADAPTERS.TORUS_EVM]: {
33
+ label: "Torus Wallet",
34
+ showOnModal: true,
35
+ showOnMobile: true,
36
+ showOnDesktop: true,
37
+ },
38
+ [EVM_ADAPTERS.METAMASK]: {
39
+ label: "MetaMask",
40
+ showOnModal: true,
41
+ showOnMobile: false,
42
+ showOnDesktop: true,
43
+ },
44
+ [EVM_ADAPTERS.OPENLOGIN]: {
45
+ label: "OpenLogin",
46
+ showOnModal: true,
47
+ showOnMobile: true,
48
+ showOnDesktop: true,
49
+ },
50
+ [EVM_ADAPTERS.WALLET_CONNECT_V1]: {
51
+ label: "Wallet Connect",
52
+ showOnModal: true,
53
+ showOnMobile: true,
54
+ showOnDesktop: true,
55
+ },
56
+ },
57
+ };
58
+
59
+ export const defaultSolanaWalletModalConfig: AdaptersModalConfig = {
60
+ chainNamespace: CHAIN_NAMESPACES.SOLANA,
61
+ adapters: {
62
+ [SOLANA_ADAPTERS.OPENLOGIN]: {
63
+ label: "OpenLogin",
64
+ showOnModal: true,
65
+ showOnMobile: true,
66
+ showOnDesktop: true,
67
+ },
68
+ },
69
+ };
70
+
71
+ export const defaultEvmWalletModalConfig: AdaptersModalConfig = {
72
+ chainNamespace: CHAIN_NAMESPACES.EIP155,
73
+ adapters: {
74
+ [EVM_ADAPTERS.OPENLOGIN]: {
75
+ label: "OpenLogin",
76
+ showOnModal: true,
77
+ showOnMobile: true,
78
+ showOnDesktop: true,
79
+ },
80
+ },
81
+ };
82
+
83
+ export const defaultOtherModalConfig: AdaptersModalConfig = {
84
+ chainNamespace: CHAIN_NAMESPACES.OTHER,
85
+ adapters: {
86
+ [EVM_ADAPTERS.OPENLOGIN]: {
87
+ label: "OpenLogin",
88
+ showOnModal: true,
89
+ showOnMobile: true,
90
+ showOnDesktop: true,
91
+ },
92
+ },
93
+ };
package/src/default.ts ADDED
@@ -0,0 +1,47 @@
1
+ import type { OpenLoginOptions } from "@toruslabs/openlogin";
2
+ import { CHAIN_NAMESPACES, CustomChainConfig, getChainConfig, IAdapter, WALLET_ADAPTER_TYPE, WALLET_ADAPTERS } from "@web3auth/base";
3
+
4
+ export const getDefaultAdapterModule = async (params: {
5
+ name: WALLET_ADAPTER_TYPE;
6
+ clientId: string;
7
+ customChainConfig: Partial<CustomChainConfig> & Pick<CustomChainConfig, "chainNamespace">;
8
+ }): Promise<IAdapter<unknown>> => {
9
+ const { name, customChainConfig, clientId } = params;
10
+ if (!Object.values(CHAIN_NAMESPACES).includes(customChainConfig.chainNamespace))
11
+ throw new Error(`Invalid chainNamespace: ${customChainConfig.chainNamespace}`);
12
+ const finalChainConfig = {
13
+ ...(getChainConfig(customChainConfig.chainNamespace, customChainConfig?.chainId) as CustomChainConfig),
14
+ ...(customChainConfig || {}),
15
+ };
16
+ if (name === WALLET_ADAPTERS.TORUS_EVM) {
17
+ const { TorusWalletAdapter } = await import("@web3auth/torus-evm-adapter");
18
+ const adapter = new TorusWalletAdapter({ chainConfig: finalChainConfig, clientId });
19
+ return adapter;
20
+ } else if (name === WALLET_ADAPTERS.TORUS_SOLANA) {
21
+ const { SolanaWalletAdapter } = await import("@web3auth/torus-solana-adapter");
22
+ const adapter = new SolanaWalletAdapter({ chainConfig: finalChainConfig, clientId });
23
+ return adapter;
24
+ } else if (name === WALLET_ADAPTERS.METAMASK) {
25
+ const { MetamaskAdapter } = await import("@web3auth/metamask-adapter");
26
+ const adapter = new MetamaskAdapter({ chainConfig: finalChainConfig, clientId });
27
+ return adapter;
28
+ } else if (name === WALLET_ADAPTERS.PHANTOM) {
29
+ const { PhantomAdapter } = await import("@web3auth/phantom-adapter");
30
+ const adapter = new PhantomAdapter({ chainConfig: finalChainConfig, clientId });
31
+ return adapter;
32
+ } else if (name === WALLET_ADAPTERS.WALLET_CONNECT_V1) {
33
+ const { WalletConnectV1Adapter } = await import("@web3auth/wallet-connect-v1-adapter");
34
+ const adapter = new WalletConnectV1Adapter({ chainConfig: finalChainConfig, clientId });
35
+ return adapter;
36
+ } else if (name === WALLET_ADAPTERS.OPENLOGIN) {
37
+ const { OpenloginAdapter, getOpenloginDefaultOptions } = await import("@web3auth/openlogin-adapter");
38
+ const defaultOptions = getOpenloginDefaultOptions(customChainConfig.chainNamespace, customChainConfig?.chainId);
39
+ const adapter = new OpenloginAdapter({
40
+ ...defaultOptions,
41
+ chainConfig: { ...(defaultOptions.chainConfig || {}), ...finalChainConfig },
42
+ adapterSettings: { ...(defaultOptions.adapterSettings as OpenLoginOptions), clientId },
43
+ });
44
+ return adapter;
45
+ }
46
+ throw new Error("Invalid wallet adapter name");
47
+ };
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./config";
2
+ export * from "./interface";
3
+ export * from "./modalManager";
@@ -0,0 +1,9 @@
1
+ import type { BaseAdapterConfig, ChainNamespaceType, LoginMethodConfig, WALLET_ADAPTER_TYPE } from "@web3auth/base";
2
+ export interface ModalConfig extends BaseAdapterConfig {
3
+ loginMethods?: LoginMethodConfig;
4
+ }
5
+
6
+ export interface AdaptersModalConfig {
7
+ chainNamespace: ChainNamespaceType;
8
+ adapters?: Record<WALLET_ADAPTER_TYPE, ModalConfig>;
9
+ }
@@ -0,0 +1,351 @@
1
+ import {
2
+ ADAPTER_CATEGORY,
3
+ ADAPTER_EVENTS,
4
+ ADAPTER_STATUS,
5
+ BaseAdapterConfig,
6
+ CHAIN_NAMESPACES,
7
+ CustomChainConfig,
8
+ getChainConfig,
9
+ log,
10
+ SafeEventEmitterProvider,
11
+ WALLET_ADAPTER_TYPE,
12
+ WALLET_ADAPTERS,
13
+ } from "@web3auth/base";
14
+ import { Web3AuthCore, Web3AuthCoreOptions } from "@web3auth/core";
15
+ import LoginModal, { getAdapterSocialLogins, LOGIN_MODAL_EVENTS, OPENLOGIN_PROVIDERS } from "@web3auth/ui";
16
+
17
+ import {
18
+ defaultEvmDappModalConfig,
19
+ defaultEvmWalletModalConfig,
20
+ defaultOtherModalConfig,
21
+ defaultSolanaDappModalConfig,
22
+ defaultSolanaWalletModalConfig,
23
+ } from "./config";
24
+ import { getDefaultAdapterModule } from "./default";
25
+ import { AdaptersModalConfig, ModalConfig } from "./interface";
26
+ import { getUserLanguage } from "./utils";
27
+
28
+ export interface UIConfig {
29
+ /**
30
+ * Logo for your app.
31
+ */
32
+ appLogo?: string;
33
+
34
+ /**
35
+ * theme for the modal
36
+ *
37
+ * @defaultValue `light`
38
+ */
39
+ theme?: "light" | "dark";
40
+
41
+ /**
42
+ * order of how login methods are shown
43
+ *
44
+ * @defaultValue `["google", "facebook", "twitter", "reddit", "discord", "twitch", "apple", "line", "github", "kakao", "linkedin", "weibo", "wechat", "email_passwordless"]`
45
+ */
46
+ loginMethodsOrder?: string[];
47
+
48
+ /**
49
+ * language which will be used by web3auth. app will use browser language if not specified. if language is not supported it will use "en"
50
+ * en: english
51
+ * de: german
52
+ * ja: japanese
53
+ * ko: korean
54
+ * zh: mandarin
55
+ * es: spanish
56
+ *
57
+ */
58
+ defaultLanguage?: string;
59
+ }
60
+ export interface Web3AuthOptions extends Web3AuthCoreOptions {
61
+ /**
62
+ * web3auth instance provides different adapters for different type of usages. If you are dapp and want to
63
+ * use external wallets like metamask, then you can use the `DAPP` authMode.
64
+ * If you are a wallet and only want to use you own wallet implementations along with openlogin,
65
+ * then you should use `WALLET` authMode.
66
+ *
67
+ * @defaultValue `DAPP`
68
+ */
69
+ authMode?: "DAPP" | "WALLET";
70
+ /**
71
+ * Config for configuring modal ui display properties
72
+ */
73
+ uiConfig?: UIConfig;
74
+
75
+ /**
76
+ * Whether to show errors on Web3Auth modal.
77
+ *
78
+ * @defaultValue `true`
79
+ */
80
+ displayErrorsOnModal?: boolean;
81
+ }
82
+ export class Web3Auth extends Web3AuthCore {
83
+ public loginModal: LoginModal;
84
+
85
+ readonly options: Web3AuthOptions;
86
+
87
+ private modalConfig: AdaptersModalConfig = defaultEvmDappModalConfig;
88
+
89
+ constructor(options: Web3AuthOptions) {
90
+ super(options);
91
+ this.options = { ...options };
92
+ const providedChainConfig = this.options.chainConfig;
93
+ if (providedChainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA) {
94
+ if (options.authMode === "WALLET") {
95
+ // default config for solana wallet modal
96
+ this.modalConfig = defaultSolanaWalletModalConfig;
97
+ } else {
98
+ // default config for solana dapp modal
99
+ this.modalConfig = defaultSolanaDappModalConfig;
100
+ }
101
+ } else if (providedChainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155) {
102
+ if (options.authMode === "WALLET") {
103
+ // default config for evm wallet modal
104
+ this.modalConfig = defaultEvmWalletModalConfig;
105
+ } else {
106
+ // default config for evm dapp modal
107
+ this.modalConfig = defaultEvmDappModalConfig;
108
+ }
109
+ } else if (providedChainConfig.chainNamespace === CHAIN_NAMESPACES.OTHER) {
110
+ this.modalConfig = defaultOtherModalConfig;
111
+ } else {
112
+ throw new Error(`Invalid chainNamespace provided: ${providedChainConfig.chainNamespace}`);
113
+ }
114
+
115
+ // get userLanguage
116
+ const defaultLanguage = getUserLanguage(this.options.uiConfig?.defaultLanguage);
117
+
118
+ this.loginModal = new LoginModal({
119
+ theme: this.options.uiConfig?.theme,
120
+ appLogo: this.options.uiConfig?.appLogo || "",
121
+ version: "",
122
+ adapterListener: this,
123
+ displayErrorsOnModal: this.options.displayErrorsOnModal,
124
+ defaultLanguage,
125
+ });
126
+ this.subscribeToLoginModalEvents();
127
+ }
128
+
129
+ public async initModal(params?: { modalConfig?: Record<WALLET_ADAPTER_TYPE, ModalConfig> }): Promise<void> {
130
+ super.checkInitRequirements();
131
+ await this.loginModal.initModal();
132
+ const providedChainConfig = this.options.chainConfig;
133
+
134
+ // merge default adapters with the custom configured adapters.
135
+ const allAdapters = [...new Set([...Object.keys(this.modalConfig.adapters || {}), ...Object.keys(this.walletAdapters)])];
136
+
137
+ const adapterConfigurationPromises = allAdapters.map(async (adapterName) => {
138
+ // start with the default config of adapter.
139
+ let adapterConfig = this.modalConfig.adapters?.[adapterName] || {
140
+ label: adapterName,
141
+ showOnModal: true,
142
+ showOnMobile: true,
143
+ showOnDesktop: true,
144
+ };
145
+
146
+ // override the default config of adapter if some config is being provided by the user.
147
+ if (params?.modalConfig?.[adapterName]) {
148
+ adapterConfig = { ...adapterConfig, ...params.modalConfig[adapterName] };
149
+ }
150
+ (this.modalConfig.adapters as Record<WALLET_ADAPTER_TYPE, ModalConfig>)[adapterName] = adapterConfig as ModalConfig;
151
+
152
+ // check if adapter is configured/added by user and exist in walletAdapters map.
153
+ const adapter = this.walletAdapters[adapterName];
154
+ log.debug("adapter config", adapterName, this.modalConfig.adapters?.[adapterName].showOnModal, adapter);
155
+
156
+ // if adapter is not custom configured then check if it is available in default adapters.
157
+ // and if adapter is not hidden by user
158
+ if (!adapter && this.modalConfig.adapters?.[adapterName].showOnModal) {
159
+ // if adapter is not configured and some default configuration is available, use it.
160
+ const ad = await getDefaultAdapterModule({
161
+ name: adapterName,
162
+ customChainConfig: this.options.chainConfig,
163
+ clientId: this.options.clientId,
164
+ });
165
+
166
+ this.walletAdapters[adapterName] = ad;
167
+
168
+ return adapterName;
169
+ } else if (adapter?.type === ADAPTER_CATEGORY.IN_APP || adapter?.type === ADAPTER_CATEGORY.EXTERNAL || adapterName === this.cachedAdapter) {
170
+ if (!this.modalConfig.adapters?.[adapterName].showOnModal) return;
171
+ // add client id to adapter, same web3auth client id can be used in adapter.
172
+ // this id is being overridden if user is also passing client id in adapter's constructor.
173
+ this.walletAdapters[adapterName].setAdapterSettings({ clientId: this.options.clientId, sessionTime: this.options.sessionTime });
174
+
175
+ // if adapter doesn't have any chainConfig then we will set the chainConfig based of passed chainNamespace
176
+ // and chainNamespace.
177
+ if (!adapter.chainConfigProxy) {
178
+ const chainConfig = {
179
+ ...getChainConfig(providedChainConfig.chainNamespace, this.coreOptions.chainConfig?.chainId),
180
+ ...this.coreOptions.chainConfig,
181
+ } as CustomChainConfig;
182
+ this.walletAdapters[adapterName].setChainConfig(chainConfig);
183
+ }
184
+
185
+ return adapterName;
186
+ }
187
+ });
188
+
189
+ const adapterNames = await Promise.all(adapterConfigurationPromises);
190
+ const hasInAppWallets = Object.values(this.walletAdapters).some((adapter) => {
191
+ if (adapter.type !== ADAPTER_CATEGORY.IN_APP) return false;
192
+ if (this.modalConfig.adapters[adapter.name].showOnModal !== true) return false;
193
+ if (!this.modalConfig.adapters[adapter.name].loginMethods) return true;
194
+ const mergedLoginMethods = getAdapterSocialLogins(
195
+ adapter.name,
196
+ this.walletAdapters[adapter.name],
197
+ (this.modalConfig.adapters as Record<WALLET_ADAPTER_TYPE, ModalConfig>)[adapter.name]?.loginMethods
198
+ );
199
+ if (Object.values(mergedLoginMethods).some((method) => method.showOnModal)) return true;
200
+ return false;
201
+ });
202
+ log.debug(hasInAppWallets, this.walletAdapters, "hasInAppWallets");
203
+ // Now, initialize the adapters.
204
+ const initPromises = adapterNames.map(async (adapterName) => {
205
+ if (!adapterName) return;
206
+ try {
207
+ const adapter = this.walletAdapters[adapterName];
208
+ // only initialize a external adapter here if it is a cached adapter.
209
+ if (this.cachedAdapter !== adapterName && adapter.type === ADAPTER_CATEGORY.EXTERNAL) {
210
+ return;
211
+ }
212
+ // in-app wallets or cached wallet (being connected or already connected) are initialized first.
213
+ // if adapter is configured thn only initialize in app or cached adapter.
214
+ // external wallets are initialized on INIT_EXTERNAL_WALLET event.
215
+ this.subscribeToAdapterEvents(adapter);
216
+ if (adapter.status === ADAPTER_STATUS.NOT_READY) await adapter.init({ autoConnect: this.cachedAdapter === adapterName });
217
+ // note: not adding cachedWallet to modal if it is external wallet.
218
+ // adding it later if no in-app wallets are available.
219
+ if (adapter.type === ADAPTER_CATEGORY.IN_APP) {
220
+ this.initializeInAppWallet(adapterName);
221
+ }
222
+ } catch (error) {
223
+ log.error(error, "error while initializing adapter");
224
+ }
225
+ });
226
+
227
+ this.status = ADAPTER_STATUS.READY;
228
+ await Promise.all(initPromises);
229
+
230
+ const hasExternalWallets = allAdapters.some((adapterName) => {
231
+ return this.walletAdapters[adapterName]?.type === ADAPTER_CATEGORY.EXTERNAL && this.modalConfig.adapters?.[adapterName].showOnModal;
232
+ });
233
+
234
+ if (hasExternalWallets) {
235
+ this.loginModal.initExternalWalletContainer();
236
+ }
237
+
238
+ // variable to check if we have any in app wallets
239
+ // currently all default in app and external wallets can be hidden or shown based on config.
240
+ if (!hasInAppWallets && hasExternalWallets) {
241
+ // if no in app wallet is available then initialize external wallets in modal
242
+ await this.initExternalWalletAdapters(false, { showExternalWalletsOnly: true });
243
+ }
244
+ }
245
+
246
+ public async connect(): Promise<SafeEventEmitterProvider | null> {
247
+ // if (!this.loginModal.initialized) throw new Error("Login modal is not initialized");
248
+ // if already connected return provider
249
+ if (this.provider) return this.provider;
250
+ this.loginModal.open();
251
+ return new Promise((resolve, reject) => {
252
+ this.once(ADAPTER_EVENTS.CONNECTED, () => {
253
+ return resolve(this.provider);
254
+ });
255
+ this.once(ADAPTER_EVENTS.ERRORED, (err: unknown) => {
256
+ return reject(err);
257
+ });
258
+ });
259
+ }
260
+
261
+ private async initExternalWalletAdapters(externalWalletsInitialized: boolean, options?: { showExternalWalletsOnly: boolean }): Promise<void> {
262
+ if (externalWalletsInitialized) return;
263
+ const adaptersConfig: Record<string, BaseAdapterConfig> = {};
264
+ const adaptersData: Record<string, unknown> = {};
265
+ const adapterPromises = Object.keys(this.walletAdapters).map(async (adapterName) => {
266
+ try {
267
+ const adapter = this.walletAdapters[adapterName];
268
+ if (adapter?.type === ADAPTER_CATEGORY.EXTERNAL) {
269
+ log.debug("init external wallet", this.cachedAdapter, adapterName);
270
+ this.subscribeToAdapterEvents(adapter);
271
+ // we are not initializing cached adapter here as it is already being initialized in initModal before.
272
+ if (this.cachedAdapter === adapterName) {
273
+ return;
274
+ }
275
+ if (adapter.status === ADAPTER_STATUS.NOT_READY)
276
+ return await Promise.race([
277
+ adapter.init({ autoConnect: this.cachedAdapter === adapterName }).then(() => {
278
+ adaptersConfig[adapterName] = (this.modalConfig.adapters as Record<WALLET_ADAPTER_TYPE, ModalConfig>)[adapterName];
279
+ adaptersData[adapterName] = adapter.adapterData || {};
280
+ return adapterName;
281
+ }),
282
+ new Promise((resolve) => {
283
+ setTimeout(() => {
284
+ return resolve(null);
285
+ }, 5000);
286
+ }),
287
+ ]);
288
+ }
289
+ } catch (error) {
290
+ log.error(error, "error while initializing adapter");
291
+ }
292
+ });
293
+
294
+ const adapterInitResults = await Promise.all(adapterPromises);
295
+ const finalAdaptersConfig: Record<WALLET_ADAPTER_TYPE, BaseAdapterConfig> = {};
296
+ adapterInitResults.forEach((result: string | undefined) => {
297
+ if (result) {
298
+ finalAdaptersConfig[result] = adaptersConfig[result];
299
+ }
300
+ });
301
+ this.loginModal.addWalletLogins(finalAdaptersConfig, { showExternalWalletsOnly: !!options?.showExternalWalletsOnly });
302
+ }
303
+
304
+ private initializeInAppWallet(adapterName: string): void {
305
+ log.info("adapterInitResults", adapterName);
306
+ if (this.walletAdapters[adapterName].type === ADAPTER_CATEGORY.IN_APP) {
307
+ this.loginModal.addSocialLogins(
308
+ adapterName,
309
+ getAdapterSocialLogins(
310
+ adapterName,
311
+ this.walletAdapters[adapterName],
312
+ (this.modalConfig.adapters as Record<WALLET_ADAPTER_TYPE, ModalConfig>)[adapterName]?.loginMethods
313
+ ),
314
+ this.options.uiConfig?.loginMethodsOrder || OPENLOGIN_PROVIDERS
315
+ );
316
+ }
317
+ }
318
+
319
+ private subscribeToLoginModalEvents(): void {
320
+ this.loginModal.on(LOGIN_MODAL_EVENTS.LOGIN, async (params: { adapter: WALLET_ADAPTER_TYPE; loginParams: unknown }) => {
321
+ try {
322
+ await this.connectTo<unknown>(params.adapter, params.loginParams);
323
+ } catch (error) {
324
+ log.error(`Error while connecting to adapter: ${params.adapter}`, error);
325
+ }
326
+ });
327
+ this.loginModal.on(LOGIN_MODAL_EVENTS.INIT_EXTERNAL_WALLETS, async (params: { externalWalletsInitialized: boolean }) => {
328
+ await this.initExternalWalletAdapters(params.externalWalletsInitialized);
329
+ });
330
+ this.loginModal.on(LOGIN_MODAL_EVENTS.DISCONNECT, async () => {
331
+ try {
332
+ await this.logout();
333
+ } catch (error) {
334
+ log.error(`Error while disconnecting`, error);
335
+ }
336
+ });
337
+ this.loginModal.on(LOGIN_MODAL_EVENTS.MODAL_VISIBILITY, async (visibility: boolean) => {
338
+ log.debug("is login modal visible", visibility);
339
+ this.emit(LOGIN_MODAL_EVENTS.MODAL_VISIBILITY, visibility);
340
+ const walletConnectStatus = this.walletAdapters[WALLET_ADAPTERS.WALLET_CONNECT_V1]?.status;
341
+ if (visibility && walletConnectStatus === ADAPTER_STATUS.READY) {
342
+ // refreshing session for wallet connect whenever modal is opened.
343
+ try {
344
+ this.walletAdapters[WALLET_ADAPTERS.WALLET_CONNECT_V1].connect();
345
+ } catch (error) {
346
+ log.error(`Error while disconnecting to wallet connect in core`, error);
347
+ }
348
+ }
349
+ });
350
+ }
351
+ }