shogun-core 3.0.4 → 3.0.5

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 (95) hide show
  1. package/dist/browser/shogun-core.js +92134 -0
  2. package/dist/browser/shogun-core.js.map +1 -0
  3. package/dist/config/simplified-config.js +230 -0
  4. package/dist/core.js +338 -0
  5. package/dist/gundb/crypto.js +268 -0
  6. package/dist/gundb/db.js +1833 -0
  7. package/dist/gundb/derive.js +229 -0
  8. package/dist/gundb/errors.js +66 -0
  9. package/dist/gundb/index.js +6 -0
  10. package/dist/gundb/restricted-put.js +81 -0
  11. package/dist/gundb/rxjs.js +445 -0
  12. package/dist/gundb/simple-api.js +438 -0
  13. package/dist/gundb/types.js +4 -0
  14. package/dist/index.js +16 -0
  15. package/dist/interfaces/common.js +1 -0
  16. package/dist/interfaces/events.js +36 -0
  17. package/dist/interfaces/plugin.js +1 -0
  18. package/dist/interfaces/shogun.js +34 -0
  19. package/dist/managers/AuthManager.js +225 -0
  20. package/dist/managers/CoreInitializer.js +240 -0
  21. package/dist/managers/EventManager.js +67 -0
  22. package/dist/managers/PluginManager.js +296 -0
  23. package/dist/migration-test.js +91 -0
  24. package/dist/plugins/base.js +47 -0
  25. package/dist/plugins/index.js +15 -0
  26. package/dist/plugins/nostr/index.js +4 -0
  27. package/dist/plugins/nostr/nostrConnector.js +413 -0
  28. package/dist/plugins/nostr/nostrConnectorPlugin.js +446 -0
  29. package/dist/plugins/nostr/nostrSigner.js +313 -0
  30. package/dist/plugins/nostr/types.js +1 -0
  31. package/dist/plugins/oauth/index.js +3 -0
  32. package/dist/plugins/oauth/oauthConnector.js +753 -0
  33. package/dist/plugins/oauth/oauthPlugin.js +396 -0
  34. package/dist/plugins/oauth/types.js +1 -0
  35. package/dist/plugins/web3/index.js +4 -0
  36. package/dist/plugins/web3/types.js +1 -0
  37. package/dist/plugins/web3/web3Connector.js +528 -0
  38. package/dist/plugins/web3/web3ConnectorPlugin.js +448 -0
  39. package/dist/plugins/web3/web3Signer.js +308 -0
  40. package/dist/plugins/webauthn/index.js +3 -0
  41. package/dist/plugins/webauthn/types.js +11 -0
  42. package/dist/plugins/webauthn/webauthn.js +478 -0
  43. package/dist/plugins/webauthn/webauthnPlugin.js +398 -0
  44. package/dist/plugins/webauthn/webauthnSigner.js +304 -0
  45. package/dist/storage/storage.js +147 -0
  46. package/dist/types/config/simplified-config.d.ts +114 -0
  47. package/dist/types/core.d.ts +305 -0
  48. package/dist/types/gundb/crypto.d.ts +95 -0
  49. package/dist/types/gundb/db.d.ts +404 -0
  50. package/dist/types/gundb/derive.d.ts +21 -0
  51. package/dist/types/gundb/errors.d.ts +42 -0
  52. package/dist/types/gundb/index.d.ts +3 -0
  53. package/dist/types/gundb/restricted-put.d.ts +15 -0
  54. package/dist/types/gundb/rxjs.d.ts +110 -0
  55. package/dist/types/gundb/simple-api.d.ts +90 -0
  56. package/dist/types/gundb/types.d.ts +264 -0
  57. package/dist/types/index.d.ts +14 -0
  58. package/dist/types/interfaces/common.d.ts +85 -0
  59. package/dist/types/interfaces/events.d.ts +131 -0
  60. package/dist/types/interfaces/plugin.d.ts +162 -0
  61. package/dist/types/interfaces/shogun.d.ts +215 -0
  62. package/dist/types/managers/AuthManager.d.ts +72 -0
  63. package/dist/types/managers/CoreInitializer.d.ts +40 -0
  64. package/dist/types/managers/EventManager.d.ts +49 -0
  65. package/dist/types/managers/PluginManager.d.ts +145 -0
  66. package/dist/types/migration-test.d.ts +16 -0
  67. package/dist/types/plugins/base.d.ts +35 -0
  68. package/dist/types/plugins/index.d.ts +14 -0
  69. package/dist/types/plugins/nostr/index.d.ts +4 -0
  70. package/dist/types/plugins/nostr/nostrConnector.d.ts +119 -0
  71. package/dist/types/plugins/nostr/nostrConnectorPlugin.d.ts +163 -0
  72. package/dist/types/plugins/nostr/nostrSigner.d.ts +105 -0
  73. package/dist/types/plugins/nostr/types.d.ts +122 -0
  74. package/dist/types/plugins/oauth/index.d.ts +3 -0
  75. package/dist/types/plugins/oauth/oauthConnector.d.ts +110 -0
  76. package/dist/types/plugins/oauth/oauthPlugin.d.ts +91 -0
  77. package/dist/types/plugins/oauth/types.d.ts +114 -0
  78. package/dist/types/plugins/web3/index.d.ts +4 -0
  79. package/dist/types/plugins/web3/types.d.ts +107 -0
  80. package/dist/types/plugins/web3/web3Connector.d.ts +129 -0
  81. package/dist/types/plugins/web3/web3ConnectorPlugin.d.ts +160 -0
  82. package/dist/types/plugins/web3/web3Signer.d.ts +114 -0
  83. package/dist/types/plugins/webauthn/index.d.ts +3 -0
  84. package/dist/types/plugins/webauthn/types.d.ts +162 -0
  85. package/dist/types/plugins/webauthn/webauthn.d.ts +129 -0
  86. package/dist/types/plugins/webauthn/webauthnPlugin.d.ts +158 -0
  87. package/dist/types/plugins/webauthn/webauthnSigner.d.ts +91 -0
  88. package/dist/types/storage/storage.d.ts +50 -0
  89. package/dist/types/utils/errorHandler.d.ts +119 -0
  90. package/dist/types/utils/eventEmitter.d.ts +39 -0
  91. package/dist/types/utils/validation.d.ts +27 -0
  92. package/dist/utils/errorHandler.js +241 -0
  93. package/dist/utils/eventEmitter.js +76 -0
  94. package/dist/utils/validation.js +72 -0
  95. package/package.json +1 -1
@@ -0,0 +1,313 @@
1
+ import { NostrConnector } from "./nostrConnector";
2
+ import derive from "../../gundb/derive";
3
+ import { ethers } from "ethers";
4
+ /**
5
+ * Nostr Signer - Provides oneshot signing functionality
6
+ * Similar to webauthn.js but for Nostr/Bitcoin wallets
7
+ * CONSISTENT with normal Nostr approach
8
+ */
9
+ export class NostrSigner {
10
+ nostrConnector;
11
+ credentials = new Map();
12
+ MESSAGE_TO_SIGN = "I Love Shogun!"; // Same as normal approach
13
+ constructor(nostrConnector) {
14
+ this.nostrConnector = nostrConnector || new NostrConnector();
15
+ }
16
+ /**
17
+ * Creates a new Nostr signing credential
18
+ * CONSISTENT with normal Nostr approach
19
+ */
20
+ async createSigningCredential(address) {
21
+ try {
22
+ // Validate address (same validation as normal approach)
23
+ const validAddress = this.validateAddress(address);
24
+ // Generate signature using the SAME approach as normal Nostr
25
+ const signature = await this.generateDeterministicSignature(validAddress);
26
+ // Generate credentials using the SAME logic as normal approach
27
+ const username = `${validAddress.toLowerCase()}`;
28
+ const password = await this.generatePassword(signature);
29
+ const signingCredential = {
30
+ address: validAddress,
31
+ signature,
32
+ message: this.MESSAGE_TO_SIGN,
33
+ username,
34
+ password, // This ensures consistency with normal approach
35
+ };
36
+ // Store credential for later use
37
+ this.credentials.set(validAddress.toLowerCase(), signingCredential);
38
+ return signingCredential;
39
+ }
40
+ catch (error) {
41
+ console.error("Error creating Nostr signing credential:", error);
42
+ throw new Error(`Failed to create Nostr signing credential: ${error.message}`);
43
+ }
44
+ }
45
+ /**
46
+ * Validates address using the same logic as NostrConnector
47
+ */
48
+ validateAddress(address) {
49
+ if (!address) {
50
+ throw new Error("Address not provided");
51
+ }
52
+ try {
53
+ const normalizedAddress = String(address).trim();
54
+ // Basic validation for Bitcoin addresses and Nostr pubkeys (same as normal approach)
55
+ if (!/^(npub1|[0-9a-f]{64}|bc1|[13])[a-zA-HJ-NP-Z0-9]{25,59}$/.test(normalizedAddress)) {
56
+ // More lenient validation for Nostr addresses
57
+ if (normalizedAddress.length < 10) {
58
+ throw new Error("Invalid Nostr/Bitcoin address format");
59
+ }
60
+ }
61
+ return normalizedAddress;
62
+ }
63
+ catch (error) {
64
+ throw new Error("Invalid Nostr/Bitcoin address provided");
65
+ }
66
+ }
67
+ /**
68
+ * Generate deterministic signature using the SAME approach as NostrConnector
69
+ */
70
+ async generateDeterministicSignature(address) {
71
+ // Create a deterministic signature based on the address and a fixed message
72
+ // This ensures the same credentials are generated each time for the same address
73
+ // SAME LOGIC as NostrConnector.generateDeterministicSignature
74
+ const baseString = `${address}_${this.MESSAGE_TO_SIGN}_shogun_deterministic`;
75
+ // Simple hash function to create a deterministic signature
76
+ let hash = "";
77
+ let runningValue = 0;
78
+ for (let i = 0; i < baseString.length; i++) {
79
+ const charCode = baseString.charCodeAt(i);
80
+ runningValue = (runningValue * 31 + charCode) & 0xffffffff;
81
+ if (i % 4 === 3) {
82
+ hash += runningValue.toString(16).padStart(8, "0");
83
+ }
84
+ }
85
+ // Ensure we have exactly 128 characters (64 bytes in hex)
86
+ while (hash.length < 128) {
87
+ runningValue = (runningValue * 31 + hash.length) & 0xffffffff;
88
+ hash += runningValue.toString(16).padStart(8, "0");
89
+ }
90
+ // Ensure the result is exactly 128 characters and contains only valid hex characters
91
+ let deterministicSignature = hash.substring(0, 128);
92
+ // Double-check that it's a valid hex string
93
+ deterministicSignature = deterministicSignature
94
+ .toLowerCase()
95
+ .replace(/[^0-9a-f]/g, "0");
96
+ // Ensure it's exactly 128 characters
97
+ if (deterministicSignature.length < 128) {
98
+ deterministicSignature = deterministicSignature.padEnd(128, "0");
99
+ }
100
+ else if (deterministicSignature.length > 128) {
101
+ deterministicSignature = deterministicSignature.substring(0, 128);
102
+ }
103
+ return deterministicSignature;
104
+ }
105
+ /**
106
+ * Generate password using the SAME approach as NostrConnector
107
+ */
108
+ async generatePassword(signature) {
109
+ if (!signature) {
110
+ throw new Error("Invalid signature");
111
+ }
112
+ try {
113
+ // SAME LOGIC as NostrConnector.generatePassword
114
+ const normalizedSig = signature.toLowerCase().replace(/[^a-f0-9]/g, "");
115
+ const passwordHash = ethers.sha256(ethers.toUtf8Bytes(normalizedSig));
116
+ return passwordHash;
117
+ }
118
+ catch (error) {
119
+ console.error("Error generating password:", error);
120
+ throw new Error("Failed to generate password from signature");
121
+ }
122
+ }
123
+ /**
124
+ * Creates an authenticator function compatible with SEA.sign
125
+ * This is the key function that makes it work like webauthn.js but for Nostr
126
+ */
127
+ createAuthenticator(address) {
128
+ const credential = this.credentials.get(address.toLowerCase());
129
+ if (!credential) {
130
+ throw new Error(`Credential for address ${address} not found`);
131
+ }
132
+ return async (data) => {
133
+ try {
134
+ // Verify the user by requesting a new signature for the data
135
+ // In a real implementation, this would use the Nostr extension
136
+ const dataToSign = JSON.stringify(data);
137
+ // For now, create a deterministic signature based on the data and credential
138
+ const signature = await this.signData(dataToSign, credential);
139
+ return signature;
140
+ }
141
+ catch (error) {
142
+ console.error("Nostr authentication error:", error);
143
+ throw error;
144
+ }
145
+ };
146
+ }
147
+ /**
148
+ * Sign data using the credential
149
+ */
150
+ async signData(data, credential) {
151
+ // Create a deterministic signature for the data
152
+ const signatureBase = `${credential.signature}_${data}`;
153
+ return this.generateDeterministicSignature(signatureBase);
154
+ }
155
+ /**
156
+ * Creates a derived key pair from Nostr credential
157
+ * CONSISTENT with normal approach: uses password as seed
158
+ */
159
+ async createDerivedKeyPair(address, extra) {
160
+ const credential = this.credentials.get(address.toLowerCase());
161
+ if (!credential) {
162
+ throw new Error(`Credential for address ${address} not found`);
163
+ }
164
+ try {
165
+ // CONSISTENCY: Use the same approach as normal Nostr
166
+ // Use password as seed (same as normal approach)
167
+ const derivedKeys = await derive(credential.password, // This is the key consistency point!
168
+ extra, { includeP256: true });
169
+ return {
170
+ pub: derivedKeys.pub,
171
+ priv: derivedKeys.priv,
172
+ epub: derivedKeys.epub,
173
+ epriv: derivedKeys.epriv,
174
+ };
175
+ }
176
+ catch (error) {
177
+ console.error("Error deriving keys from Nostr credential:", error);
178
+ throw error;
179
+ }
180
+ }
181
+ /**
182
+ * Creates a Gun user from Nostr credential
183
+ * This ensures the SAME user is created as with normal approach
184
+ * FIX: Use derived pair instead of username/password for GunDB auth
185
+ */
186
+ async createGunUser(address, gunInstance) {
187
+ const credential = this.credentials.get(address.toLowerCase());
188
+ if (!credential) {
189
+ throw new Error(`Credential for address ${address} not found`);
190
+ }
191
+ try {
192
+ // FIX: Use derived pair for GunDB authentication instead of username/password
193
+ const derivedPair = await this.createDerivedKeyPair(address);
194
+ return new Promise((resolve) => {
195
+ // Use the derived pair directly for GunDB auth
196
+ gunInstance.user().create(derivedPair, (ack) => {
197
+ if (ack.err) {
198
+ // Try to login if user already exists
199
+ gunInstance.user().auth(derivedPair, (authAck) => {
200
+ if (authAck.err) {
201
+ resolve({ success: false, error: authAck.err });
202
+ }
203
+ else {
204
+ const userPub = authAck.pub;
205
+ // Update credential with Gun user pub
206
+ credential.gunUserPub = userPub;
207
+ this.credentials.set(address.toLowerCase(), credential);
208
+ resolve({ success: true, userPub });
209
+ }
210
+ });
211
+ }
212
+ else {
213
+ // User created, now login
214
+ gunInstance.user().auth(derivedPair, (authAck) => {
215
+ if (authAck.err) {
216
+ resolve({ success: false, error: authAck.err });
217
+ }
218
+ else {
219
+ const userPub = authAck.pub;
220
+ // Update credential with Gun user pub
221
+ credential.gunUserPub = userPub;
222
+ this.credentials.set(address.toLowerCase(), credential);
223
+ resolve({ success: true, userPub });
224
+ }
225
+ });
226
+ }
227
+ });
228
+ });
229
+ }
230
+ catch (error) {
231
+ console.error("Error creating Gun user:", error);
232
+ return { success: false, error: error.message };
233
+ }
234
+ }
235
+ /**
236
+ * Signs data using Nostr + derived keys
237
+ * This provides a hybrid approach: Nostr for user verification + derived keys for actual signing
238
+ * CONSISTENT with normal approach
239
+ */
240
+ async signWithDerivedKeys(data, address, extra) {
241
+ try {
242
+ // First, verify user with Nostr
243
+ const authenticator = this.createAuthenticator(address);
244
+ await authenticator(data); // This verifies the user
245
+ // Then use derived keys for actual signing (CONSISTENT approach)
246
+ const keyPair = await this.createDerivedKeyPair(address, extra);
247
+ // Create signature using the same approach as SEA
248
+ const message = JSON.stringify(data);
249
+ // Use a simple signing approach (in production, would use proper crypto)
250
+ const signature = await this.generateDeterministicSignature(`${keyPair.priv}_${message}`);
251
+ // Format like SEA signature
252
+ const seaSignature = {
253
+ m: message,
254
+ s: signature,
255
+ };
256
+ return "SEA" + JSON.stringify(seaSignature);
257
+ }
258
+ catch (error) {
259
+ console.error("Error signing with derived keys:", error);
260
+ throw error;
261
+ }
262
+ }
263
+ /**
264
+ * Get the Gun user public key for a credential
265
+ * This allows checking if the same user would be created
266
+ */
267
+ getGunUserPub(address) {
268
+ const credential = this.credentials.get(address.toLowerCase());
269
+ return credential?.gunUserPub;
270
+ }
271
+ /**
272
+ * Get the password (for consistency checking)
273
+ */
274
+ getPassword(address) {
275
+ const credential = this.credentials.get(address.toLowerCase());
276
+ return credential?.password;
277
+ }
278
+ /**
279
+ * Check if this credential would create the same Gun user as normal approach
280
+ */
281
+ async verifyConsistency(address, expectedUserPub) {
282
+ const credential = this.credentials.get(address.toLowerCase());
283
+ if (!credential) {
284
+ return { consistent: false };
285
+ }
286
+ // The derived keys should be the same as normal approach
287
+ const derivedKeys = await this.createDerivedKeyPair(address);
288
+ return {
289
+ consistent: expectedUserPub ? derivedKeys.pub === expectedUserPub : true,
290
+ actualUserPub: derivedKeys.pub,
291
+ expectedUserPub,
292
+ };
293
+ }
294
+ /**
295
+ * Get credential by address
296
+ */
297
+ getCredential(address) {
298
+ return this.credentials.get(address.toLowerCase());
299
+ }
300
+ /**
301
+ * List all stored credentials
302
+ */
303
+ listCredentials() {
304
+ return Array.from(this.credentials.values());
305
+ }
306
+ /**
307
+ * Remove a credential
308
+ */
309
+ removeCredential(address) {
310
+ return this.credentials.delete(address.toLowerCase());
311
+ }
312
+ }
313
+ export default NostrSigner;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ // OAuth plugin exports
2
+ export { OAuthConnector } from "./oauthConnector";
3
+ export { OAuthPlugin } from "./oauthPlugin";