shogun-core 1.2.7 → 1.2.8

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.
Files changed (67) hide show
  1. package/README.md +0 -1
  2. package/dist/browser/shogun-core.js +1 -1
  3. package/dist/browser/shogun-core.js.LICENSE.txt +2 -0
  4. package/dist/browser/shogun-core.light.js +1 -1
  5. package/dist/browser/shogun-core.vendors.light.js +1 -1
  6. package/dist/core.js +31 -71
  7. package/dist/gundb/{instance.js → gunInstance.js} +135 -115
  8. package/dist/gundb/index.js +3 -20
  9. package/dist/plugins/index.js +23 -1
  10. package/dist/plugins/nostr/index.js +1 -0
  11. package/dist/plugins/nostr/nostrChain.js +128 -0
  12. package/dist/plugins/nostr/nostrConnector.js +42 -7
  13. package/dist/plugins/nostr/nostrConnectorPlugin.js +157 -1
  14. package/dist/plugins/nostr/nostrSigner.js +343 -0
  15. package/dist/plugins/oauth/index.js +13 -0
  16. package/dist/plugins/oauth/oauthChain.js +161 -0
  17. package/dist/plugins/oauth/oauthConnector.js +542 -0
  18. package/dist/plugins/oauth/oauthPlugin.js +302 -0
  19. package/dist/plugins/oauth/types.js +2 -0
  20. package/dist/plugins/web3/index.js +1 -0
  21. package/dist/plugins/web3/web3Chain.js +77 -2
  22. package/dist/plugins/web3/web3Connector.js +159 -37
  23. package/dist/plugins/web3/web3ConnectorPlugin.js +157 -1
  24. package/dist/plugins/web3/web3Signer.js +268 -0
  25. package/dist/plugins/webauthn/webauthnChain.js +78 -0
  26. package/dist/plugins/webauthn/webauthnPlugin.js +154 -1
  27. package/dist/plugins/webauthn/webauthnSigner.js +318 -0
  28. package/dist/storage/storage.js +0 -8
  29. package/dist/types/core.d.ts +10 -34
  30. package/dist/types/gundb/gun-es/gun-es.d.ts +1 -0
  31. package/dist/types/gundb/{instance.d.ts → gunInstance.d.ts} +2 -2
  32. package/dist/types/gundb/index.d.ts +1 -4
  33. package/dist/types/plugins/index.d.ts +4 -0
  34. package/dist/types/plugins/nostr/index.d.ts +1 -0
  35. package/dist/types/plugins/nostr/nostrConnector.d.ts +3 -2
  36. package/dist/types/plugins/nostr/nostrConnectorPlugin.d.ts +82 -0
  37. package/dist/types/plugins/nostr/nostrSigner.d.ts +104 -0
  38. package/dist/types/plugins/oauth/index.d.ts +4 -0
  39. package/dist/types/plugins/oauth/oauthChain.d.ts +2 -0
  40. package/dist/types/plugins/oauth/oauthConnector.d.ts +100 -0
  41. package/dist/types/plugins/oauth/oauthPlugin.d.ts +89 -0
  42. package/dist/types/plugins/oauth/types.d.ts +106 -0
  43. package/dist/types/plugins/web3/index.d.ts +1 -0
  44. package/dist/types/plugins/web3/types.d.ts +1 -0
  45. package/dist/types/plugins/web3/web3Connector.d.ts +8 -2
  46. package/dist/types/plugins/web3/web3ConnectorPlugin.d.ts +82 -0
  47. package/dist/types/plugins/web3/web3Signer.d.ts +93 -0
  48. package/dist/types/plugins/webauthn/webauthnPlugin.d.ts +81 -0
  49. package/dist/types/plugins/webauthn/webauthnSigner.d.ts +90 -0
  50. package/dist/types/shogun.js +1 -28
  51. package/dist/types/types/events.d.ts +2 -2
  52. package/dist/types/types/shogun.d.ts +13 -49
  53. package/package.json +2 -1
  54. package/dist/browser.js +0 -107
  55. package/dist/contracts/base.js +0 -152
  56. package/dist/contracts/entryPoint.js +0 -407
  57. package/dist/contracts/index.js +0 -47
  58. package/dist/contracts/registry.js +0 -259
  59. package/dist/contracts/relay.js +0 -494
  60. package/dist/contracts/utils.js +0 -582
  61. package/dist/types/browser.d.ts +0 -27
  62. package/dist/types/contracts/base.d.ts +0 -82
  63. package/dist/types/contracts/entryPoint.d.ts +0 -138
  64. package/dist/types/contracts/index.d.ts +0 -17
  65. package/dist/types/contracts/registry.d.ts +0 -97
  66. package/dist/types/contracts/relay.d.ts +0 -165
  67. package/dist/types/contracts/utils.d.ts +0 -173
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OAuthPlugin = void 0;
4
+ const base_1 = require("../base");
5
+ const oauthConnector_1 = require("./oauthConnector");
6
+ const logger_1 = require("../../utils/logger");
7
+ const errorHandler_1 = require("../../utils/errorHandler");
8
+ /**
9
+ * OAuth Plugin for ShogunCore
10
+ * Provides authentication with external OAuth providers
11
+ */
12
+ class OAuthPlugin extends base_1.BasePlugin {
13
+ name = "oauth";
14
+ version = "1.0.0";
15
+ description = "Provides OAuth authentication with external providers for ShogunCore";
16
+ oauthConnector = null;
17
+ config = {};
18
+ /**
19
+ * @inheritdoc
20
+ */
21
+ initialize(core) {
22
+ super.initialize(core);
23
+ // Initialize the OAuth connector
24
+ this.oauthConnector = new oauthConnector_1.OAuthConnector(this.config);
25
+ (0, logger_1.log)("OAuth plugin initialized successfully");
26
+ }
27
+ /**
28
+ * Configure the OAuth plugin with provider settings
29
+ * @param config - Configuration options for OAuth
30
+ */
31
+ configure(config) {
32
+ this.config = { ...this.config, ...config };
33
+ // If connector is already initialized, update its configuration
34
+ if (this.oauthConnector) {
35
+ this.oauthConnector.updateConfig(this.config);
36
+ (0, logger_1.log)("OAuth connector configuration updated", this.config.providers);
37
+ }
38
+ }
39
+ /**
40
+ * @inheritdoc
41
+ */
42
+ destroy() {
43
+ if (this.oauthConnector) {
44
+ this.oauthConnector.cleanup();
45
+ }
46
+ this.oauthConnector = null;
47
+ super.destroy();
48
+ (0, logger_1.log)("OAuth plugin destroyed");
49
+ }
50
+ /**
51
+ * Ensure that the OAuth connector is initialized
52
+ * @private
53
+ */
54
+ assertOAuthConnector() {
55
+ this.assertInitialized();
56
+ if (!this.oauthConnector) {
57
+ throw new Error("OAuth connector not initialized");
58
+ }
59
+ return this.oauthConnector;
60
+ }
61
+ /**
62
+ * @inheritdoc
63
+ */
64
+ isSupported() {
65
+ return this.assertOAuthConnector().isSupported();
66
+ }
67
+ /**
68
+ * @inheritdoc
69
+ */
70
+ getAvailableProviders() {
71
+ return this.assertOAuthConnector().getAvailableProviders();
72
+ }
73
+ /**
74
+ * @inheritdoc
75
+ */
76
+ async initiateOAuth(provider) {
77
+ (0, logger_1.log)(`Initiating OAuth flow with ${provider}`);
78
+ return this.assertOAuthConnector().initiateOAuth(provider);
79
+ }
80
+ /**
81
+ * @inheritdoc
82
+ */
83
+ async completeOAuth(provider, authCode, state) {
84
+ (0, logger_1.log)(`Completing OAuth flow with ${provider}`);
85
+ return this.assertOAuthConnector().completeOAuth(provider, authCode, state);
86
+ }
87
+ /**
88
+ * @inheritdoc
89
+ */
90
+ async generateCredentials(userInfo, provider) {
91
+ (0, logger_1.log)(`Generating credentials for ${provider} user`);
92
+ return this.assertOAuthConnector().generateCredentials(userInfo, provider);
93
+ }
94
+ /**
95
+ * Login with OAuth
96
+ * @param provider - OAuth provider to use
97
+ * @returns {Promise<AuthResult>} Authentication result
98
+ * @description Authenticates user using OAuth with external providers
99
+ */
100
+ async login(provider) {
101
+ (0, logger_1.log)(`OAuth login with ${provider}`);
102
+ try {
103
+ const core = this.assertInitialized();
104
+ (0, logger_1.log)(`OAuth login attempt with provider: ${provider}`);
105
+ if (!provider) {
106
+ throw (0, errorHandler_1.createError)(errorHandler_1.ErrorType.VALIDATION, "PROVIDER_REQUIRED", "OAuth provider required for OAuth login");
107
+ }
108
+ if (!this.isSupported()) {
109
+ throw (0, errorHandler_1.createError)(errorHandler_1.ErrorType.ENVIRONMENT, "OAUTH_UNAVAILABLE", "OAuth is not supported in this environment");
110
+ }
111
+ // Check if provider is available
112
+ const availableProviders = this.getAvailableProviders();
113
+ if (!availableProviders.includes(provider)) {
114
+ throw (0, errorHandler_1.createError)(errorHandler_1.ErrorType.VALIDATION, "PROVIDER_NOT_CONFIGURED", `Provider ${provider} is not configured or available`);
115
+ }
116
+ // Initiate OAuth flow with the provider
117
+ const oauthResult = await this.initiateOAuth(provider);
118
+ if (!oauthResult.success) {
119
+ throw (0, errorHandler_1.createError)(errorHandler_1.ErrorType.AUTHENTICATION, "OAUTH_INITIATION_FAILED", oauthResult.error || "Failed to initiate OAuth flow");
120
+ }
121
+ // In a browser environment, this would redirect to the OAuth provider
122
+ // The frontend should handle the redirect and then call handleOAuthCallback
123
+ // with the received code and state when the provider redirects back
124
+ // Return early with the auth URL that the frontend should use for redirection
125
+ return {
126
+ success: true,
127
+ redirectUrl: oauthResult.authUrl,
128
+ pendingAuth: true,
129
+ message: "Redirect to OAuth provider required to complete authentication",
130
+ provider,
131
+ authMethod: "oauth",
132
+ };
133
+ }
134
+ catch (error) {
135
+ // Handle both ShogunError and generic errors
136
+ const errorType = error?.type || errorHandler_1.ErrorType.AUTHENTICATION;
137
+ const errorCode = error?.code || "OAUTH_LOGIN_ERROR";
138
+ const errorMessage = error?.message || "Unknown error during OAuth login";
139
+ const handledError = errorHandler_1.ErrorHandler.handle(errorType, errorCode, errorMessage, error);
140
+ return {
141
+ success: false,
142
+ error: handledError.message,
143
+ };
144
+ }
145
+ }
146
+ /**
147
+ * Sign up with OAuth
148
+ * @param provider - OAuth provider to use
149
+ * @returns {Promise<AuthResult>} Registration result
150
+ * @description Creates a new user account using OAuth with external providers
151
+ */
152
+ async signUp(provider) {
153
+ (0, logger_1.log)(`OAuth signup with ${provider}`);
154
+ try {
155
+ const core = this.assertInitialized();
156
+ (0, logger_1.log)(`OAuth signup attempt with provider: ${provider}`);
157
+ if (!provider) {
158
+ throw (0, errorHandler_1.createError)(errorHandler_1.ErrorType.VALIDATION, "PROVIDER_REQUIRED", "OAuth provider required for OAuth signup");
159
+ }
160
+ if (!this.isSupported()) {
161
+ throw (0, errorHandler_1.createError)(errorHandler_1.ErrorType.ENVIRONMENT, "OAUTH_UNAVAILABLE", "OAuth is not supported in this environment");
162
+ }
163
+ // Check if provider is available
164
+ const availableProviders = this.getAvailableProviders();
165
+ if (!availableProviders.includes(provider)) {
166
+ throw (0, errorHandler_1.createError)(errorHandler_1.ErrorType.VALIDATION, "PROVIDER_NOT_CONFIGURED", `Provider ${provider} is not configured or available`);
167
+ }
168
+ // Initiate OAuth flow with the provider
169
+ const oauthResult = await this.initiateOAuth(provider);
170
+ if (!oauthResult.success) {
171
+ throw (0, errorHandler_1.createError)(errorHandler_1.ErrorType.AUTHENTICATION, "OAUTH_INITIATION_FAILED", oauthResult.error || "Failed to initiate OAuth flow");
172
+ }
173
+ // In a browser environment, this would redirect to the OAuth provider
174
+ // The frontend should handle the redirect and then call handleOAuthCallback
175
+ // with the received code and state when the provider redirects back
176
+ // Return early with the auth URL that the frontend should use for redirection
177
+ return {
178
+ success: true,
179
+ redirectUrl: oauthResult.authUrl,
180
+ pendingAuth: true,
181
+ message: "Redirect to OAuth provider required to complete registration",
182
+ provider,
183
+ authMethod: "oauth",
184
+ };
185
+ }
186
+ catch (error) {
187
+ // Handle both ShogunError and generic errors
188
+ const errorType = error?.type || errorHandler_1.ErrorType.AUTHENTICATION;
189
+ const errorCode = error?.code || "OAUTH_SIGNUP_ERROR";
190
+ const errorMessage = error?.message || "Unknown error during OAuth signup";
191
+ const handledError = errorHandler_1.ErrorHandler.handle(errorType, errorCode, errorMessage, error);
192
+ return {
193
+ success: false,
194
+ error: handledError.message,
195
+ };
196
+ }
197
+ }
198
+ /**
199
+ * Handle OAuth callback (for frontend integration)
200
+ * This method would be called when the OAuth provider redirects back
201
+ */
202
+ async handleOAuthCallback(provider, authCode, state) {
203
+ try {
204
+ (0, logger_1.log)(`Handling OAuth callback for ${provider}`);
205
+ const core = this.assertInitialized();
206
+ // Complete the OAuth flow
207
+ const result = await this.completeOAuth(provider, authCode, state);
208
+ if (!result.success || !result.userInfo) {
209
+ throw new Error(result.error || "Failed to complete OAuth flow");
210
+ }
211
+ // Generate credentials from user info
212
+ const credentials = await this.generateCredentials(result.userInfo, provider);
213
+ // Set authentication method
214
+ core.setAuthMethod("oauth");
215
+ // Login or sign up the user
216
+ const authResult = await this._loginOrSignUp(credentials.username, credentials.password);
217
+ if (authResult.success) {
218
+ // Store user info in user metadata
219
+ if (core.user) {
220
+ await core.user.put({
221
+ oauth: {
222
+ provider,
223
+ id: result.userInfo.id,
224
+ email: result.userInfo.email,
225
+ name: result.userInfo.name,
226
+ picture: result.userInfo.picture,
227
+ lastLogin: Date.now(),
228
+ },
229
+ });
230
+ }
231
+ // Emit appropriate event
232
+ const eventType = authResult.isNewUser ? "auth:signup" : "auth:login";
233
+ core.emit(eventType, {
234
+ userPub: authResult.userPub,
235
+ username: credentials.username,
236
+ method: "oauth",
237
+ provider,
238
+ });
239
+ }
240
+ return authResult;
241
+ }
242
+ catch (error) {
243
+ (0, logger_1.logError)(`Error handling OAuth callback for ${provider}:`, error);
244
+ return {
245
+ success: false,
246
+ error: error.message || "Failed to handle OAuth callback",
247
+ };
248
+ }
249
+ }
250
+ /**
251
+ * Private helper to login or sign up a user
252
+ */
253
+ async _loginOrSignUp(username, password) {
254
+ const core = this.assertInitialized();
255
+ if (!password) {
256
+ return {
257
+ success: false,
258
+ error: "Password not provided for login/signup.",
259
+ };
260
+ }
261
+ return new Promise((resolve) => {
262
+ // Check if user exists first to avoid race conditions
263
+ core.gun.get(`~@${username}`).once(async (data) => {
264
+ let authResult;
265
+ if (data) {
266
+ // User exists, so log in
267
+ (0, logger_1.log)(`User ${username} exists, attempting login.`);
268
+ authResult = await core.login(username, password);
269
+ authResult.isNewUser = false;
270
+ }
271
+ else {
272
+ // User does not exist, so sign up
273
+ (0, logger_1.log)(`User ${username} does not exist, attempting signup.`);
274
+ authResult = await core.signUp(username, password);
275
+ authResult.isNewUser = true;
276
+ }
277
+ resolve(authResult);
278
+ });
279
+ });
280
+ }
281
+ /**
282
+ * Alias for handleOAuthCallback for backward compatibility
283
+ * @deprecated Use handleOAuthCallback instead
284
+ */
285
+ async handleSimpleOAuth(provider, authCode, state) {
286
+ (0, logger_1.log)(`handleSimpleOAuth called (alias for handleOAuthCallback) for ${provider}`);
287
+ return this.handleOAuthCallback(provider, authCode, state);
288
+ }
289
+ /**
290
+ * Get cached user info for a user
291
+ */
292
+ getCachedUserInfo(userId, provider) {
293
+ return this.assertOAuthConnector().getCachedUserInfo(userId, provider);
294
+ }
295
+ /**
296
+ * Clear user info cache
297
+ */
298
+ clearUserCache(userId, provider) {
299
+ this.assertOAuthConnector().clearUserCache(userId, provider);
300
+ }
301
+ }
302
+ exports.OAuthPlugin = OAuthPlugin;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -21,5 +21,6 @@ exports.web3Chain = void 0;
21
21
  __exportStar(require("./web3ConnectorPlugin"), exports);
22
22
  __exportStar(require("./types"), exports);
23
23
  __exportStar(require("./web3Connector"), exports);
24
+ __exportStar(require("./web3Signer"), exports);
24
25
  var web3Chain_1 = require("./web3Chain");
25
26
  Object.defineProperty(exports, "web3Chain", { enumerable: true, get: function () { return __importDefault(web3Chain_1).default; } });
@@ -5,8 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const gun_1 = __importDefault(require("gun"));
7
7
  const web3Connector_1 = require("./web3Connector");
8
+ const web3Signer_1 = require("./web3Signer");
8
9
  const web3Chain = () => {
9
10
  const web3 = new web3Connector_1.Web3Connector();
11
+ const signer = new web3Signer_1.Web3Signer(web3);
12
+ // Initialize the web3 chain object if it doesn't exist
13
+ if (!gun_1.default.chain.web3) {
14
+ gun_1.default.chain.web3 = {};
15
+ }
10
16
  gun_1.default.chain.web3.connect = async function () {
11
17
  return await web3.connectMetaMask();
12
18
  };
@@ -23,11 +29,80 @@ const web3Chain = () => {
23
29
  const signer = await web3.getSigner();
24
30
  return await signer.signMessage(message);
25
31
  };
26
- gun_1.default.chain.verifySignature = async function (message, signature) {
32
+ gun_1.default.chain.web3.verifySignature = async function (message, signature) {
27
33
  return await web3.verifySignature(message, signature);
28
34
  };
29
- gun_1.default.chain.isMetaMaskAvailable = function () {
35
+ gun_1.default.chain.web3.isMetaMaskAvailable = function () {
30
36
  return web3Connector_1.Web3Connector.isMetaMaskAvailable();
31
37
  };
38
+ /**
39
+ * Setup oneshot signing for an Ethereum address
40
+ * Creates signing credential with consistent password generation
41
+ */
42
+ gun_1.default.chain.web3.setupOneshotSigning = async function (address) {
43
+ return await signer.createSigningCredential(address);
44
+ };
45
+ /**
46
+ * Create authenticator for Web3 signing
47
+ * Returns a function that can be used with SEA.sign
48
+ */
49
+ gun_1.default.chain.web3.createAuthenticator = function (address) {
50
+ return signer.createAuthenticator(address);
51
+ };
52
+ /**
53
+ * Create derived key pair from Web3 credential
54
+ * Uses the same password generation as normal Web3 approach
55
+ */
56
+ gun_1.default.chain.web3.createDerivedKeyPair = async function (address, extra) {
57
+ return await signer.createDerivedKeyPair(address, extra);
58
+ };
59
+ /**
60
+ * Quick sign method that combines Web3 verification with derived key signing
61
+ * Similar to webauthn.js but for Web3
62
+ */
63
+ gun_1.default.chain.web3.quickSign = async function (data, address, extra) {
64
+ return await signer.signWithDerivedKeys(data, address, extra);
65
+ };
66
+ /**
67
+ * Creates a Gun user from Web3 signing credential
68
+ * Ensures SAME user as normal approach
69
+ */
70
+ gun_1.default.chain.web3.createGunUserFromSigningCredential = async function (address) {
71
+ return await signer.createGunUser(address, this);
72
+ };
73
+ /**
74
+ * Get the Gun user public key for a signing credential
75
+ */
76
+ gun_1.default.chain.web3.getGunUserPubFromSigningCredential = function (address) {
77
+ return signer.getGunUserPub(address);
78
+ };
79
+ /**
80
+ * Get the password (for consistency checking)
81
+ */
82
+ gun_1.default.chain.web3.getPassword = function (address) {
83
+ return signer.getPassword(address);
84
+ };
85
+ /**
86
+ * Verify consistency between oneshot and normal approaches
87
+ */
88
+ gun_1.default.chain.web3.verifyConsistency = async function (address, expectedUserPub) {
89
+ return await signer.verifyConsistency(address, expectedUserPub);
90
+ };
91
+ /**
92
+ * Complete consistent oneshot signing workflow
93
+ * Creates the SAME Gun user as normal approach
94
+ */
95
+ gun_1.default.chain.web3.setupConsistentOneshotSigning = async function (address) {
96
+ const credential = await signer.createSigningCredential(address);
97
+ const authenticator = signer.createAuthenticator(address);
98
+ const gunUser = await signer.createGunUser(address, this);
99
+ return {
100
+ credential,
101
+ authenticator,
102
+ gunUser,
103
+ username: credential.username,
104
+ password: credential.password,
105
+ };
106
+ };
32
107
  };
33
108
  exports.default = web3Chain;
@@ -31,33 +31,112 @@ class Web3Connector extends eventEmitter_1.EventEmitter {
31
31
  this.setupEventListeners();
32
32
  }
33
33
  /**
34
- * Initialize the provider synchronously
34
+ * Initialize the provider synchronously with fallback mechanisms
35
+ * to handle conflicts between multiple wallet providers
35
36
  */
36
37
  initProvider() {
37
- if (typeof window !== "undefined" && window.ethereum) {
38
+ if (typeof window !== "undefined") {
38
39
  try {
39
- this.provider = new ethers_1.ethers.BrowserProvider(window.ethereum);
40
- (0, logger_1.logDebug)("BrowserProvider initialized successfully");
40
+ // Check if ethereum is available from any provider
41
+ const ethereumProvider = this.getAvailableEthereumProvider();
42
+ if (ethereumProvider) {
43
+ this.provider = new ethers_1.ethers.BrowserProvider(ethereumProvider);
44
+ (0, logger_1.logDebug)("BrowserProvider initialized successfully");
45
+ }
46
+ else {
47
+ (0, logger_1.logWarn)("No compatible Ethereum provider found");
48
+ }
41
49
  }
42
50
  catch (error) {
43
51
  (0, logger_1.logError)("Failed to initialize BrowserProvider", error);
44
52
  }
45
53
  }
46
54
  else {
47
- (0, logger_1.logWarn)("Window.ethereum is not available");
55
+ (0, logger_1.logWarn)("Window object not available (non-browser environment)");
56
+ }
57
+ }
58
+ /**
59
+ * Get available Ethereum provider from multiple possible sources
60
+ */
61
+ getAvailableEthereumProvider() {
62
+ if (typeof window === "undefined")
63
+ return undefined;
64
+ // Define provider sources with priority order
65
+ const providerSources = [
66
+ // Check if we have providers in the _ethereumProviders registry (from index.html)
67
+ {
68
+ source: () => window._ethereumProviders && window._ethereumProviders[0],
69
+ name: "Registry Primary",
70
+ },
71
+ { source: () => window.ethereum, name: "Standard ethereum" },
72
+ {
73
+ source: () => window.web3?.currentProvider,
74
+ name: "Legacy web3",
75
+ },
76
+ { source: () => window.metamask, name: "MetaMask specific" },
77
+ {
78
+ source: () => window.ethereum?.providers?.find((p) => p.isMetaMask),
79
+ name: "MetaMask from providers array",
80
+ },
81
+ {
82
+ source: () => window.ethereum?.providers?.[0],
83
+ name: "First provider in array",
84
+ },
85
+ // Try known provider names
86
+ {
87
+ source: () => window.enkrypt?.providers?.ethereum,
88
+ name: "Enkrypt",
89
+ },
90
+ {
91
+ source: () => window.coinbaseWalletExtension,
92
+ name: "Coinbase",
93
+ },
94
+ { source: () => window.trustWallet, name: "Trust Wallet" },
95
+ // Use special registry if available
96
+ {
97
+ source: () => Array.isArray(window._ethereumProviders)
98
+ ? window._ethereumProviders.find((p) => !p._isProxy)
99
+ : undefined,
100
+ name: "Registry non-proxy",
101
+ },
102
+ ];
103
+ // Try each provider source
104
+ for (const { source, name } of providerSources) {
105
+ try {
106
+ const provider = source();
107
+ if (provider && typeof provider.request === "function") {
108
+ (0, logger_1.logDebug)(`Found compatible Ethereum provider: ${name}`);
109
+ return provider;
110
+ }
111
+ }
112
+ catch (error) {
113
+ // Continue to next provider source
114
+ (0, logger_1.logWarn)(`Error checking provider ${name}:`, error);
115
+ continue;
116
+ }
48
117
  }
118
+ // No provider found
119
+ (0, logger_1.logWarn)("No compatible Ethereum provider found");
120
+ return undefined;
49
121
  }
50
122
  /**
51
123
  * Initialize the BrowserProvider (async method for explicit calls)
52
124
  */
53
125
  async setupProvider() {
54
126
  try {
55
- if (typeof window !== "undefined" && window.ethereum) {
56
- this.provider = new ethers_1.ethers.BrowserProvider(window.ethereum);
57
- (0, logger_1.logDebug)("BrowserProvider initialized successfully");
127
+ if (typeof window !== "undefined") {
128
+ // Check if ethereum is available from any provider
129
+ const ethereumProvider = this.getAvailableEthereumProvider();
130
+ if (ethereumProvider) {
131
+ this.provider = new ethers_1.ethers.BrowserProvider(ethereumProvider);
132
+ (0, logger_1.logDebug)("BrowserProvider initialized successfully");
133
+ }
134
+ else {
135
+ (0, logger_1.logWarn)("No compatible Ethereum provider found");
136
+ }
58
137
  }
59
138
  else {
60
- (0, logger_1.logWarn)("Window.ethereum is not available");
139
+ (0, logger_1.logWarn)("Window object not available (non-browser environment)");
61
140
  }
62
141
  }
63
142
  catch (error) {
@@ -69,14 +148,25 @@ class Web3Connector extends eventEmitter_1.EventEmitter {
69
148
  */
70
149
  setupEventListeners() {
71
150
  if (this.provider) {
151
+ // Listen for network changes through ethers provider
72
152
  this.provider.on("network", (newNetwork, oldNetwork) => {
73
153
  this.emit("chainChanged", newNetwork);
74
154
  });
75
- // Listen for account changes
76
- if (window.ethereum?.on) {
77
- window.ethereum.on("accountsChanged", (accounts) => {
78
- this.emit("accountsChanged", accounts);
79
- });
155
+ // Listen for account changes through the detected provider
156
+ try {
157
+ const ethereumProvider = this.getAvailableEthereumProvider();
158
+ if (ethereumProvider?.on) {
159
+ ethereumProvider.on("accountsChanged", (accounts) => {
160
+ this.emit("accountsChanged", accounts);
161
+ });
162
+ // Also listen for chainChanged events directly
163
+ ethereumProvider.on("chainChanged", (chainId) => {
164
+ this.emit("chainChanged", { chainId });
165
+ });
166
+ }
167
+ }
168
+ catch (error) {
169
+ (0, logger_1.logWarn)("Failed to setup account change listeners", error);
80
170
  }
81
171
  }
82
172
  }
@@ -145,21 +235,40 @@ class Web3Connector extends eventEmitter_1.EventEmitter {
145
235
  throw new Error("MetaMask is not available. Please install MetaMask extension.");
146
236
  }
147
237
  }
238
+ // First check if we can get the provider
239
+ const ethereumProvider = this.getAvailableEthereumProvider();
240
+ if (!ethereumProvider) {
241
+ throw new Error("No compatible Ethereum provider found");
242
+ }
148
243
  // Richiedi esplicitamente l'accesso all'account MetaMask
149
244
  (0, logger_1.logDebug)("Requesting account access...");
150
245
  let accounts = [];
151
- if (window.ethereum) {
152
- try {
153
- accounts = await window.ethereum.request({
154
- method: "eth_requestAccounts",
155
- });
156
- (0, logger_1.logDebug)(`Accounts requested successfully: ${accounts.length} accounts returned`);
246
+ // Try multiple methods of requesting accounts for compatibility
247
+ try {
248
+ // Try the provider we found first
249
+ accounts = await ethereumProvider.request({
250
+ method: "eth_requestAccounts",
251
+ });
252
+ }
253
+ catch (requestError) {
254
+ (0, logger_1.logWarn)("First account request failed, trying window.ethereum:", requestError);
255
+ // Fallback to window.ethereum if available and different
256
+ if (window.ethereum && window.ethereum !== ethereumProvider) {
257
+ try {
258
+ accounts = await window.ethereum.request({
259
+ method: "eth_requestAccounts",
260
+ });
261
+ }
262
+ catch (fallbackError) {
263
+ (0, logger_1.logError)("All account request methods failed", fallbackError);
264
+ throw new Error("User denied account access");
265
+ }
157
266
  }
158
- catch (requestError) {
159
- (0, logger_1.logError)("Error requesting MetaMask accounts:", requestError);
267
+ else {
160
268
  throw new Error("User denied account access");
161
269
  }
162
270
  }
271
+ (0, logger_1.logDebug)(`Accounts requested successfully: ${accounts.length} accounts returned`);
163
272
  if (!accounts || accounts.length === 0) {
164
273
  (0, logger_1.logDebug)("No accounts found, trying to get signer...");
165
274
  }
@@ -170,20 +279,22 @@ class Web3Connector extends eventEmitter_1.EventEmitter {
170
279
  const address = await signer.getAddress();
171
280
  if (!address) {
172
281
  (0, logger_1.logError)("No address returned from signer");
173
- throw new Error("No accounts found in MetaMask");
282
+ continue;
174
283
  }
175
- (0, logger_1.logDebug)(`Signer address obtained: ${address}`);
176
- const metamaskUsername = `${address.toLowerCase()}`;
177
- // Emetti evento connesso
284
+ (0, logger_1.logDebug)(`Successfully connected to MetaMask with address: ${address}`);
178
285
  this.emit("connected", { address });
179
- (0, logger_1.logDebug)(`MetaMask connected successfully with address: ${address}`);
180
- return { success: true, address, username: metamaskUsername };
286
+ return {
287
+ success: true,
288
+ address,
289
+ message: "Successfully connected to MetaMask",
290
+ };
181
291
  }
182
292
  catch (error) {
183
- (0, logger_1.logError)(`Error in connection attempt ${attempt}:`, error);
184
- if (attempt === this.config.maxRetries)
293
+ (0, logger_1.logError)(`Attempt ${attempt} failed:`, error);
294
+ if (attempt === this.config.maxRetries) {
185
295
  throw error;
186
- (0, logger_1.logDebug)(`Retrying in ${this.config.retryDelay}ms...`);
296
+ }
297
+ // Wait before retrying
187
298
  await new Promise((resolve) => setTimeout(resolve, this.config.retryDelay));
188
299
  }
189
300
  }
@@ -262,10 +373,21 @@ class Web3Connector extends eventEmitter_1.EventEmitter {
262
373
  * @returns true if MetaMask is available
263
374
  */
264
375
  static isMetaMaskAvailable() {
265
- const ethereum = window.ethereum;
266
- return (typeof window !== "undefined" &&
267
- typeof ethereum !== "undefined" &&
268
- ethereum?.isMetaMask === true);
376
+ if (typeof window === "undefined")
377
+ return false;
378
+ // Check standard location
379
+ if (window.ethereum?.isMetaMask === true)
380
+ return true;
381
+ // Check alternate locations (for compatibility with multiple wallet extensions)
382
+ const alternateProviders = [
383
+ window.web3?.currentProvider,
384
+ window.metamask,
385
+ ];
386
+ for (const provider of alternateProviders) {
387
+ if (provider?.isMetaMask === true)
388
+ return true;
389
+ }
390
+ return false;
269
391
  }
270
392
  /**
271
393
  * Request signature using BrowserProvider
@@ -326,10 +448,10 @@ class Web3Connector extends eventEmitter_1.EventEmitter {
326
448
  });
327
449
  }
328
450
  /**
329
- * Checks if MetaMask is available
451
+ * Checks if any Ethereum provider is available
330
452
  */
331
453
  isAvailable() {
332
- return typeof window !== "undefined" && !!window.ethereum;
454
+ return (typeof window !== "undefined" && !!this.getAvailableEthereumProvider());
333
455
  }
334
456
  /**
335
457
  * Configure custom JSON-RPC provider