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.
- package/README.md +0 -1
- package/dist/browser/shogun-core.js +1 -1
- package/dist/browser/shogun-core.js.LICENSE.txt +2 -0
- package/dist/browser/shogun-core.light.js +1 -1
- package/dist/browser/shogun-core.vendors.light.js +1 -1
- package/dist/core.js +31 -71
- package/dist/gundb/{instance.js → gunInstance.js} +135 -115
- package/dist/gundb/index.js +3 -20
- package/dist/plugins/index.js +23 -1
- package/dist/plugins/nostr/index.js +1 -0
- package/dist/plugins/nostr/nostrChain.js +128 -0
- package/dist/plugins/nostr/nostrConnector.js +42 -7
- package/dist/plugins/nostr/nostrConnectorPlugin.js +157 -1
- package/dist/plugins/nostr/nostrSigner.js +343 -0
- package/dist/plugins/oauth/index.js +13 -0
- package/dist/plugins/oauth/oauthChain.js +161 -0
- package/dist/plugins/oauth/oauthConnector.js +542 -0
- package/dist/plugins/oauth/oauthPlugin.js +302 -0
- package/dist/plugins/oauth/types.js +2 -0
- package/dist/plugins/web3/index.js +1 -0
- package/dist/plugins/web3/web3Chain.js +77 -2
- package/dist/plugins/web3/web3Connector.js +159 -37
- package/dist/plugins/web3/web3ConnectorPlugin.js +157 -1
- package/dist/plugins/web3/web3Signer.js +268 -0
- package/dist/plugins/webauthn/webauthnChain.js +78 -0
- package/dist/plugins/webauthn/webauthnPlugin.js +154 -1
- package/dist/plugins/webauthn/webauthnSigner.js +318 -0
- package/dist/storage/storage.js +0 -8
- package/dist/types/core.d.ts +10 -34
- package/dist/types/gundb/gun-es/gun-es.d.ts +1 -0
- package/dist/types/gundb/{instance.d.ts → gunInstance.d.ts} +2 -2
- package/dist/types/gundb/index.d.ts +1 -4
- package/dist/types/plugins/index.d.ts +4 -0
- package/dist/types/plugins/nostr/index.d.ts +1 -0
- package/dist/types/plugins/nostr/nostrConnector.d.ts +3 -2
- package/dist/types/plugins/nostr/nostrConnectorPlugin.d.ts +82 -0
- package/dist/types/plugins/nostr/nostrSigner.d.ts +104 -0
- package/dist/types/plugins/oauth/index.d.ts +4 -0
- package/dist/types/plugins/oauth/oauthChain.d.ts +2 -0
- package/dist/types/plugins/oauth/oauthConnector.d.ts +100 -0
- package/dist/types/plugins/oauth/oauthPlugin.d.ts +89 -0
- package/dist/types/plugins/oauth/types.d.ts +106 -0
- package/dist/types/plugins/web3/index.d.ts +1 -0
- package/dist/types/plugins/web3/types.d.ts +1 -0
- package/dist/types/plugins/web3/web3Connector.d.ts +8 -2
- package/dist/types/plugins/web3/web3ConnectorPlugin.d.ts +82 -0
- package/dist/types/plugins/web3/web3Signer.d.ts +93 -0
- package/dist/types/plugins/webauthn/webauthnPlugin.d.ts +81 -0
- package/dist/types/plugins/webauthn/webauthnSigner.d.ts +90 -0
- package/dist/types/shogun.js +1 -28
- package/dist/types/types/events.d.ts +2 -2
- package/dist/types/types/shogun.d.ts +13 -49
- package/package.json +2 -1
- package/dist/browser.js +0 -107
- package/dist/contracts/base.js +0 -152
- package/dist/contracts/entryPoint.js +0 -407
- package/dist/contracts/index.js +0 -47
- package/dist/contracts/registry.js +0 -259
- package/dist/contracts/relay.js +0 -494
- package/dist/contracts/utils.js +0 -582
- package/dist/types/browser.d.ts +0 -27
- package/dist/types/contracts/base.d.ts +0 -82
- package/dist/types/contracts/entryPoint.d.ts +0 -138
- package/dist/types/contracts/index.d.ts +0 -17
- package/dist/types/contracts/registry.d.ts +0 -97
- package/dist/types/contracts/relay.d.ts +0 -165
- 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;
|
|
@@ -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"
|
|
38
|
+
if (typeof window !== "undefined") {
|
|
38
39
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
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"
|
|
56
|
-
|
|
57
|
-
|
|
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
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
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
|
-
|
|
282
|
+
continue;
|
|
174
283
|
}
|
|
175
|
-
(0, logger_1.logDebug)(`
|
|
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
|
-
|
|
180
|
-
|
|
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)(`
|
|
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
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
|
451
|
+
* Checks if any Ethereum provider is available
|
|
330
452
|
*/
|
|
331
453
|
isAvailable() {
|
|
332
|
-
return typeof window !== "undefined" && !!
|
|
454
|
+
return (typeof window !== "undefined" && !!this.getAvailableEthereumProvider());
|
|
333
455
|
}
|
|
334
456
|
/**
|
|
335
457
|
* Configure custom JSON-RPC provider
|