w3pk 0.4.0 → 0.4.1
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 +181 -22
- package/dist/index.d.mts +45 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
WebAuthn SDK for passwordless authentication, encrypted Ethereum wallets, and privacy-preserving stealth addresses.
|
|
4
4
|
|
|
5
|
-
Live demo: **https://d2u.w3hc.org/
|
|
5
|
+
Live demo: **https://d2u.w3hc.org/voting**
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -72,6 +72,12 @@ await w3pk.generateWallet()
|
|
|
72
72
|
// Check if wallet exists for current user
|
|
73
73
|
await w3pk.hasWallet()
|
|
74
74
|
// Returns: boolean
|
|
75
|
+
|
|
76
|
+
// Derive HD wallet at specific index (requires authentication)
|
|
77
|
+
await w3pk.deriveWallet(0) // First address (default)
|
|
78
|
+
await w3pk.deriveWallet(1) // Second address
|
|
79
|
+
await w3pk.deriveWallet(5) // Sixth address
|
|
80
|
+
// Returns: { address: string, privateKey: string }
|
|
75
81
|
```
|
|
76
82
|
|
|
77
83
|
#### Authentication
|
|
@@ -107,11 +113,39 @@ await w3pk.signMessage(message: string)
|
|
|
107
113
|
### Properties
|
|
108
114
|
|
|
109
115
|
```typescript
|
|
110
|
-
w3pk.isAuthenticated // boolean
|
|
111
|
-
w3pk.user // UserInfo | null
|
|
112
|
-
w3pk.version // string
|
|
113
|
-
w3pk.isBrowserEnvironment // boolean
|
|
114
|
-
w3pk.stealth // StealthAddressModule | null
|
|
116
|
+
w3pk.isAuthenticated // boolean - Current authentication state
|
|
117
|
+
w3pk.user // UserInfo | null - Current user data
|
|
118
|
+
w3pk.version // string - SDK version
|
|
119
|
+
w3pk.isBrowserEnvironment // boolean - Browser environment detection
|
|
120
|
+
w3pk.stealth // StealthAddressModule | null - Stealth address module
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Error Handling
|
|
124
|
+
|
|
125
|
+
The SDK provides specific error types for better error handling:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import {
|
|
129
|
+
Web3PasskeyError,
|
|
130
|
+
AuthenticationError,
|
|
131
|
+
RegistrationError,
|
|
132
|
+
WalletError,
|
|
133
|
+
CryptoError,
|
|
134
|
+
StorageError,
|
|
135
|
+
ApiError
|
|
136
|
+
} from 'w3pk'
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
await w3pk.register({ username: 'alice' })
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (error instanceof AuthenticationError) {
|
|
142
|
+
console.error('WebAuthn authentication failed:', error.message)
|
|
143
|
+
} else if (error instanceof WalletError) {
|
|
144
|
+
console.error('Wallet operation failed:', error.message)
|
|
145
|
+
} else if (error instanceof ApiError) {
|
|
146
|
+
console.error('Backend API error:', error.message)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
115
149
|
```
|
|
116
150
|
|
|
117
151
|
### Stealth Address API
|
|
@@ -133,6 +167,26 @@ canControlStealthAddress(viewingKey, ephemeralPublicKey, targetAddress)
|
|
|
133
167
|
// Returns: boolean
|
|
134
168
|
```
|
|
135
169
|
|
|
170
|
+
### Utility Functions
|
|
171
|
+
|
|
172
|
+
For direct wallet operations without SDK authentication:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
import { generateBIP39Wallet, createWalletFromMnemonic, deriveWalletFromMnemonic } from 'w3pk'
|
|
176
|
+
|
|
177
|
+
// Generate new BIP39 wallet
|
|
178
|
+
const wallet = generateBIP39Wallet()
|
|
179
|
+
// Returns: { address: string, mnemonic: string }
|
|
180
|
+
|
|
181
|
+
// Create ethers wallet from mnemonic
|
|
182
|
+
const ethersWallet = createWalletFromMnemonic(mnemonic)
|
|
183
|
+
// Returns: ethers.HDNodeWallet
|
|
184
|
+
|
|
185
|
+
// Derive HD wallet at specific index
|
|
186
|
+
const derived = deriveWalletFromMnemonic(mnemonic, 2)
|
|
187
|
+
// Returns: { address: string, privateKey: string }
|
|
188
|
+
```
|
|
189
|
+
|
|
136
190
|
### Types
|
|
137
191
|
|
|
138
192
|
```typescript
|
|
@@ -166,6 +220,49 @@ interface StealthAddressResult {
|
|
|
166
220
|
}
|
|
167
221
|
```
|
|
168
222
|
|
|
223
|
+
## HD Wallet Example
|
|
224
|
+
|
|
225
|
+
Access multiple addresses from a single mnemonic for advanced wallet management:
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { createWeb3Passkey } from 'w3pk'
|
|
229
|
+
import { ethers } from 'ethers'
|
|
230
|
+
|
|
231
|
+
// Initialize and authenticate
|
|
232
|
+
const w3pk = createWeb3Passkey({
|
|
233
|
+
apiBaseUrl: 'https://webauthn.w3hc.org'
|
|
234
|
+
})
|
|
235
|
+
await w3pk.login()
|
|
236
|
+
|
|
237
|
+
// Generate multiple wallet addresses from the same mnemonic
|
|
238
|
+
const mainWallet = await w3pk.deriveWallet(0) // Main wallet
|
|
239
|
+
const savingsWallet = await w3pk.deriveWallet(1) // Savings wallet
|
|
240
|
+
const tradingWallet = await w3pk.deriveWallet(2) // Trading wallet
|
|
241
|
+
|
|
242
|
+
console.log('Main address:', mainWallet.address)
|
|
243
|
+
console.log('Savings address:', savingsWallet.address)
|
|
244
|
+
console.log('Trading address:', tradingWallet.address)
|
|
245
|
+
|
|
246
|
+
// Use private keys directly with ethers.js
|
|
247
|
+
const provider = new ethers.JsonRpcProvider('https://ethereum-sepolia-rpc.publicnode.com')
|
|
248
|
+
const mainSigner = new ethers.Wallet(mainWallet.privateKey, provider)
|
|
249
|
+
const savingsSigner = new ethers.Wallet(savingsWallet.privateKey, provider)
|
|
250
|
+
|
|
251
|
+
// Send transactions from different derived addresses
|
|
252
|
+
const tx1 = await mainSigner.sendTransaction({
|
|
253
|
+
to: savingsWallet.address,
|
|
254
|
+
value: ethers.parseEther('0.1')
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
const tx2 = await savingsSigner.sendTransaction({
|
|
258
|
+
to: tradingWallet.address,
|
|
259
|
+
value: ethers.parseEther('0.05')
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
console.log('Transfer to savings:', tx1.hash)
|
|
263
|
+
console.log('Transfer to trading:', tx2.hash)
|
|
264
|
+
```
|
|
265
|
+
|
|
169
266
|
## Stealth Address Example
|
|
170
267
|
|
|
171
268
|
```typescript
|
|
@@ -281,20 +378,49 @@ pnpm start:dev
|
|
|
281
378
|
|
|
282
379
|
## Security
|
|
283
380
|
|
|
284
|
-
|
|
285
|
-
- ✅
|
|
286
|
-
- ✅
|
|
287
|
-
- ✅
|
|
288
|
-
- ✅
|
|
289
|
-
- ✅
|
|
290
|
-
|
|
381
|
+
### Encryption & Storage
|
|
382
|
+
- ✅ **Client-side AES-GCM-256 encryption** - All sensitive data encrypted in browser
|
|
383
|
+
- ✅ **PBKDF2 key derivation** (100,000 iterations) from WebAuthn credentials
|
|
384
|
+
- ✅ **Private keys never leave device** - Zero server-side key storage
|
|
385
|
+
- ✅ **IndexedDB encrypted storage** - Separate encrypted storage per device
|
|
386
|
+
- ✅ **WebAuthn/FIDO2 authentication** - Hardware-backed biometric security
|
|
387
|
+
|
|
388
|
+
### Wallet Standards
|
|
389
|
+
- ✅ **BIP39 standard mnemonic** - Industry-standard 12-word recovery phrase
|
|
390
|
+
- ✅ **BIP44 HD derivation** - Standard path `m/44'/60'/0'/0/{index}` for Ethereum
|
|
391
|
+
- ✅ **Deterministic addresses** - Same mnemonic always produces same addresses
|
|
392
|
+
- ✅ **Multiple address support** - Derive unlimited addresses from one mnemonic
|
|
393
|
+
|
|
394
|
+
### Privacy Features
|
|
395
|
+
- ✅ **Stealth addresses** - Unlinkable transaction privacy (optional)
|
|
396
|
+
- ✅ **Zero-knowledge proofs** - Privacy-preserving stealth address generation
|
|
397
|
+
- ✅ **Ephemeral keys** - Fresh keys for each stealth transaction
|
|
398
|
+
- ✅ **Unlinkable transactions** - No on-chain connection between stealth addresses
|
|
399
|
+
|
|
400
|
+
### Security Notes & Best Practices
|
|
401
|
+
|
|
402
|
+
#### ⚠️ Critical Security Requirements
|
|
403
|
+
- **MUST backup mnemonic** - The 12-word phrase is shown only once during registration
|
|
404
|
+
- **MUST secure mnemonic** - Store it offline, never share or store digitally
|
|
405
|
+
- **Cannot recover without mnemonic** - Lost device + lost mnemonic = lost wallet forever
|
|
406
|
+
|
|
407
|
+
#### 🔒 Device Security
|
|
408
|
+
- Your wallet is protected by device biometrics (fingerprint, Face ID, Windows Hello)
|
|
409
|
+
- Each device stores its own encrypted copy of the wallet
|
|
410
|
+
- WebAuthn credentials are bound to your specific device hardware
|
|
411
|
+
- Fresh authentication required for sensitive operations (signing, key derivation)
|
|
291
412
|
|
|
292
|
-
|
|
413
|
+
#### 🌐 Network Security
|
|
414
|
+
- SDK works entirely client-side - no private keys sent to servers
|
|
415
|
+
- Backend only stores WebAuthn public key credentials (no wallet data)
|
|
416
|
+
- All wallet encryption/decryption happens in your browser
|
|
417
|
+
- Compatible with any Ethereum-compatible network
|
|
293
418
|
|
|
294
|
-
|
|
295
|
-
-
|
|
296
|
-
-
|
|
297
|
-
-
|
|
419
|
+
#### 💡 Operational Security Tips
|
|
420
|
+
- Test wallet functionality with small amounts first
|
|
421
|
+
- Verify signatures on Etherscan before sending large transactions
|
|
422
|
+
- Use different derived addresses for different purposes (privacy by design)
|
|
423
|
+
- Consider using stealth addresses for maximum transaction privacy
|
|
298
424
|
|
|
299
425
|
## React Integration
|
|
300
426
|
|
|
@@ -357,14 +483,47 @@ function App() {
|
|
|
357
483
|
# Install dependencies
|
|
358
484
|
pnpm install
|
|
359
485
|
|
|
360
|
-
# Build
|
|
486
|
+
# Build for production
|
|
361
487
|
pnpm build
|
|
362
488
|
|
|
363
|
-
#
|
|
489
|
+
# Development mode with watch
|
|
364
490
|
pnpm dev
|
|
365
491
|
|
|
366
|
-
#
|
|
367
|
-
pnpm test
|
|
492
|
+
# Run tests
|
|
493
|
+
pnpm test # Run basic + comprehensive test suite
|
|
494
|
+
pnpm test:basic # Run basic functionality tests only
|
|
495
|
+
pnpm test:comprehensive # Run full 23-test comprehensive suite
|
|
496
|
+
|
|
497
|
+
# Publish to npm
|
|
498
|
+
pnpm prepublishOnly # Builds before publishing
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### Test Coverage
|
|
502
|
+
|
|
503
|
+
The SDK includes a comprehensive test suite with **23 test cases** covering:
|
|
504
|
+
|
|
505
|
+
- ✅ **Core SDK functionality** - Constructor, configuration, environment detection
|
|
506
|
+
- ✅ **Wallet generation** - BIP39/BIP44 compliance, HD derivation, consistency
|
|
507
|
+
- ✅ **Encryption/decryption** - AES-GCM-256, key derivation, data roundtrips
|
|
508
|
+
- ✅ **Storage operations** - IndexedDB CRUD, multiple wallets, cleanup
|
|
509
|
+
- ✅ **Message signing** - Signature generation, address verification
|
|
510
|
+
- ✅ **HD wallet derivation** - Multi-index support, validation, consistency
|
|
511
|
+
- ✅ **Error handling** - Graceful failure scenarios
|
|
512
|
+
- ✅ **Integration testing** - End-to-end workflows
|
|
513
|
+
|
|
514
|
+
### Architecture
|
|
515
|
+
|
|
516
|
+
```
|
|
517
|
+
w3pk/
|
|
518
|
+
├── src/
|
|
519
|
+
│ ├── core/ # Main SDK class and configuration
|
|
520
|
+
│ ├── wallet/ # Wallet generation, signing, storage
|
|
521
|
+
│ ├── auth/ # WebAuthn authentication flows
|
|
522
|
+
│ ├── stealth/ # Privacy-preserving stealth addresses
|
|
523
|
+
│ ├── utils/ # API client, validation utilities
|
|
524
|
+
│ └── types/ # TypeScript type definitions
|
|
525
|
+
├── test/ # Comprehensive test suite
|
|
526
|
+
└── dist/ # Built output (CJS + ESM + types)
|
|
368
527
|
```
|
|
369
528
|
|
|
370
529
|
## Browser Compatibility
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Stealth address cryptography for privacy-preserving transactions
|
|
3
5
|
*/
|
|
@@ -163,6 +165,17 @@ declare class Web3Passkey {
|
|
|
163
165
|
* Check if wallet exists for current user
|
|
164
166
|
*/
|
|
165
167
|
hasWallet(): Promise<boolean>;
|
|
168
|
+
/**
|
|
169
|
+
* Derive HD wallet address and private key at specific index
|
|
170
|
+
* Requires authentication to access encrypted mnemonic
|
|
171
|
+
*
|
|
172
|
+
* @param index HD derivation index (default: 0)
|
|
173
|
+
* @returns Object with address and privateKey
|
|
174
|
+
*/
|
|
175
|
+
deriveWallet(index?: number): Promise<{
|
|
176
|
+
address: string;
|
|
177
|
+
privateKey: string;
|
|
178
|
+
}>;
|
|
166
179
|
/**
|
|
167
180
|
* Register a new user with WebAuthn
|
|
168
181
|
* Handles the complete registration flow internally
|
|
@@ -218,6 +231,37 @@ declare class Web3Passkey {
|
|
|
218
231
|
get stealth(): StealthAddressModule | null;
|
|
219
232
|
}
|
|
220
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Wallet-related types
|
|
236
|
+
*/
|
|
237
|
+
interface WalletData {
|
|
238
|
+
address: string;
|
|
239
|
+
mnemonic: string;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* BIP39 wallet generation
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Generates a new BIP39 wallet with HD derivation
|
|
248
|
+
* Uses BIP44 path: m/44'/60'/0'/0/0 for Ethereum
|
|
249
|
+
*/
|
|
250
|
+
declare function generateBIP39Wallet(): WalletData;
|
|
251
|
+
/**
|
|
252
|
+
* Creates wallet from mnemonic phrase
|
|
253
|
+
* Uses BIP44 path: m/44'/60'/0'/0/0
|
|
254
|
+
*/
|
|
255
|
+
declare function createWalletFromMnemonic(mnemonic: string): ethers.HDNodeWallet;
|
|
256
|
+
/**
|
|
257
|
+
* Derives HD wallet address and private key at specific index
|
|
258
|
+
* Uses BIP44 path: m/44'/60'/0'/0/{index}
|
|
259
|
+
*/
|
|
260
|
+
declare function deriveWalletFromMnemonic(mnemonic: string, index?: number): {
|
|
261
|
+
address: string;
|
|
262
|
+
privateKey: string;
|
|
263
|
+
};
|
|
264
|
+
|
|
221
265
|
/**
|
|
222
266
|
* w3pk - Web3 Passkey SDK
|
|
223
267
|
* WebAuthn SDK for passwordless authentication and encrypted wallet management
|
|
@@ -225,4 +269,4 @@ declare class Web3Passkey {
|
|
|
225
269
|
|
|
226
270
|
declare function createWeb3Passkey(config: Web3PasskeyConfig): Web3Passkey;
|
|
227
271
|
|
|
228
|
-
export { ApiError, AuthenticationError, CryptoError, RegistrationError, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, type UserInfo, WalletError, type WalletInfo, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, canControlStealthAddress, createWeb3Passkey, createWeb3Passkey as default };
|
|
272
|
+
export { ApiError, AuthenticationError, CryptoError, RegistrationError, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, type UserInfo, WalletError, type WalletInfo, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, canControlStealthAddress, createWalletFromMnemonic, createWeb3Passkey, createWeb3Passkey as default, deriveWalletFromMnemonic, generateBIP39Wallet };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Stealth address cryptography for privacy-preserving transactions
|
|
3
5
|
*/
|
|
@@ -163,6 +165,17 @@ declare class Web3Passkey {
|
|
|
163
165
|
* Check if wallet exists for current user
|
|
164
166
|
*/
|
|
165
167
|
hasWallet(): Promise<boolean>;
|
|
168
|
+
/**
|
|
169
|
+
* Derive HD wallet address and private key at specific index
|
|
170
|
+
* Requires authentication to access encrypted mnemonic
|
|
171
|
+
*
|
|
172
|
+
* @param index HD derivation index (default: 0)
|
|
173
|
+
* @returns Object with address and privateKey
|
|
174
|
+
*/
|
|
175
|
+
deriveWallet(index?: number): Promise<{
|
|
176
|
+
address: string;
|
|
177
|
+
privateKey: string;
|
|
178
|
+
}>;
|
|
166
179
|
/**
|
|
167
180
|
* Register a new user with WebAuthn
|
|
168
181
|
* Handles the complete registration flow internally
|
|
@@ -218,6 +231,37 @@ declare class Web3Passkey {
|
|
|
218
231
|
get stealth(): StealthAddressModule | null;
|
|
219
232
|
}
|
|
220
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Wallet-related types
|
|
236
|
+
*/
|
|
237
|
+
interface WalletData {
|
|
238
|
+
address: string;
|
|
239
|
+
mnemonic: string;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* BIP39 wallet generation
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Generates a new BIP39 wallet with HD derivation
|
|
248
|
+
* Uses BIP44 path: m/44'/60'/0'/0/0 for Ethereum
|
|
249
|
+
*/
|
|
250
|
+
declare function generateBIP39Wallet(): WalletData;
|
|
251
|
+
/**
|
|
252
|
+
* Creates wallet from mnemonic phrase
|
|
253
|
+
* Uses BIP44 path: m/44'/60'/0'/0/0
|
|
254
|
+
*/
|
|
255
|
+
declare function createWalletFromMnemonic(mnemonic: string): ethers.HDNodeWallet;
|
|
256
|
+
/**
|
|
257
|
+
* Derives HD wallet address and private key at specific index
|
|
258
|
+
* Uses BIP44 path: m/44'/60'/0'/0/{index}
|
|
259
|
+
*/
|
|
260
|
+
declare function deriveWalletFromMnemonic(mnemonic: string, index?: number): {
|
|
261
|
+
address: string;
|
|
262
|
+
privateKey: string;
|
|
263
|
+
};
|
|
264
|
+
|
|
221
265
|
/**
|
|
222
266
|
* w3pk - Web3 Passkey SDK
|
|
223
267
|
* WebAuthn SDK for passwordless authentication and encrypted wallet management
|
|
@@ -225,4 +269,4 @@ declare class Web3Passkey {
|
|
|
225
269
|
|
|
226
270
|
declare function createWeb3Passkey(config: Web3PasskeyConfig): Web3Passkey;
|
|
227
271
|
|
|
228
|
-
export { ApiError, AuthenticationError, CryptoError, RegistrationError, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, type UserInfo, WalletError, type WalletInfo, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, canControlStealthAddress, createWeb3Passkey, createWeb3Passkey as default };
|
|
272
|
+
export { ApiError, AuthenticationError, CryptoError, RegistrationError, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, type UserInfo, WalletError, type WalletInfo, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, canControlStealthAddress, createWalletFromMnemonic, createWeb3Passkey, createWeb3Passkey as default, deriveWalletFromMnemonic, generateBIP39Wallet };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var K=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var $=Object.prototype.hasOwnProperty;var N=(n,e)=>()=>(n&&(e=n(n=0)),e);var M=(n,e)=>{for(var t in e)K(n,t,{get:e[t],enumerable:!0})},J=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of H(e))!$.call(n,s)&&s!==t&&K(n,s,{get:()=>e[s],enumerable:!(r=G(e,s))||r.enumerable});return n};var V=n=>J(K({},"__esModule",{value:!0}),n);var a,f,S,p,c,h,d,m=N(()=>{"use strict";a=class extends Error{constructor(t,r,s){super(t);this.code=r;this.originalError=s;this.name="Web3PasskeyError"}},f=class extends a{constructor(e,t){super(e,"AUTHENTICATION_ERROR",t),this.name="AuthenticationError"}},S=class extends a{constructor(e,t){super(e,"REGISTRATION_ERROR",t),this.name="RegistrationError"}},p=class extends a{constructor(e,t){super(e,"WALLET_ERROR",t),this.name="WalletError"}},c=class extends a{constructor(e,t){super(e,"CRYPTO_ERROR",t),this.name="CryptoError"}},h=class extends a{constructor(e,t){super(e,"STORAGE_ERROR",t),this.name="StorageError"}},d=class extends a{constructor(t,r,s){super(t,"API_ERROR",s);this.statusCode=r;this.name="ApiError"}}});var q={};M(q,{canControlStealthAddress:()=>T,deriveStealthKeys:()=>x,generateStealthAddress:()=>Q});function x(n){try{let e=l.ethers.HDNodeWallet.fromPhrase(n,void 0,"m/44'/60'/1'/0/0"),t=l.ethers.HDNodeWallet.fromPhrase(n,void 0,"m/44'/60'/1'/0/1");return{metaAddress:_(e.signingKey.publicKey,t.signingKey.publicKey),viewingKey:e.privateKey,spendingKey:t.privateKey}}catch(e){throw new c("Failed to derive stealth keys",e)}}function Q(n){try{let e=l.ethers.Wallet.createRandom(),t=l.ethers.solidityPackedKeccak256(["bytes","address"],[e.signingKey.publicKey,n]),r=new l.ethers.Wallet(t);return{stealthAddress:r.address,stealthPrivkey:r.privateKey,ephemeralPubkey:e.signingKey.publicKey}}catch(e){throw new c("Failed to generate stealth address",e)}}function T(n,e,t,r){try{let s=new l.ethers.Wallet(n),o=new l.ethers.Wallet(e),i=_(s.signingKey.publicKey,o.signingKey.publicKey),g=l.ethers.solidityPackedKeccak256(["bytes","address"],[t,i]);return new l.ethers.Wallet(g).address.toLowerCase()===r.toLowerCase()}catch{return!1}}function _(n,e){let t=l.ethers.solidityPackedKeccak256(["bytes","bytes"],[n,e]);return l.ethers.getAddress("0x"+t.slice(26))}var l,k=N(()=>{"use strict";l=require("ethers");m()});var Z={};M(Z,{ApiError:()=>d,AuthenticationError:()=>f,CryptoError:()=>c,RegistrationError:()=>S,StealthAddressModule:()=>w,StorageError:()=>h,WalletError:()=>p,Web3Passkey:()=>y,Web3PasskeyError:()=>a,canControlStealthAddress:()=>T,createWeb3Passkey:()=>L,default:()=>X});module.exports=V(Z);var v=require("@simplewebauthn/browser");m();var E=class{constructor(e,t=3e4){this.baseUrl=e;this.timeout=t}async fetchWithTimeout(e,t){let r=new AbortController,s=setTimeout(()=>r.abort(),this.timeout);try{let o=await fetch(e,{...t,signal:r.signal});return clearTimeout(s),o}catch(o){throw clearTimeout(s),o}}async post(e,t,r){try{let s=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:"POST",headers:{"Content-Type":"application/json",...r?.headers},body:JSON.stringify(t),...r});if(!s.ok)throw new d(`API request failed: ${s.statusText}`,s.status);return await s.json()}catch(s){throw s instanceof d?s:new d("Network request failed",void 0,s)}}async get(e,t){try{let r=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:"GET",headers:{"Content-Type":"application/json",...t?.headers},...t});if(!r.ok)throw new d(`API request failed: ${r.statusText}`,r.status);return await r.json()}catch(r){throw r instanceof d?r:new d("Network request failed",void 0,r)}}};m();var Y="Web3PasskeyWallet",z=1,u="wallets",P=class{constructor(){this.db=null}async init(){return new Promise((e,t)=>{let r=indexedDB.open(Y,z);r.onerror=()=>t(new h("Failed to open database",r.error)),r.onsuccess=()=>{this.db=r.result,e()},r.onupgradeneeded=()=>{let s=r.result;s.objectStoreNames.contains(u)||s.createObjectStore(u,{keyPath:"ethereumAddress"})}})}async store(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([u],"readwrite").objectStore(u).put(e);i.onerror=()=>r(new h("Failed to store wallet data",i.error)),i.onsuccess=()=>t()})}async retrieve(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([u],"readonly").objectStore(u).get(e);i.onerror=()=>r(new h("Failed to retrieve wallet data",i.error)),i.onsuccess=()=>t(i.result||null)})}async delete(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([u],"readwrite").objectStore(u).delete(e);i.onerror=()=>r(new h("Failed to delete wallet data",i.error)),i.onsuccess=()=>t()})}async clear(){return this.db||await this.init(),new Promise((e,t)=>{let o=this.db.transaction([u],"readwrite").objectStore(u).clear();o.onerror=()=>t(new h("Failed to clear wallet data",o.error)),o.onsuccess=()=>e()})}};m();var W=require("ethers");m();function U(){try{let n=W.ethers.Wallet.createRandom().mnemonic;if(!n)throw new Error("Failed to generate mnemonic");let e=n.phrase;return{address:W.ethers.HDNodeWallet.fromPhrase(e,void 0,"m/44'/60'/0'/0/0").address,mnemonic:e}}catch(n){throw new p("Wallet generation failed",n)}}function B(n){try{if(!n||n.trim().split(/\s+/).length<12)throw new Error("Invalid mnemonic: must be at least 12 words");return W.ethers.HDNodeWallet.fromPhrase(n.trim(),void 0,"m/44'/60'/0'/0/0")}catch(e){throw new p(`Wallet creation failed: ${e instanceof Error?e.message:"Invalid mnemonic"}`,e)}}m();async function A(n,e){try{let t=new TextEncoder().encode(n+e),r=await crypto.subtle.importKey("raw",t,{name:"PBKDF2"},!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:new TextEncoder().encode("webauthn-wallet-salt-w3pk"),iterations:1e5,hash:"SHA-256"},r,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new c("Failed to derive encryption key",t)}}async function O(n,e){try{let t=crypto.getRandomValues(new Uint8Array(12)),r=new TextEncoder().encode(n),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:t},e,r),o=new Uint8Array(t.length+s.byteLength);return o.set(t),o.set(new Uint8Array(s),t.length),btoa(String.fromCharCode(...o))}catch(t){throw new c("Failed to encrypt data",t)}}async function R(n,e){try{if(!n||n.length<16)throw new Error("Invalid encrypted data: too small");let t=new Uint8Array(atob(n).split("").map(i=>i.charCodeAt(0)));if(t.length<12)throw new Error("Invalid encrypted data: missing IV");let r=t.slice(0,12),s=t.slice(12);if(s.length===0)throw new Error("Invalid encrypted data: no content");let o=await crypto.subtle.decrypt({name:"AES-GCM",iv:r},e,s);return new TextDecoder().decode(o)}catch(t){throw new c(`Data decryption failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}var C=class{constructor(e){this.storage=e}async signMessage(e,t,r,s){try{let o=await this.storage.retrieve(e);if(!o)throw new Error("No wallet found for this address");let i=await A(r,s),g=await R(o.encryptedMnemonic,i),b=B(g);if(b.address.toLowerCase()!==e.toLowerCase())throw new Error("Wallet address mismatch");return await b.signMessage(t)}catch(o){throw new p("Failed to sign message",o)}}async hasWallet(e){return await this.storage.retrieve(e)!==null}};m();k();var w=class{constructor(e,t){this.config=e,this.getMnemonic=t}async generateStealthAddress(){try{let e=await this.getMnemonic();if(!e)throw new f("Not authenticated. Please login first.");let t=x(e),{generateStealthAddress:r}=await Promise.resolve().then(()=>(k(),q)),s=r(t.metaAddress);return{stealthAddress:s.stealthAddress,stealthPrivateKey:s.stealthPrivkey,ephemeralPublicKey:s.ephemeralPubkey}}catch(e){throw new a("Failed to generate stealth address","STEALTH_GENERATION_ERROR",e)}}async getKeys(){try{let e=await this.getMnemonic();if(!e)throw new f("Not authenticated. Please login first.");return x(e)}catch(e){throw new a("Failed to get stealth keys","STEALTH_KEYS_ERROR",e)}}get isAvailable(){return!0}};var I={timeout:3e4,debug:!1};var y=class{constructor(e){this.currentUser=null;this.isAuthenticatedState=!1;this.stealthAddresses=null;this.isBrowser=typeof window<"u"&&typeof localStorage<"u",this.config={...I,...e,timeout:e.timeout??I.timeout,debug:e.debug??I.debug},this.apiClient=new E(this.config.apiBaseUrl,this.config.timeout),this.walletStorage=new P,this.walletSigner=new C(this.walletStorage),e.stealthAddresses&&(this.stealthAddresses=new w(e.stealthAddresses,this.getMnemonic.bind(this))),this.isBrowser?(this.walletStorage.init().catch(t=>{this.config.debug&&console.error("Failed to initialize wallet storage:",t)}),this.loadAuthState()):this.config.debug&&console.warn("w3pk: Running in non-browser environment, some features disabled")}loadAuthState(){if(this.isBrowser)try{let e=localStorage.getItem("w3pk_user"),t=localStorage.getItem("w3pk_authenticated");e&&t==="true"&&(this.currentUser=JSON.parse(e),this.isAuthenticatedState=!0,this.notifyAuthStateChange(!0,this.currentUser??void 0))}catch(e){this.config.debug&&console.error("Failed to load auth state:",e),this.clearAuthState()}}saveAuthState(e){if(!this.isBrowser){console.warn("w3pk: Cannot save auth state in non-browser environment");return}try{localStorage.setItem("w3pk_user",JSON.stringify(e)),localStorage.setItem("w3pk_authenticated","true"),this.currentUser=e,this.isAuthenticatedState=!0,this.notifyAuthStateChange(!0,e)}catch(t){this.config.debug&&console.error("Failed to save auth state:",t)}}clearAuthState(){if(this.isBrowser){try{localStorage.removeItem("w3pk_user"),localStorage.removeItem("w3pk_authenticated")}catch(e){this.config.debug&&console.error("Failed to clear auth state:",e)}this.currentUser=null,this.isAuthenticatedState=!1,this.notifyAuthStateChange(!1)}}notifyAuthStateChange(e,t){this.config.onAuthStateChanged&&this.config.onAuthStateChanged(e,t)}createUserInfo(e,t){return{id:t,username:e,displayName:e,ethereumAddress:t}}async getMnemonic(){if(!this.isBrowser||!this.currentUser)return null;try{let e=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!e)return null;let t=await A(e.credentialId,e.challenge);return await R(e.encryptedMnemonic,t)}catch(e){return this.config.debug&&console.error("Failed to get mnemonic:",e),null}}async generateWallet(){try{let e=U();return this.config.debug&&console.log("Wallet generated:",e.address),e}catch(e){throw this.config.onError&&this.config.onError(e),e}}async hasWallet(){if(!this.isBrowser)return console.warn("w3pk: Wallet storage not available in non-browser environment"),!1;if(!this.currentUser)return!1;try{return await this.walletSigner.hasWallet(this.currentUser.ethereumAddress)}catch(e){return this.config.debug&&console.error("Failed to check wallet existence:",e),!1}}async register(e){if(!this.isBrowser)throw new Error("Registration requires browser environment with WebAuthn support");try{let{username:t}=e,{ethereumAddress:r,mnemonic:s}=e;if(!r||!s){let F=U();r=F.address,s=F.mnemonic}let o=await this.apiClient.post("/webauthn/register/begin",{username:t,ethereumAddress:r});if(!o.success||!o.data)throw new Error("Failed to get registration options from server");let i=o.data.options||o.data,g=await(0,v.startRegistration)(i),b=await A(g.id,i.challenge),D=await O(s,b);if(await this.walletStorage.store({ethereumAddress:r,encryptedMnemonic:D,credentialId:g.id,challenge:i.challenge,createdAt:Date.now()}),!(await this.apiClient.post("/webauthn/register/complete",{ethereumAddress:r,response:g})).success)throw new Error("Registration verification failed");let j=this.createUserInfo(t,r);return this.saveAuthState(j),this.config.debug&&console.log("Registration successful for:",r),{ethereumAddress:r,mnemonic:e.mnemonic?void 0:s}}catch(t){throw this.config.onError&&this.config.onError(t),t}}async login(){if(!this.isBrowser)throw new Error("Authentication requires browser environment with WebAuthn support");try{let e=await this.apiClient.post("/webauthn/authenticate/usernameless/begin",{});if(!e.success||!e.data)throw new Error("Failed to get usernameless authentication options from server");let t=e.data.options||e.data,r=await(0,v.startAuthentication)(t),s=await this.apiClient.post("/webauthn/authenticate/usernameless/complete",{response:r});if(!s.success)throw new Error("Usernameless authentication verification failed");let o=s.data?.user;if(!o)throw new Error("No user data received from server");let i=this.createUserInfo(o.username,o.ethereumAddress||o.id);return this.saveAuthState(i),this.config.debug&&console.log("Usernameless authentication successful for:",i.ethereumAddress),{verified:!0,user:i}}catch(e){throw this.config.onError&&this.config.onError(e),e}}logout(){this.clearAuthState(),this.config.debug&&console.log("User logged out")}async signMessage(e){if(!this.isBrowser)throw new Error("Message signing requires browser environment");if(!this.currentUser)throw new Error("Not authenticated");try{let t=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!t)throw new Error("No wallet found on this device. Please register to create a new wallet.");this.config.debug&&console.log("Requesting WebAuthn authentication for signing...");let r=await this.apiClient.post("/webauthn/authenticate/usernameless/begin",{});if(!r.success||!r.data)throw new Error("Failed to begin authentication for signing");let s=r.data.options||r.data,o=await(0,v.startAuthentication)(s);if(!(await this.apiClient.post("/webauthn/authenticate/usernameless/complete",{response:o})).success)throw new Error("Authentication verification failed for signing");let g=await this.walletSigner.signMessage(this.currentUser.ethereumAddress,e,t.credentialId,t.challenge);return this.config.debug&&console.log("Message signed successfully"),g}catch(t){throw this.config.onError&&this.config.onError(t),t}}get isAuthenticated(){return this.isAuthenticatedState}get user(){return this.currentUser}get version(){return"0.4.0"}get isBrowserEnvironment(){return this.isBrowser}get stealth(){return this.stealthAddresses}};m();k();function L(n){return new y(n)}var X=L;
|
|
1
|
+
"use strict";var T=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var B=(s,e)=>()=>(s&&(e=s(s=0)),e);var O=(s,e)=>{for(var t in e)T(s,t,{get:e[t],enumerable:!0})},V=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of G(e))!J.call(s,n)&&n!==t&&T(s,n,{get:()=>e[n],enumerable:!(r=j(e,n))||r.enumerable});return s};var Y=s=>V(T({},"__esModule",{value:!0}),s);var a,f,P,h,c,u,d,p=B(()=>{"use strict";a=class extends Error{constructor(t,r,n){super(t);this.code=r;this.originalError=n;this.name="Web3PasskeyError"}},f=class extends a{constructor(e,t){super(e,"AUTHENTICATION_ERROR",t),this.name="AuthenticationError"}},P=class extends a{constructor(e,t){super(e,"REGISTRATION_ERROR",t),this.name="RegistrationError"}},h=class extends a{constructor(e,t){super(e,"WALLET_ERROR",t),this.name="WalletError"}},c=class extends a{constructor(e,t){super(e,"CRYPTO_ERROR",t),this.name="CryptoError"}},u=class extends a{constructor(e,t){super(e,"STORAGE_ERROR",t),this.name="StorageError"}},d=class extends a{constructor(t,r,n){super(t,"API_ERROR",n);this.statusCode=r;this.name="ApiError"}}});var H={};O(H,{canControlStealthAddress:()=>F,deriveStealthKeys:()=>K,generateStealthAddress:()=>X});function K(s){try{let e=l.ethers.HDNodeWallet.fromPhrase(s,void 0,"m/44'/60'/1'/0/0"),t=l.ethers.HDNodeWallet.fromPhrase(s,void 0,"m/44'/60'/1'/0/1");return{metaAddress:q(e.signingKey.publicKey,t.signingKey.publicKey),viewingKey:e.privateKey,spendingKey:t.privateKey}}catch(e){throw new c("Failed to derive stealth keys",e)}}function X(s){try{let e=l.ethers.Wallet.createRandom(),t=l.ethers.solidityPackedKeccak256(["bytes","address"],[e.signingKey.publicKey,s]),r=new l.ethers.Wallet(t);return{stealthAddress:r.address,stealthPrivkey:r.privateKey,ephemeralPubkey:e.signingKey.publicKey}}catch(e){throw new c("Failed to generate stealth address",e)}}function F(s,e,t,r){try{let n=new l.ethers.Wallet(s),o=new l.ethers.Wallet(e),i=q(n.signingKey.publicKey,o.signingKey.publicKey),m=l.ethers.solidityPackedKeccak256(["bytes","address"],[t,i]);return new l.ethers.Wallet(m).address.toLowerCase()===r.toLowerCase()}catch{return!1}}function q(s,e){let t=l.ethers.solidityPackedKeccak256(["bytes","bytes"],[s,e]);return l.ethers.getAddress("0x"+t.slice(26))}var l,U=B(()=>{"use strict";l=require("ethers");p()});var ee={};O(ee,{ApiError:()=>d,AuthenticationError:()=>f,CryptoError:()=>c,RegistrationError:()=>P,StealthAddressModule:()=>w,StorageError:()=>u,WalletError:()=>h,Web3Passkey:()=>y,Web3PasskeyError:()=>a,canControlStealthAddress:()=>F,createWalletFromMnemonic:()=>C,createWeb3Passkey:()=>L,default:()=>Z,deriveWalletFromMnemonic:()=>x,generateBIP39Wallet:()=>A});module.exports=Y(ee);var E=require("@simplewebauthn/browser");p();var W=class{constructor(e,t=3e4){this.baseUrl=e;this.timeout=t}async fetchWithTimeout(e,t){let r=new AbortController,n=setTimeout(()=>r.abort(),this.timeout);try{let o=await fetch(e,{...t,signal:r.signal});return clearTimeout(n),o}catch(o){throw clearTimeout(n),o}}async post(e,t,r){try{let n=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:"POST",headers:{"Content-Type":"application/json",...r?.headers},body:JSON.stringify(t),...r});if(!n.ok)throw new d(`API request failed: ${n.statusText}`,n.status);return await n.json()}catch(n){throw n instanceof d?n:new d("Network request failed",void 0,n)}}async get(e,t){try{let r=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:"GET",headers:{"Content-Type":"application/json",...t?.headers},...t});if(!r.ok)throw new d(`API request failed: ${r.statusText}`,r.status);return await r.json()}catch(r){throw r instanceof d?r:new d("Network request failed",void 0,r)}}};p();var z="Web3PasskeyWallet",Q=1,g="wallets",R=class{constructor(){this.db=null}async init(){return new Promise((e,t)=>{let r=indexedDB.open(z,Q);r.onerror=()=>t(new u("Failed to open database",r.error)),r.onsuccess=()=>{this.db=r.result,e()},r.onupgradeneeded=()=>{let n=r.result;n.objectStoreNames.contains(g)||n.createObjectStore(g,{keyPath:"ethereumAddress"})}})}async store(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([g],"readwrite").objectStore(g).put(e);i.onerror=()=>r(new u("Failed to store wallet data",i.error)),i.onsuccess=()=>t()})}async retrieve(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([g],"readonly").objectStore(g).get(e);i.onerror=()=>r(new u("Failed to retrieve wallet data",i.error)),i.onsuccess=()=>t(i.result||null)})}async delete(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([g],"readwrite").objectStore(g).delete(e);i.onerror=()=>r(new u("Failed to delete wallet data",i.error)),i.onsuccess=()=>t()})}async clear(){return this.db||await this.init(),new Promise((e,t)=>{let o=this.db.transaction([g],"readwrite").objectStore(g).clear();o.onerror=()=>t(new u("Failed to clear wallet data",o.error)),o.onsuccess=()=>e()})}};p();var v=require("ethers");p();function A(){try{let s=v.ethers.Wallet.createRandom().mnemonic;if(!s)throw new Error("Failed to generate mnemonic");let e=s.phrase;return{address:v.ethers.HDNodeWallet.fromPhrase(e,void 0,"m/44'/60'/0'/0/0").address,mnemonic:e}}catch(s){throw new h("Wallet generation failed",s)}}function C(s){try{if(!s||s.trim().split(/\s+/).length<12)throw new Error("Invalid mnemonic: must be at least 12 words");return v.ethers.HDNodeWallet.fromPhrase(s.trim(),void 0,"m/44'/60'/0'/0/0")}catch(e){throw new h(`Wallet creation failed: ${e instanceof Error?e.message:"Invalid mnemonic"}`,e)}}function x(s,e=0){try{if(!s||s.trim().split(/\s+/).length<12)throw new Error("Invalid mnemonic: must be at least 12 words");if(e<0||!Number.isInteger(e))throw new Error("Index must be a non-negative integer");let t=`m/44'/60'/0'/0/${e}`,r=v.ethers.HDNodeWallet.fromPhrase(s.trim(),void 0,t);return{address:r.address,privateKey:r.privateKey}}catch(t){throw new h(`HD wallet derivation failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}p();async function S(s,e){try{let t=new TextEncoder().encode(s+e),r=await crypto.subtle.importKey("raw",t,{name:"PBKDF2"},!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:new TextEncoder().encode("webauthn-wallet-salt-w3pk"),iterations:1e5,hash:"SHA-256"},r,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new c("Failed to derive encryption key",t)}}async function _(s,e){try{let t=crypto.getRandomValues(new Uint8Array(12)),r=new TextEncoder().encode(s),n=await crypto.subtle.encrypt({name:"AES-GCM",iv:t},e,r),o=new Uint8Array(t.length+n.byteLength);return o.set(t),o.set(new Uint8Array(n),t.length),btoa(String.fromCharCode(...o))}catch(t){throw new c("Failed to encrypt data",t)}}async function I(s,e){try{if(!s||s.length<16)throw new Error("Invalid encrypted data: too small");let t=new Uint8Array(atob(s).split("").map(i=>i.charCodeAt(0)));if(t.length<12)throw new Error("Invalid encrypted data: missing IV");let r=t.slice(0,12),n=t.slice(12);if(n.length===0)throw new Error("Invalid encrypted data: no content");let o=await crypto.subtle.decrypt({name:"AES-GCM",iv:r},e,n);return new TextDecoder().decode(o)}catch(t){throw new c(`Data decryption failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}var k=class{constructor(e){this.storage=e}async signMessage(e,t,r,n){try{let o=await this.storage.retrieve(e);if(!o)throw new Error("No wallet found for this address");let i=await S(r,n),m=await I(o.encryptedMnemonic,i),b=C(m);if(b.address.toLowerCase()!==e.toLowerCase())throw new Error("Wallet address mismatch");return await b.signMessage(t)}catch(o){throw new h("Failed to sign message",o)}}async hasWallet(e){return await this.storage.retrieve(e)!==null}};p();U();var w=class{constructor(e,t){this.config=e,this.getMnemonic=t}async generateStealthAddress(){try{let e=await this.getMnemonic();if(!e)throw new f("Not authenticated. Please login first.");let t=K(e),{generateStealthAddress:r}=await Promise.resolve().then(()=>(U(),H)),n=r(t.metaAddress);return{stealthAddress:n.stealthAddress,stealthPrivateKey:n.stealthPrivkey,ephemeralPublicKey:n.ephemeralPubkey}}catch(e){throw new a("Failed to generate stealth address","STEALTH_GENERATION_ERROR",e)}}async getKeys(){try{let e=await this.getMnemonic();if(!e)throw new f("Not authenticated. Please login first.");return K(e)}catch(e){throw new a("Failed to get stealth keys","STEALTH_KEYS_ERROR",e)}}get isAvailable(){return!0}};var D={timeout:3e4,debug:!1};var y=class{constructor(e){this.currentUser=null;this.isAuthenticatedState=!1;this.stealthAddresses=null;this.isBrowser=typeof window<"u"&&typeof localStorage<"u",this.config={...D,...e,timeout:e.timeout??D.timeout,debug:e.debug??D.debug},this.apiClient=new W(this.config.apiBaseUrl,this.config.timeout),this.walletStorage=new R,this.walletSigner=new k(this.walletStorage),e.stealthAddresses&&(this.stealthAddresses=new w(e.stealthAddresses,this.getMnemonic.bind(this))),this.isBrowser?(this.walletStorage.init().catch(t=>{this.config.debug&&console.error("Failed to initialize wallet storage:",t)}),this.loadAuthState()):this.config.debug&&console.warn("w3pk: Running in non-browser environment, some features disabled")}loadAuthState(){if(this.isBrowser)try{let e=localStorage.getItem("w3pk_user"),t=localStorage.getItem("w3pk_authenticated");e&&t==="true"&&(this.currentUser=JSON.parse(e),this.isAuthenticatedState=!0,this.notifyAuthStateChange(!0,this.currentUser??void 0))}catch(e){this.config.debug&&console.error("Failed to load auth state:",e),this.clearAuthState()}}saveAuthState(e){if(!this.isBrowser){console.warn("w3pk: Cannot save auth state in non-browser environment");return}try{localStorage.setItem("w3pk_user",JSON.stringify(e)),localStorage.setItem("w3pk_authenticated","true"),this.currentUser=e,this.isAuthenticatedState=!0,this.notifyAuthStateChange(!0,e)}catch(t){this.config.debug&&console.error("Failed to save auth state:",t)}}clearAuthState(){if(this.isBrowser){try{localStorage.removeItem("w3pk_user"),localStorage.removeItem("w3pk_authenticated")}catch(e){this.config.debug&&console.error("Failed to clear auth state:",e)}this.currentUser=null,this.isAuthenticatedState=!1,this.notifyAuthStateChange(!1)}}notifyAuthStateChange(e,t){this.config.onAuthStateChanged&&this.config.onAuthStateChanged(e,t)}createUserInfo(e,t){return{id:t,username:e,displayName:e,ethereumAddress:t}}async getMnemonic(){if(!this.isBrowser||!this.currentUser)return null;try{let e=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!e)return null;let t=await S(e.credentialId,e.challenge);return await I(e.encryptedMnemonic,t)}catch(e){return this.config.debug&&console.error("Failed to get mnemonic:",e),null}}async generateWallet(){try{let e=A();return this.config.debug&&console.log("Wallet generated:",e.address),e}catch(e){throw this.config.onError&&this.config.onError(e),e}}async hasWallet(){if(!this.isBrowser)return console.warn("w3pk: Wallet storage not available in non-browser environment"),!1;if(!this.currentUser)return!1;try{return await this.walletSigner.hasWallet(this.currentUser.ethereumAddress)}catch(e){return this.config.debug&&console.error("Failed to check wallet existence:",e),!1}}async deriveWallet(e=0){if(!this.isBrowser)throw new Error("HD wallet derivation requires browser environment");if(!this.currentUser)throw new Error("Not authenticated");try{let t=await this.getMnemonic();if(!t)throw new Error("No wallet found for this user");let r=x(t,e);return this.config.debug&&console.log(`HD wallet derived at index ${e}:`,r.address),r}catch(t){throw this.config.onError&&this.config.onError(t),t}}async register(e){if(!this.isBrowser)throw new Error("Registration requires browser environment with WebAuthn support");try{let{username:t}=e,{ethereumAddress:r,mnemonic:n}=e;if(!r||!n){let N=A();r=N.address,n=N.mnemonic}let o=await this.apiClient.post("/webauthn/register/begin",{username:t,ethereumAddress:r});if(!o.success||!o.data)throw new Error("Failed to get registration options from server");let i=o.data.options||o.data,m=await(0,E.startRegistration)(i),b=await S(m.id,i.challenge),M=await _(n,b);if(await this.walletStorage.store({ethereumAddress:r,encryptedMnemonic:M,credentialId:m.id,challenge:i.challenge,createdAt:Date.now()}),!(await this.apiClient.post("/webauthn/register/complete",{ethereumAddress:r,response:m})).success)throw new Error("Registration verification failed");let $=this.createUserInfo(t,r);return this.saveAuthState($),this.config.debug&&console.log("Registration successful for:",r),{ethereumAddress:r,mnemonic:e.mnemonic?void 0:n}}catch(t){throw this.config.onError&&this.config.onError(t),t}}async login(){if(!this.isBrowser)throw new Error("Authentication requires browser environment with WebAuthn support");try{let e=await this.apiClient.post("/webauthn/authenticate/usernameless/begin",{});if(!e.success||!e.data)throw new Error("Failed to get usernameless authentication options from server");let t=e.data.options||e.data,r=await(0,E.startAuthentication)(t),n=await this.apiClient.post("/webauthn/authenticate/usernameless/complete",{response:r});if(!n.success)throw new Error("Usernameless authentication verification failed");let o=n.data?.user;if(!o)throw new Error("No user data received from server");let i=this.createUserInfo(o.username,o.ethereumAddress||o.id);return this.saveAuthState(i),this.config.debug&&console.log("Usernameless authentication successful for:",i.ethereumAddress),{verified:!0,user:i}}catch(e){throw this.config.onError&&this.config.onError(e),e}}logout(){this.clearAuthState(),this.config.debug&&console.log("User logged out")}async signMessage(e){if(!this.isBrowser)throw new Error("Message signing requires browser environment");if(!this.currentUser)throw new Error("Not authenticated");try{let t=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!t)throw new Error("No wallet found on this device. Please register to create a new wallet.");this.config.debug&&console.log("Requesting WebAuthn authentication for signing...");let r=await this.apiClient.post("/webauthn/authenticate/usernameless/begin",{});if(!r.success||!r.data)throw new Error("Failed to begin authentication for signing");let n=r.data.options||r.data,o=await(0,E.startAuthentication)(n);if(!(await this.apiClient.post("/webauthn/authenticate/usernameless/complete",{response:o})).success)throw new Error("Authentication verification failed for signing");let m=await this.walletSigner.signMessage(this.currentUser.ethereumAddress,e,t.credentialId,t.challenge);return this.config.debug&&console.log("Message signed successfully"),m}catch(t){throw this.config.onError&&this.config.onError(t),t}}get isAuthenticated(){return this.isAuthenticatedState}get user(){return this.currentUser}get version(){return"0.4.1"}get isBrowserEnvironment(){return this.isBrowser}get stealth(){return this.stealthAddresses}};p();U();function L(s){return new y(s)}var Z=L;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/errors.ts","../src/stealth/crypto.ts","../src/index.ts","../src/core/sdk.ts","../src/utils/api.ts","../src/wallet/storage.ts","../src/wallet/signing.ts","../src/wallet/generate.ts","../src/wallet/crypto.ts","../src/stealth/index.ts","../src/core/config.ts"],"sourcesContent":["/**\n * Custom error classes for better error handling\n */\n\nexport class Web3PasskeyError extends Error {\n constructor(\n message: string,\n public code: string,\n public originalError?: unknown\n ) {\n super(message);\n this.name = \"Web3PasskeyError\";\n }\n}\n\nexport class AuthenticationError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"AUTHENTICATION_ERROR\", originalError);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class RegistrationError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"REGISTRATION_ERROR\", originalError);\n this.name = \"RegistrationError\";\n }\n}\n\nexport class WalletError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"WALLET_ERROR\", originalError);\n this.name = \"WalletError\";\n }\n}\n\nexport class CryptoError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"CRYPTO_ERROR\", originalError);\n this.name = \"CryptoError\";\n }\n}\n\nexport class StorageError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"STORAGE_ERROR\", originalError);\n this.name = \"StorageError\";\n }\n}\n\nexport class ApiError extends Web3PasskeyError {\n constructor(\n message: string,\n public statusCode?: number,\n originalError?: unknown\n ) {\n super(message, \"API_ERROR\", originalError);\n this.name = \"ApiError\";\n }\n}\n","/**\n * Stealth address cryptography for privacy-preserving transactions\n */\n\nimport { ethers } from \"ethers\";\nimport { CryptoError } from \"../core/errors\";\n\nexport interface StealthKeys {\n metaAddress: string;\n viewingKey: string;\n spendingKey: string;\n}\n\nexport interface StealthAddressResult {\n stealthAddress: string;\n stealthPrivkey: string;\n ephemeralPubkey: string;\n}\n\n/**\n * Derive stealth keys from w3pk mnemonic using HD paths\n */\nexport function deriveStealthKeys(mnemonic: string): StealthKeys {\n try {\n // Use specific derivation paths for stealth keys\n const viewingWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic,\n undefined,\n \"m/44'/60'/1'/0/0\" // Viewing key path\n );\n\n const spendingWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic,\n undefined,\n \"m/44'/60'/1'/0/1\" // Spending key path\n );\n\n // Meta address is derived from viewing key\n const metaAddress = computeMetaAddress(\n viewingWallet.signingKey.publicKey,\n spendingWallet.signingKey.publicKey\n );\n\n return {\n metaAddress,\n viewingKey: viewingWallet.privateKey,\n spendingKey: spendingWallet.privateKey,\n };\n } catch (error) {\n throw new CryptoError(\"Failed to derive stealth keys\", error);\n }\n}\n\n/**\n * Generate a stealth address using ECDH\n */\nexport function generateStealthAddress(\n metaAddress: string\n): StealthAddressResult {\n try {\n // Generate ephemeral keypair\n const ephemeralWallet = ethers.Wallet.createRandom();\n\n // For simplified implementation, derive stealth address from ephemeral key + meta address\n const stealthSeed = ethers.solidityPackedKeccak256(\n [\"bytes\", \"address\"],\n [ephemeralWallet.signingKey.publicKey, metaAddress]\n );\n\n const stealthWallet = new ethers.Wallet(stealthSeed);\n\n return {\n stealthAddress: stealthWallet.address,\n stealthPrivkey: stealthWallet.privateKey,\n ephemeralPubkey: ephemeralWallet.signingKey.publicKey,\n };\n } catch (error) {\n throw new CryptoError(\"Failed to generate stealth address\", error);\n }\n}\n\n/**\n * Check if a stealth address can be controlled by the stealth keys\n * Useful for scanning and proving ownership of stealth addresses\n */\nexport function canControlStealthAddress(\n viewingKey: string,\n spendingKey: string,\n ephemeralPubkey: string,\n targetAddress: string\n): boolean {\n try {\n // Reconstruct stealth address using both viewing and spending keys\n const viewingWallet = new ethers.Wallet(viewingKey);\n const spendingWallet = new ethers.Wallet(spendingKey);\n \n const metaAddress = computeMetaAddress(\n viewingWallet.signingKey.publicKey,\n spendingWallet.signingKey.publicKey\n );\n\n const stealthSeed = ethers.solidityPackedKeccak256(\n [\"bytes\", \"address\"],\n [ephemeralPubkey, metaAddress]\n );\n\n const derivedWallet = new ethers.Wallet(stealthSeed);\n\n return derivedWallet.address.toLowerCase() === targetAddress.toLowerCase();\n } catch (error) {\n return false;\n }\n}\n\n/**\n * Compute meta address from public keys (simplified)\n */\nfunction computeMetaAddress(\n viewingPubkey: string,\n spendingPubkey: string\n): string {\n const combined = ethers.solidityPackedKeccak256(\n [\"bytes\", \"bytes\"],\n [viewingPubkey, spendingPubkey]\n );\n\n // Take first 20 bytes as address\n return ethers.getAddress(\"0x\" + combined.slice(26));\n}\n","/**\n * w3pk - Web3 Passkey SDK\n * WebAuthn SDK for passwordless authentication and encrypted wallet management\n */\n\nimport { Web3Passkey } from \"./core/sdk\";\nimport type { Web3PasskeyConfig } from \"./core/config\";\n\n// Main factory function\nexport function createWeb3Passkey(config: Web3PasskeyConfig): Web3Passkey {\n return new Web3Passkey(config);\n}\n\n// Export types\nexport type { Web3PasskeyConfig, StealthAddressConfig } from \"./core/config\";\nexport type { UserInfo, WalletInfo } from \"./types\";\nexport type { StealthKeys, StealthAddressResult } from \"./stealth\";\n\n// Export errors for custom error handling\nexport {\n Web3PasskeyError,\n AuthenticationError,\n RegistrationError,\n WalletError,\n CryptoError,\n StorageError,\n ApiError,\n} from \"./core/errors\";\n\n// Export SDK class for advanced usage\nexport { Web3Passkey } from \"./core/sdk\";\n\n// Export stealth address module for advanced usage\nexport { StealthAddressModule } from \"./stealth\";\n\n// Export crypto utilities\nexport { canControlStealthAddress } from \"./stealth/crypto\";\n\n// Default export\nexport default createWeb3Passkey;\n","/**\n * Main Web3Passkey SDK class\n */\n\nimport {\n startRegistration,\n startAuthentication,\n} from \"@simplewebauthn/browser\";\nimport { ApiClient } from \"../utils/api\";\nimport { IndexedDBWalletStorage } from \"../wallet/storage\";\nimport { WalletSigner } from \"../wallet/signing\";\nimport { generateBIP39Wallet } from \"../wallet/generate\";\nimport {\n deriveEncryptionKey,\n encryptData,\n decryptData,\n} from \"../wallet/crypto\";\nimport { StealthAddressModule } from \"../stealth\";\nimport type {\n Web3PasskeyConfig,\n InternalConfig,\n StealthAddressConfig,\n} from \"./config\";\nimport { DEFAULT_CONFIG } from \"./config\";\nimport type { UserInfo, WalletInfo } from \"../types\";\n\nexport interface AuthResult {\n verified: boolean;\n user?: UserInfo;\n}\n\nexport class Web3Passkey {\n private config: InternalConfig;\n private apiClient: ApiClient;\n private walletStorage: IndexedDBWalletStorage;\n private walletSigner: WalletSigner;\n private currentUser: UserInfo | null = null;\n private isAuthenticatedState: boolean = false;\n private isBrowser: boolean;\n private stealthAddresses: StealthAddressModule | null = null;\n\n constructor(config: Web3PasskeyConfig) {\n // Check if running in browser\n this.isBrowser =\n typeof window !== \"undefined\" && typeof localStorage !== \"undefined\";\n\n // Merge with defaults\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n timeout: config.timeout ?? DEFAULT_CONFIG.timeout!,\n debug: config.debug ?? DEFAULT_CONFIG.debug!,\n } as InternalConfig;\n\n // Initialize components\n this.apiClient = new ApiClient(this.config.apiBaseUrl, this.config.timeout);\n this.walletStorage = new IndexedDBWalletStorage();\n this.walletSigner = new WalletSigner(this.walletStorage);\n\n // Initialize stealth addresses if configured\n if (config.stealthAddresses) {\n this.stealthAddresses = new StealthAddressModule(\n config.stealthAddresses,\n this.getMnemonic.bind(this)\n );\n }\n\n // Initialize storage only in browser\n if (this.isBrowser) {\n this.walletStorage.init().catch((error) => {\n if (this.config.debug) {\n console.error(\"Failed to initialize wallet storage:\", error);\n }\n });\n\n // Load persisted auth state\n this.loadAuthState();\n } else if (this.config.debug) {\n console.warn(\n \"w3pk: Running in non-browser environment, some features disabled\"\n );\n }\n }\n\n // ========================================\n // Auth State Management\n // ========================================\n\n private loadAuthState(): void {\n if (!this.isBrowser) return;\n\n try {\n const storedUser = localStorage.getItem(\"w3pk_user\");\n const storedAuth = localStorage.getItem(\"w3pk_authenticated\");\n\n if (storedUser && storedAuth === \"true\") {\n this.currentUser = JSON.parse(storedUser);\n this.isAuthenticatedState = true;\n this.notifyAuthStateChange(true, this.currentUser ?? undefined);\n }\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to load auth state:\", error);\n }\n this.clearAuthState();\n }\n }\n\n private saveAuthState(user: UserInfo): void {\n if (!this.isBrowser) {\n console.warn(\"w3pk: Cannot save auth state in non-browser environment\");\n return;\n }\n\n try {\n localStorage.setItem(\"w3pk_user\", JSON.stringify(user));\n localStorage.setItem(\"w3pk_authenticated\", \"true\");\n this.currentUser = user;\n this.isAuthenticatedState = true;\n this.notifyAuthStateChange(true, user);\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to save auth state:\", error);\n }\n }\n }\n\n private clearAuthState(): void {\n if (!this.isBrowser) return;\n\n try {\n localStorage.removeItem(\"w3pk_user\");\n localStorage.removeItem(\"w3pk_authenticated\");\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to clear auth state:\", error);\n }\n }\n\n this.currentUser = null;\n this.isAuthenticatedState = false;\n this.notifyAuthStateChange(false);\n }\n\n private notifyAuthStateChange(\n isAuthenticated: boolean,\n user?: UserInfo\n ): void {\n if (this.config.onAuthStateChanged) {\n this.config.onAuthStateChanged(isAuthenticated, user);\n }\n }\n\n private createUserInfo(username: string, ethereumAddress: string): UserInfo {\n return {\n id: ethereumAddress,\n username,\n displayName: username,\n ethereumAddress,\n };\n }\n\n /**\n * Get mnemonic for current authenticated user\n * Used by stealth address module\n */\n private async getMnemonic(): Promise<string | null> {\n if (!this.isBrowser || !this.currentUser) {\n return null;\n }\n\n try {\n // Get encrypted wallet data\n const walletData = await this.walletStorage.retrieve(\n this.currentUser.ethereumAddress\n );\n if (!walletData) {\n return null;\n }\n\n // Derive encryption key from stored credentials\n const encryptionKey = await deriveEncryptionKey(\n walletData.credentialId,\n walletData.challenge\n );\n\n // Decrypt mnemonic\n return await decryptData(walletData.encryptedMnemonic, encryptionKey);\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to get mnemonic:\", error);\n }\n return null;\n }\n }\n\n // ========================================\n // Public API - Wallet\n // ========================================\n\n /**\n * Generate a new BIP39 wallet\n * @returns Wallet info with mnemonic (user MUST backup)\n */\n async generateWallet(): Promise<WalletInfo> {\n try {\n const wallet = generateBIP39Wallet();\n\n if (this.config.debug) {\n console.log(\"Wallet generated:\", wallet.address);\n }\n\n return wallet;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Check if wallet exists for current user\n */\n async hasWallet(): Promise<boolean> {\n if (!this.isBrowser) {\n console.warn(\n \"w3pk: Wallet storage not available in non-browser environment\"\n );\n return false;\n }\n\n if (!this.currentUser) {\n return false;\n }\n\n try {\n return await this.walletSigner.hasWallet(\n this.currentUser.ethereumAddress\n );\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to check wallet existence:\", error);\n }\n return false;\n }\n }\n\n // ========================================\n // Public API - Authentication\n // ========================================\n\n /**\n * Register a new user with WebAuthn\n * Handles the complete registration flow internally\n * Automatically generates wallet if not provided\n *\n * @param username Username for the account\n * @param ethereumAddress Optional: Ethereum address (will generate if not provided)\n * @param mnemonic Optional: BIP39 mnemonic (will generate if not provided)\n * @returns Object containing ethereumAddress and mnemonic (only if generated)\n */\n async register(options: {\n username: string;\n ethereumAddress?: string;\n mnemonic?: string;\n }): Promise<{ ethereumAddress: string; mnemonic?: string }> {\n if (!this.isBrowser) {\n throw new Error(\n \"Registration requires browser environment with WebAuthn support\"\n );\n }\n\n try {\n const { username } = options;\n let { ethereumAddress, mnemonic } = options;\n\n // Generate wallet if not provided\n if (!ethereumAddress || !mnemonic) {\n const wallet = generateBIP39Wallet();\n ethereumAddress = wallet.address;\n mnemonic = wallet.mnemonic;\n }\n\n // Step 1: Begin registration - get WebAuthn options from server\n const beginResponse = await this.apiClient.post(\n \"/webauthn/register/begin\",\n {\n username,\n ethereumAddress,\n }\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\"Failed to get registration options from server\");\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 2: Perform WebAuthn registration (browser prompt)\n const credential = await startRegistration(webauthnOptions);\n\n // Step 3: Encrypt mnemonic with WebAuthn-derived key\n const encryptionKey = await deriveEncryptionKey(\n credential.id,\n webauthnOptions.challenge\n );\n const encryptedMnemonic = await encryptData(mnemonic, encryptionKey);\n\n // Step 4: Store encrypted mnemonic in IndexedDB\n await this.walletStorage.store({\n ethereumAddress,\n encryptedMnemonic,\n credentialId: credential.id,\n challenge: webauthnOptions.challenge,\n createdAt: Date.now(),\n });\n\n // Step 5: Complete registration with server\n const completeResponse = await this.apiClient.post(\n \"/webauthn/register/complete\",\n {\n ethereumAddress,\n response: credential,\n }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Registration verification failed\");\n }\n\n // Step 6: Save auth state with displayName\n const user = this.createUserInfo(username, ethereumAddress);\n this.saveAuthState(user);\n\n if (this.config.debug) {\n console.log(\"Registration successful for:\", ethereumAddress);\n }\n\n // Return the wallet info (mnemonic only if we generated it)\n return {\n ethereumAddress,\n mnemonic: options.mnemonic ? undefined : mnemonic,\n };\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Authenticate without username (usernameless flow)\n */\n async login(): Promise<AuthResult> {\n if (!this.isBrowser) {\n throw new Error(\n \"Authentication requires browser environment with WebAuthn support\"\n );\n }\n\n try {\n // Step 1: Begin usernameless authentication\n const beginResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/begin\",\n {}\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\n \"Failed to get usernameless authentication options from server\"\n );\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 2: WebAuthn authentication\n const credential = await startAuthentication(webauthnOptions);\n\n // Step 3: Complete authentication\n const completeResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/complete\",\n { response: credential }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Usernameless authentication verification failed\");\n }\n\n const serverUser = completeResponse.data?.user;\n if (!serverUser) {\n throw new Error(\"No user data received from server\");\n }\n\n // Create UserInfo with displayName\n const user = this.createUserInfo(\n serverUser.username,\n serverUser.ethereumAddress || serverUser.id\n );\n this.saveAuthState(user);\n\n if (this.config.debug) {\n console.log(\n \"Usernameless authentication successful for:\",\n user.ethereumAddress\n );\n }\n\n return {\n verified: true,\n user,\n };\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Logout current user\n */\n logout(): void {\n this.clearAuthState();\n\n if (this.config.debug) {\n console.log(\"User logged out\");\n }\n }\n\n // ========================================\n // Public API - Message Signing\n // ========================================\n\n /**\n * Sign a message with encrypted wallet\n * Handles fresh WebAuthn authentication internally\n *\n * @param message Message to sign\n */\n async signMessage(message: string): Promise<string> {\n if (!this.isBrowser) {\n throw new Error(\"Message signing requires browser environment\");\n }\n\n if (!this.currentUser) {\n throw new Error(\"Not authenticated\");\n }\n\n try {\n // Step 1: Check if wallet exists\n const walletData = await this.walletStorage.retrieve(\n this.currentUser.ethereumAddress\n );\n if (!walletData) {\n throw new Error(\n \"No wallet found on this device. Please register to create a new wallet.\"\n );\n }\n\n // Step 2: Request fresh WebAuthn authentication\n if (this.config.debug) {\n console.log(\"Requesting WebAuthn authentication for signing...\");\n }\n\n const beginResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/begin\",\n {}\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\"Failed to begin authentication for signing\");\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 3: Perform WebAuthn authentication (browser prompt)\n const credential = await startAuthentication(webauthnOptions);\n\n // Step 4: Verify authentication with server\n const completeResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/complete\",\n { response: credential }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Authentication verification failed for signing\");\n }\n\n // Step 5: Use the authenticated credentials to sign\n const signature = await this.walletSigner.signMessage(\n this.currentUser.ethereumAddress,\n message,\n walletData.credentialId,\n walletData.challenge\n );\n\n if (this.config.debug) {\n console.log(\"Message signed successfully\");\n }\n\n return signature;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n // ========================================\n // Public API - Getters\n // ========================================\n\n /**\n * Check if user is authenticated\n */\n get isAuthenticated(): boolean {\n return this.isAuthenticatedState;\n }\n\n /**\n * Get current user info\n */\n get user(): UserInfo | null {\n return this.currentUser;\n }\n\n /**\n * Get SDK version\n */\n get version(): string {\n return \"0.4.0\";\n }\n\n /**\n * Check if running in browser environment\n */\n get isBrowserEnvironment(): boolean {\n return this.isBrowser;\n }\n\n /**\n * Get stealth address module (if configured)\n */\n get stealth(): StealthAddressModule | null {\n return this.stealthAddresses;\n }\n}\n","/**\n * API client for backend communication\n */\n\nimport { ApiError } from \"../core/errors\";\nimport type { ApiResponse } from \"../types\";\n\nexport class ApiClient {\n constructor(private baseUrl: string, private timeout: number = 30000) {}\n\n private async fetchWithTimeout(\n url: string,\n options: RequestInit\n ): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n async post<T = any>(\n endpoint: string,\n body: any,\n options?: RequestInit\n ): Promise<ApiResponse<T>> {\n try {\n const response = await this.fetchWithTimeout(\n `${this.baseUrl}${endpoint}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n body: JSON.stringify(body),\n ...options,\n }\n );\n\n if (!response.ok) {\n throw new ApiError(\n `API request failed: ${response.statusText}`,\n response.status\n );\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n throw new ApiError(\"Network request failed\", undefined, error);\n }\n }\n\n async get<T = any>(\n endpoint: string,\n options?: RequestInit\n ): Promise<ApiResponse<T>> {\n try {\n const response = await this.fetchWithTimeout(\n `${this.baseUrl}${endpoint}`,\n {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n ...options,\n }\n );\n\n if (!response.ok) {\n throw new ApiError(\n `API request failed: ${response.statusText}`,\n response.status\n );\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n throw new ApiError(\"Network request failed\", undefined, error);\n }\n }\n}\n","/**\n * IndexedDB storage for encrypted wallet data\n */\n\nimport { StorageError } from \"../core/errors\";\nimport type { EncryptedWalletData, WalletStorage } from \"./types\";\n\nconst DB_NAME = \"Web3PasskeyWallet\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"wallets\";\n\nexport class IndexedDBWalletStorage implements WalletStorage {\n private db: IDBDatabase | null = null;\n\n async init(): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n\n request.onerror = () =>\n reject(new StorageError(\"Failed to open database\", request.error));\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: \"ethereumAddress\" });\n }\n };\n });\n }\n\n async store(data: EncryptedWalletData): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.put(data);\n request.onerror = () =>\n reject(new StorageError(\"Failed to store wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n\n async retrieve(ethereumAddress: string): Promise<EncryptedWalletData | null> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readonly\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.get(ethereumAddress);\n request.onerror = () =>\n reject(\n new StorageError(\"Failed to retrieve wallet data\", request.error)\n );\n request.onsuccess = () => resolve(request.result || null);\n });\n }\n\n async delete(ethereumAddress: string): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.delete(ethereumAddress);\n request.onerror = () =>\n reject(new StorageError(\"Failed to delete wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n\n async clear(): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.clear();\n request.onerror = () =>\n reject(new StorageError(\"Failed to clear wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n}\n","/**\n * Message signing with encrypted wallet\n */\n\nimport { WalletError } from \"../core/errors\";\nimport { createWalletFromMnemonic } from \"./generate\";\nimport { deriveEncryptionKey, decryptData } from \"./crypto\";\nimport type { IndexedDBWalletStorage } from \"./storage\";\n\nexport class WalletSigner {\n constructor(private storage: IndexedDBWalletStorage) {}\n\n /**\n * Sign a message with the encrypted wallet\n * Requires fresh WebAuthn authentication\n */\n async signMessage(\n ethereumAddress: string,\n message: string,\n credentialId: string,\n challenge: string\n ): Promise<string> {\n try {\n // Retrieve encrypted wallet data\n const walletData = await this.storage.retrieve(ethereumAddress);\n if (!walletData) {\n throw new Error(\"No wallet found for this address\");\n }\n\n // Derive encryption key from WebAuthn credentials\n const encryptionKey = await deriveEncryptionKey(credentialId, challenge);\n\n // Decrypt mnemonic\n const mnemonic = await decryptData(\n walletData.encryptedMnemonic,\n encryptionKey\n );\n\n // Create wallet from mnemonic\n const wallet = createWalletFromMnemonic(mnemonic);\n\n // Verify address matches\n if (wallet.address.toLowerCase() !== ethereumAddress.toLowerCase()) {\n throw new Error(\"Wallet address mismatch\");\n }\n\n // Sign message\n const signature = await wallet.signMessage(message);\n\n // Clear mnemonic from memory (wallet will be garbage collected)\n return signature;\n } catch (error) {\n throw new WalletError(\"Failed to sign message\", error);\n }\n }\n\n /**\n * Check if wallet exists for address\n */\n async hasWallet(ethereumAddress: string): Promise<boolean> {\n const walletData = await this.storage.retrieve(ethereumAddress);\n return walletData !== null;\n }\n}\n","/**\n * BIP39 wallet generation\n */\n\nimport { ethers } from \"ethers\";\nimport { WalletError } from \"../core/errors\";\nimport type { WalletData } from \"./types\";\n\n/**\n * Generates a new BIP39 wallet with HD derivation\n * Uses BIP44 path: m/44'/60'/0'/0/0 for Ethereum\n */\nexport function generateBIP39Wallet(): WalletData {\n try {\n // Generate random mnemonic using ethers' utility\n const mnemonic = ethers.Wallet.createRandom().mnemonic;\n\n if (!mnemonic) {\n throw new Error(\"Failed to generate mnemonic\");\n }\n\n const mnemonicPhrase = mnemonic.phrase;\n\n // Create HD wallet from mnemonic phrase with derivation path\n const derivationPath = \"m/44'/60'/0'/0/0\";\n const hdWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonicPhrase,\n undefined,\n derivationPath\n );\n\n return {\n address: hdWallet.address,\n mnemonic: mnemonicPhrase,\n };\n } catch (error) {\n throw new WalletError(\"Wallet generation failed\", error);\n }\n}\n\n/**\n * Creates wallet from mnemonic phrase\n * Uses BIP44 path: m/44'/60'/0'/0/0\n */\nexport function createWalletFromMnemonic(\n mnemonic: string\n): ethers.HDNodeWallet {\n try {\n if (!mnemonic || mnemonic.trim().split(/\\s+/).length < 12) {\n throw new Error(\"Invalid mnemonic: must be at least 12 words\");\n }\n\n // Create HD wallet with derivation path directly\n const derivationPath = \"m/44'/60'/0'/0/0\";\n const wallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic.trim(),\n undefined,\n derivationPath\n );\n\n return wallet;\n } catch (error) {\n throw new WalletError(\n `Wallet creation failed: ${\n error instanceof Error ? error.message : \"Invalid mnemonic\"\n }`,\n error\n );\n }\n}\n","/**\n * Cryptographic utilities for wallet encryption\n */\n\nimport { CryptoError } from \"../core/errors\";\n\n/**\n * Derives an encryption key from WebAuthn credential data\n */\nexport async function deriveEncryptionKey(\n credentialId: string,\n challenge: string\n): Promise<CryptoKey> {\n try {\n const keyMaterial = new TextEncoder().encode(credentialId + challenge);\n\n const importedKey = await crypto.subtle.importKey(\n \"raw\",\n keyMaterial,\n { name: \"PBKDF2\" },\n false,\n [\"deriveKey\"]\n );\n\n return crypto.subtle.deriveKey(\n {\n name: \"PBKDF2\",\n salt: new TextEncoder().encode(\"webauthn-wallet-salt-w3pk\"),\n iterations: 100000,\n hash: \"SHA-256\",\n },\n importedKey,\n { name: \"AES-GCM\", length: 256 },\n false,\n [\"encrypt\", \"decrypt\"]\n );\n } catch (error) {\n throw new CryptoError(\"Failed to derive encryption key\", error);\n }\n}\n\n/**\n * Encrypts data using AES-GCM\n */\nexport async function encryptData(\n data: string,\n key: CryptoKey\n): Promise<string> {\n try {\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const encodedData = new TextEncoder().encode(data);\n\n const encrypted = await crypto.subtle.encrypt(\n { name: \"AES-GCM\", iv },\n key,\n encodedData\n );\n\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\n combined.set(iv);\n combined.set(new Uint8Array(encrypted), iv.length);\n\n return btoa(String.fromCharCode(...combined));\n } catch (error) {\n throw new CryptoError(\"Failed to encrypt data\", error);\n }\n}\n\n/**\n * Decrypts data using AES-GCM\n */\nexport async function decryptData(\n encryptedData: string,\n key: CryptoKey\n): Promise<string> {\n try {\n if (!encryptedData || encryptedData.length < 16) {\n throw new Error(\"Invalid encrypted data: too small\");\n }\n\n const combined = new Uint8Array(\n atob(encryptedData)\n .split(\"\")\n .map((char) => char.charCodeAt(0))\n );\n\n if (combined.length < 12) {\n throw new Error(\"Invalid encrypted data: missing IV\");\n }\n\n const iv = combined.slice(0, 12);\n const encrypted = combined.slice(12);\n\n if (encrypted.length === 0) {\n throw new Error(\"Invalid encrypted data: no content\");\n }\n\n const decrypted = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv },\n key,\n encrypted\n );\n\n return new TextDecoder().decode(decrypted);\n } catch (error) {\n throw new CryptoError(\n `Data decryption failed: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n error\n );\n }\n}\n","/**\n * Stealth Address Module for w3pk SDK\n * Provides privacy-preserving stealth address generation capabilities\n */\n\nimport { ethers } from \"ethers\";\nimport { Web3PasskeyError, AuthenticationError } from \"../core/errors\";\nimport { deriveStealthKeys } from \"./crypto\";\nimport type { StealthKeys } from \"./crypto\";\n\nexport interface StealthAddressConfig {\n // Network-agnostic - no provider needed\n}\n\nexport interface StealthAddressResult {\n stealthAddress: string;\n stealthPrivateKey: string;\n ephemeralPublicKey: string;\n}\n\n/**\n * Main Stealth Address Module\n * Integrates with w3pk WebAuthn for seamless privacy-preserving stealth address generation\n */\nexport class StealthAddressModule {\n private config: StealthAddressConfig;\n private getMnemonic: () => Promise<string | null>;\n\n constructor(config: StealthAddressConfig, getMnemonic: () => Promise<string | null>) {\n this.config = config;\n this.getMnemonic = getMnemonic;\n }\n\n // ========================================\n // Stealth Address Generation\n // ========================================\n\n /**\n * Generate a fresh stealth address for privacy-preserving transactions\n * Returns the stealth address and private key for the user to handle transactions\n */\n async generateStealthAddress(): Promise<StealthAddressResult> {\n try {\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new AuthenticationError(\"Not authenticated. Please login first.\");\n }\n\n const stealthKeys = deriveStealthKeys(mnemonic);\n const { generateStealthAddress } = await import(\"./crypto\");\n const stealthResult = generateStealthAddress(stealthKeys.metaAddress);\n\n return {\n stealthAddress: stealthResult.stealthAddress,\n stealthPrivateKey: stealthResult.stealthPrivkey,\n ephemeralPublicKey: stealthResult.ephemeralPubkey\n };\n } catch (error) {\n throw new Web3PasskeyError(\n \"Failed to generate stealth address\",\n \"STEALTH_GENERATION_ERROR\",\n error\n );\n }\n }\n\n\n // ========================================\n // Privacy & Key Management\n // ========================================\n\n /**\n * Get stealth keys for manual operations\n */\n async getKeys(): Promise<StealthKeys> {\n try {\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new AuthenticationError(\"Not authenticated. Please login first.\");\n }\n\n return deriveStealthKeys(mnemonic);\n } catch (error) {\n throw new Web3PasskeyError(\n \"Failed to get stealth keys\",\n \"STEALTH_KEYS_ERROR\",\n error\n );\n }\n }\n\n // ========================================\n // Status & Management\n // ========================================\n\n /**\n * Check if stealth addresses are available (always true if properly configured)\n */\n get isAvailable(): boolean {\n return true;\n }\n}\n\n// Export types for stealth module\nexport type { StealthKeys };","/**\n * SDK Configuration\n */\n\nimport type { UserInfo } from \"../types\";\nimport type { Web3PasskeyError } from \"./errors\";\nimport type { ethers } from \"ethers\";\n\nexport interface StealthAddressConfig {}\n\nexport interface Web3PasskeyConfig {\n /**\n * Base URL of the WebAuthn API\n * @example 'https://webauthn.w3hc.org'\n */\n apiBaseUrl: string;\n\n /**\n * Timeout for API requests in milliseconds\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom error handler\n */\n onError?: (error: Web3PasskeyError) => void;\n\n /**\n * Auth state change callback\n */\n onAuthStateChanged?: (isAuthenticated: boolean, user?: UserInfo) => void;\n\n /**\n * Optional stealth address configuration\n * If provided, enables privacy-preserving stealth address generation\n */\n stealthAddresses?: StealthAddressConfig;\n}\n\nexport interface InternalConfig extends Required<Web3PasskeyConfig> {\n // Normalized config with all defaults applied\n}\n\nexport const DEFAULT_CONFIG: Partial<Web3PasskeyConfig> = {\n timeout: 30000,\n debug: false,\n};\n"],"mappings":"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","names":["Web3PasskeyError","AuthenticationError","RegistrationError","WalletError","CryptoError","StorageError","ApiError","init_errors","__esmMin","message","code","originalError","statusCode","crypto_exports","__export","canControlStealthAddress","deriveStealthKeys","generateStealthAddress","mnemonic","viewingWallet","spendingWallet","computeMetaAddress","error","CryptoError","metaAddress","ephemeralWallet","stealthSeed","stealthWallet","viewingKey","spendingKey","ephemeralPubkey","targetAddress","viewingPubkey","spendingPubkey","combined","import_ethers","init_crypto","__esmMin","init_errors","index_exports","__export","ApiError","AuthenticationError","CryptoError","RegistrationError","StealthAddressModule","StorageError","WalletError","Web3Passkey","Web3PasskeyError","canControlStealthAddress","createWeb3Passkey","index_default","__toCommonJS","import_browser","init_errors","ApiClient","baseUrl","timeout","url","options","controller","timeoutId","response","error","endpoint","body","ApiError","init_errors","DB_NAME","DB_VERSION","STORE_NAME","IndexedDBWalletStorage","resolve","reject","request","StorageError","db","data","ethereumAddress","init_errors","import_ethers","init_errors","generateBIP39Wallet","mnemonic","mnemonicPhrase","error","WalletError","createWalletFromMnemonic","init_errors","deriveEncryptionKey","credentialId","challenge","keyMaterial","importedKey","error","CryptoError","encryptData","data","key","iv","encodedData","encrypted","combined","decryptData","encryptedData","char","decrypted","WalletSigner","storage","ethereumAddress","message","credentialId","challenge","walletData","encryptionKey","deriveEncryptionKey","mnemonic","decryptData","wallet","createWalletFromMnemonic","error","WalletError","init_errors","init_crypto","StealthAddressModule","config","getMnemonic","mnemonic","AuthenticationError","stealthKeys","deriveStealthKeys","generateStealthAddress","stealthResult","error","Web3PasskeyError","DEFAULT_CONFIG","Web3Passkey","config","DEFAULT_CONFIG","ApiClient","IndexedDBWalletStorage","WalletSigner","StealthAddressModule","error","storedUser","storedAuth","user","isAuthenticated","username","ethereumAddress","walletData","encryptionKey","deriveEncryptionKey","decryptData","wallet","generateBIP39Wallet","options","mnemonic","beginResponse","webauthnOptions","credential","encryptedMnemonic","encryptData","completeResponse","serverUser","message","signature","init_errors","init_crypto","createWeb3Passkey","config","Web3Passkey","index_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/errors.ts","../src/stealth/crypto.ts","../src/index.ts","../src/core/sdk.ts","../src/utils/api.ts","../src/wallet/storage.ts","../src/wallet/signing.ts","../src/wallet/generate.ts","../src/wallet/crypto.ts","../src/stealth/index.ts","../src/core/config.ts"],"sourcesContent":["/**\n * Custom error classes for better error handling\n */\n\nexport class Web3PasskeyError extends Error {\n constructor(\n message: string,\n public code: string,\n public originalError?: unknown\n ) {\n super(message);\n this.name = \"Web3PasskeyError\";\n }\n}\n\nexport class AuthenticationError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"AUTHENTICATION_ERROR\", originalError);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class RegistrationError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"REGISTRATION_ERROR\", originalError);\n this.name = \"RegistrationError\";\n }\n}\n\nexport class WalletError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"WALLET_ERROR\", originalError);\n this.name = \"WalletError\";\n }\n}\n\nexport class CryptoError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"CRYPTO_ERROR\", originalError);\n this.name = \"CryptoError\";\n }\n}\n\nexport class StorageError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"STORAGE_ERROR\", originalError);\n this.name = \"StorageError\";\n }\n}\n\nexport class ApiError extends Web3PasskeyError {\n constructor(\n message: string,\n public statusCode?: number,\n originalError?: unknown\n ) {\n super(message, \"API_ERROR\", originalError);\n this.name = \"ApiError\";\n }\n}\n","/**\n * Stealth address cryptography for privacy-preserving transactions\n */\n\nimport { ethers } from \"ethers\";\nimport { CryptoError } from \"../core/errors\";\n\nexport interface StealthKeys {\n metaAddress: string;\n viewingKey: string;\n spendingKey: string;\n}\n\nexport interface StealthAddressResult {\n stealthAddress: string;\n stealthPrivkey: string;\n ephemeralPubkey: string;\n}\n\n/**\n * Derive stealth keys from w3pk mnemonic using HD paths\n */\nexport function deriveStealthKeys(mnemonic: string): StealthKeys {\n try {\n // Use specific derivation paths for stealth keys\n const viewingWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic,\n undefined,\n \"m/44'/60'/1'/0/0\" // Viewing key path\n );\n\n const spendingWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic,\n undefined,\n \"m/44'/60'/1'/0/1\" // Spending key path\n );\n\n // Meta address is derived from viewing key\n const metaAddress = computeMetaAddress(\n viewingWallet.signingKey.publicKey,\n spendingWallet.signingKey.publicKey\n );\n\n return {\n metaAddress,\n viewingKey: viewingWallet.privateKey,\n spendingKey: spendingWallet.privateKey,\n };\n } catch (error) {\n throw new CryptoError(\"Failed to derive stealth keys\", error);\n }\n}\n\n/**\n * Generate a stealth address using ECDH\n */\nexport function generateStealthAddress(\n metaAddress: string\n): StealthAddressResult {\n try {\n // Generate ephemeral keypair\n const ephemeralWallet = ethers.Wallet.createRandom();\n\n // For simplified implementation, derive stealth address from ephemeral key + meta address\n const stealthSeed = ethers.solidityPackedKeccak256(\n [\"bytes\", \"address\"],\n [ephemeralWallet.signingKey.publicKey, metaAddress]\n );\n\n const stealthWallet = new ethers.Wallet(stealthSeed);\n\n return {\n stealthAddress: stealthWallet.address,\n stealthPrivkey: stealthWallet.privateKey,\n ephemeralPubkey: ephemeralWallet.signingKey.publicKey,\n };\n } catch (error) {\n throw new CryptoError(\"Failed to generate stealth address\", error);\n }\n}\n\n/**\n * Check if a stealth address can be controlled by the stealth keys\n * Useful for scanning and proving ownership of stealth addresses\n */\nexport function canControlStealthAddress(\n viewingKey: string,\n spendingKey: string,\n ephemeralPubkey: string,\n targetAddress: string\n): boolean {\n try {\n // Reconstruct stealth address using both viewing and spending keys\n const viewingWallet = new ethers.Wallet(viewingKey);\n const spendingWallet = new ethers.Wallet(spendingKey);\n \n const metaAddress = computeMetaAddress(\n viewingWallet.signingKey.publicKey,\n spendingWallet.signingKey.publicKey\n );\n\n const stealthSeed = ethers.solidityPackedKeccak256(\n [\"bytes\", \"address\"],\n [ephemeralPubkey, metaAddress]\n );\n\n const derivedWallet = new ethers.Wallet(stealthSeed);\n\n return derivedWallet.address.toLowerCase() === targetAddress.toLowerCase();\n } catch (error) {\n return false;\n }\n}\n\n/**\n * Compute meta address from public keys (simplified)\n */\nfunction computeMetaAddress(\n viewingPubkey: string,\n spendingPubkey: string\n): string {\n const combined = ethers.solidityPackedKeccak256(\n [\"bytes\", \"bytes\"],\n [viewingPubkey, spendingPubkey]\n );\n\n // Take first 20 bytes as address\n return ethers.getAddress(\"0x\" + combined.slice(26));\n}\n","/**\n * w3pk - Web3 Passkey SDK\n * WebAuthn SDK for passwordless authentication and encrypted wallet management\n */\n\nimport { Web3Passkey } from \"./core/sdk\";\nimport type { Web3PasskeyConfig } from \"./core/config\";\n\n// Main factory function\nexport function createWeb3Passkey(config: Web3PasskeyConfig): Web3Passkey {\n return new Web3Passkey(config);\n}\n\n// Export types\nexport type { Web3PasskeyConfig, StealthAddressConfig } from \"./core/config\";\nexport type { UserInfo, WalletInfo } from \"./types\";\nexport type { StealthKeys, StealthAddressResult } from \"./stealth\";\n\n// Export errors for custom error handling\nexport {\n Web3PasskeyError,\n AuthenticationError,\n RegistrationError,\n WalletError,\n CryptoError,\n StorageError,\n ApiError,\n} from \"./core/errors\";\n\n// Export SDK class for advanced usage\nexport { Web3Passkey } from \"./core/sdk\";\n\n// Export stealth address module for advanced usage\nexport { StealthAddressModule } from \"./stealth\";\n\n// Export crypto utilities\nexport { canControlStealthAddress } from \"./stealth/crypto\";\n\n// Export wallet generation utilities\nexport { generateBIP39Wallet, createWalletFromMnemonic, deriveWalletFromMnemonic } from \"./wallet/generate\";\n\n// Default export\nexport default createWeb3Passkey;\n","/**\n * Main Web3Passkey SDK class\n */\n\nimport {\n startRegistration,\n startAuthentication,\n} from \"@simplewebauthn/browser\";\nimport { ApiClient } from \"../utils/api\";\nimport { IndexedDBWalletStorage } from \"../wallet/storage\";\nimport { WalletSigner } from \"../wallet/signing\";\nimport {\n generateBIP39Wallet,\n deriveWalletFromMnemonic,\n} from \"../wallet/generate\";\nimport {\n deriveEncryptionKey,\n encryptData,\n decryptData,\n} from \"../wallet/crypto\";\nimport { StealthAddressModule } from \"../stealth\";\nimport type {\n Web3PasskeyConfig,\n InternalConfig,\n StealthAddressConfig,\n} from \"./config\";\nimport { DEFAULT_CONFIG } from \"./config\";\nimport type { UserInfo, WalletInfo } from \"../types\";\n\nexport interface AuthResult {\n verified: boolean;\n user?: UserInfo;\n}\n\nexport class Web3Passkey {\n private config: InternalConfig;\n private apiClient: ApiClient;\n private walletStorage: IndexedDBWalletStorage;\n private walletSigner: WalletSigner;\n private currentUser: UserInfo | null = null;\n private isAuthenticatedState: boolean = false;\n private isBrowser: boolean;\n private stealthAddresses: StealthAddressModule | null = null;\n\n constructor(config: Web3PasskeyConfig) {\n // Check if running in browser\n this.isBrowser =\n typeof window !== \"undefined\" && typeof localStorage !== \"undefined\";\n\n // Merge with defaults\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n timeout: config.timeout ?? DEFAULT_CONFIG.timeout!,\n debug: config.debug ?? DEFAULT_CONFIG.debug!,\n } as InternalConfig;\n\n // Initialize components\n this.apiClient = new ApiClient(this.config.apiBaseUrl, this.config.timeout);\n this.walletStorage = new IndexedDBWalletStorage();\n this.walletSigner = new WalletSigner(this.walletStorage);\n\n // Initialize stealth addresses if configured\n if (config.stealthAddresses) {\n this.stealthAddresses = new StealthAddressModule(\n config.stealthAddresses,\n this.getMnemonic.bind(this)\n );\n }\n\n // Initialize storage only in browser\n if (this.isBrowser) {\n this.walletStorage.init().catch((error) => {\n if (this.config.debug) {\n console.error(\"Failed to initialize wallet storage:\", error);\n }\n });\n\n // Load persisted auth state\n this.loadAuthState();\n } else if (this.config.debug) {\n console.warn(\n \"w3pk: Running in non-browser environment, some features disabled\"\n );\n }\n }\n\n // ========================================\n // Auth State Management\n // ========================================\n\n private loadAuthState(): void {\n if (!this.isBrowser) return;\n\n try {\n const storedUser = localStorage.getItem(\"w3pk_user\");\n const storedAuth = localStorage.getItem(\"w3pk_authenticated\");\n\n if (storedUser && storedAuth === \"true\") {\n this.currentUser = JSON.parse(storedUser);\n this.isAuthenticatedState = true;\n this.notifyAuthStateChange(true, this.currentUser ?? undefined);\n }\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to load auth state:\", error);\n }\n this.clearAuthState();\n }\n }\n\n private saveAuthState(user: UserInfo): void {\n if (!this.isBrowser) {\n console.warn(\"w3pk: Cannot save auth state in non-browser environment\");\n return;\n }\n\n try {\n localStorage.setItem(\"w3pk_user\", JSON.stringify(user));\n localStorage.setItem(\"w3pk_authenticated\", \"true\");\n this.currentUser = user;\n this.isAuthenticatedState = true;\n this.notifyAuthStateChange(true, user);\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to save auth state:\", error);\n }\n }\n }\n\n private clearAuthState(): void {\n if (!this.isBrowser) return;\n\n try {\n localStorage.removeItem(\"w3pk_user\");\n localStorage.removeItem(\"w3pk_authenticated\");\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to clear auth state:\", error);\n }\n }\n\n this.currentUser = null;\n this.isAuthenticatedState = false;\n this.notifyAuthStateChange(false);\n }\n\n private notifyAuthStateChange(\n isAuthenticated: boolean,\n user?: UserInfo\n ): void {\n if (this.config.onAuthStateChanged) {\n this.config.onAuthStateChanged(isAuthenticated, user);\n }\n }\n\n private createUserInfo(username: string, ethereumAddress: string): UserInfo {\n return {\n id: ethereumAddress,\n username,\n displayName: username,\n ethereumAddress,\n };\n }\n\n /**\n * Get mnemonic for current authenticated user\n * Used by stealth address module\n */\n private async getMnemonic(): Promise<string | null> {\n if (!this.isBrowser || !this.currentUser) {\n return null;\n }\n\n try {\n // Get encrypted wallet data\n const walletData = await this.walletStorage.retrieve(\n this.currentUser.ethereumAddress\n );\n if (!walletData) {\n return null;\n }\n\n // Derive encryption key from stored credentials\n const encryptionKey = await deriveEncryptionKey(\n walletData.credentialId,\n walletData.challenge\n );\n\n // Decrypt mnemonic\n return await decryptData(walletData.encryptedMnemonic, encryptionKey);\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to get mnemonic:\", error);\n }\n return null;\n }\n }\n\n // ========================================\n // Public API - Wallet\n // ========================================\n\n /**\n * Generate a new BIP39 wallet\n * @returns Wallet info with mnemonic (user MUST backup)\n */\n async generateWallet(): Promise<WalletInfo> {\n try {\n const wallet = generateBIP39Wallet();\n\n if (this.config.debug) {\n console.log(\"Wallet generated:\", wallet.address);\n }\n\n return wallet;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Check if wallet exists for current user\n */\n async hasWallet(): Promise<boolean> {\n if (!this.isBrowser) {\n console.warn(\n \"w3pk: Wallet storage not available in non-browser environment\"\n );\n return false;\n }\n\n if (!this.currentUser) {\n return false;\n }\n\n try {\n return await this.walletSigner.hasWallet(\n this.currentUser.ethereumAddress\n );\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to check wallet existence:\", error);\n }\n return false;\n }\n }\n\n /**\n * Derive HD wallet address and private key at specific index\n * Requires authentication to access encrypted mnemonic\n *\n * @param index HD derivation index (default: 0)\n * @returns Object with address and privateKey\n */\n async deriveWallet(\n index: number = 0\n ): Promise<{ address: string; privateKey: string }> {\n if (!this.isBrowser) {\n throw new Error(\"HD wallet derivation requires browser environment\");\n }\n\n if (!this.currentUser) {\n throw new Error(\"Not authenticated\");\n }\n\n try {\n // Get mnemonic for current authenticated user\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new Error(\"No wallet found for this user\");\n }\n\n // Derive wallet at specific index\n const derivedWallet = deriveWalletFromMnemonic(mnemonic, index);\n\n if (this.config.debug) {\n console.log(\n `HD wallet derived at index ${index}:`,\n derivedWallet.address\n );\n }\n\n return derivedWallet;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n // ========================================\n // Public API - Authentication\n // ========================================\n\n /**\n * Register a new user with WebAuthn\n * Handles the complete registration flow internally\n * Automatically generates wallet if not provided\n *\n * @param username Username for the account\n * @param ethereumAddress Optional: Ethereum address (will generate if not provided)\n * @param mnemonic Optional: BIP39 mnemonic (will generate if not provided)\n * @returns Object containing ethereumAddress and mnemonic (only if generated)\n */\n async register(options: {\n username: string;\n ethereumAddress?: string;\n mnemonic?: string;\n }): Promise<{ ethereumAddress: string; mnemonic?: string }> {\n if (!this.isBrowser) {\n throw new Error(\n \"Registration requires browser environment with WebAuthn support\"\n );\n }\n\n try {\n const { username } = options;\n let { ethereumAddress, mnemonic } = options;\n\n // Generate wallet if not provided\n if (!ethereumAddress || !mnemonic) {\n const wallet = generateBIP39Wallet();\n ethereumAddress = wallet.address;\n mnemonic = wallet.mnemonic;\n }\n\n // Step 1: Begin registration - get WebAuthn options from server\n const beginResponse = await this.apiClient.post(\n \"/webauthn/register/begin\",\n {\n username,\n ethereumAddress,\n }\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\"Failed to get registration options from server\");\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 2: Perform WebAuthn registration (browser prompt)\n const credential = await startRegistration(webauthnOptions);\n\n // Step 3: Encrypt mnemonic with WebAuthn-derived key\n const encryptionKey = await deriveEncryptionKey(\n credential.id,\n webauthnOptions.challenge\n );\n const encryptedMnemonic = await encryptData(mnemonic, encryptionKey);\n\n // Step 4: Store encrypted mnemonic in IndexedDB\n await this.walletStorage.store({\n ethereumAddress,\n encryptedMnemonic,\n credentialId: credential.id,\n challenge: webauthnOptions.challenge,\n createdAt: Date.now(),\n });\n\n // Step 5: Complete registration with server\n const completeResponse = await this.apiClient.post(\n \"/webauthn/register/complete\",\n {\n ethereumAddress,\n response: credential,\n }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Registration verification failed\");\n }\n\n // Step 6: Save auth state with displayName\n const user = this.createUserInfo(username, ethereumAddress);\n this.saveAuthState(user);\n\n if (this.config.debug) {\n console.log(\"Registration successful for:\", ethereumAddress);\n }\n\n // Return the wallet info (mnemonic only if we generated it)\n return {\n ethereumAddress,\n mnemonic: options.mnemonic ? undefined : mnemonic,\n };\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Authenticate without username (usernameless flow)\n */\n async login(): Promise<AuthResult> {\n if (!this.isBrowser) {\n throw new Error(\n \"Authentication requires browser environment with WebAuthn support\"\n );\n }\n\n try {\n // Step 1: Begin usernameless authentication\n const beginResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/begin\",\n {}\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\n \"Failed to get usernameless authentication options from server\"\n );\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 2: WebAuthn authentication\n const credential = await startAuthentication(webauthnOptions);\n\n // Step 3: Complete authentication\n const completeResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/complete\",\n { response: credential }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Usernameless authentication verification failed\");\n }\n\n const serverUser = completeResponse.data?.user;\n if (!serverUser) {\n throw new Error(\"No user data received from server\");\n }\n\n // Create UserInfo with displayName\n const user = this.createUserInfo(\n serverUser.username,\n serverUser.ethereumAddress || serverUser.id\n );\n this.saveAuthState(user);\n\n if (this.config.debug) {\n console.log(\n \"Usernameless authentication successful for:\",\n user.ethereumAddress\n );\n }\n\n return {\n verified: true,\n user,\n };\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Logout current user\n */\n logout(): void {\n this.clearAuthState();\n\n if (this.config.debug) {\n console.log(\"User logged out\");\n }\n }\n\n // ========================================\n // Public API - Message Signing\n // ========================================\n\n /**\n * Sign a message with encrypted wallet\n * Handles fresh WebAuthn authentication internally\n *\n * @param message Message to sign\n */\n async signMessage(message: string): Promise<string> {\n if (!this.isBrowser) {\n throw new Error(\"Message signing requires browser environment\");\n }\n\n if (!this.currentUser) {\n throw new Error(\"Not authenticated\");\n }\n\n try {\n // Step 1: Check if wallet exists\n const walletData = await this.walletStorage.retrieve(\n this.currentUser.ethereumAddress\n );\n if (!walletData) {\n throw new Error(\n \"No wallet found on this device. Please register to create a new wallet.\"\n );\n }\n\n // Step 2: Request fresh WebAuthn authentication\n if (this.config.debug) {\n console.log(\"Requesting WebAuthn authentication for signing...\");\n }\n\n const beginResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/begin\",\n {}\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\"Failed to begin authentication for signing\");\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 3: Perform WebAuthn authentication (browser prompt)\n const credential = await startAuthentication(webauthnOptions);\n\n // Step 4: Verify authentication with server\n const completeResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/complete\",\n { response: credential }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Authentication verification failed for signing\");\n }\n\n // Step 5: Use the authenticated credentials to sign\n const signature = await this.walletSigner.signMessage(\n this.currentUser.ethereumAddress,\n message,\n walletData.credentialId,\n walletData.challenge\n );\n\n if (this.config.debug) {\n console.log(\"Message signed successfully\");\n }\n\n return signature;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n // ========================================\n // Public API - Getters\n // ========================================\n\n /**\n * Check if user is authenticated\n */\n get isAuthenticated(): boolean {\n return this.isAuthenticatedState;\n }\n\n /**\n * Get current user info\n */\n get user(): UserInfo | null {\n return this.currentUser;\n }\n\n /**\n * Get SDK version\n */\n get version(): string {\n return \"0.4.1\";\n }\n\n /**\n * Check if running in browser environment\n */\n get isBrowserEnvironment(): boolean {\n return this.isBrowser;\n }\n\n /**\n * Get stealth address module (if configured)\n */\n get stealth(): StealthAddressModule | null {\n return this.stealthAddresses;\n }\n}\n","/**\n * API client for backend communication\n */\n\nimport { ApiError } from \"../core/errors\";\nimport type { ApiResponse } from \"../types\";\n\nexport class ApiClient {\n constructor(private baseUrl: string, private timeout: number = 30000) {}\n\n private async fetchWithTimeout(\n url: string,\n options: RequestInit\n ): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n async post<T = any>(\n endpoint: string,\n body: any,\n options?: RequestInit\n ): Promise<ApiResponse<T>> {\n try {\n const response = await this.fetchWithTimeout(\n `${this.baseUrl}${endpoint}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n body: JSON.stringify(body),\n ...options,\n }\n );\n\n if (!response.ok) {\n throw new ApiError(\n `API request failed: ${response.statusText}`,\n response.status\n );\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n throw new ApiError(\"Network request failed\", undefined, error);\n }\n }\n\n async get<T = any>(\n endpoint: string,\n options?: RequestInit\n ): Promise<ApiResponse<T>> {\n try {\n const response = await this.fetchWithTimeout(\n `${this.baseUrl}${endpoint}`,\n {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n ...options,\n }\n );\n\n if (!response.ok) {\n throw new ApiError(\n `API request failed: ${response.statusText}`,\n response.status\n );\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n throw new ApiError(\"Network request failed\", undefined, error);\n }\n }\n}\n","/**\n * IndexedDB storage for encrypted wallet data\n */\n\nimport { StorageError } from \"../core/errors\";\nimport type { EncryptedWalletData, WalletStorage } from \"./types\";\n\nconst DB_NAME = \"Web3PasskeyWallet\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"wallets\";\n\nexport class IndexedDBWalletStorage implements WalletStorage {\n private db: IDBDatabase | null = null;\n\n async init(): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n\n request.onerror = () =>\n reject(new StorageError(\"Failed to open database\", request.error));\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: \"ethereumAddress\" });\n }\n };\n });\n }\n\n async store(data: EncryptedWalletData): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.put(data);\n request.onerror = () =>\n reject(new StorageError(\"Failed to store wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n\n async retrieve(ethereumAddress: string): Promise<EncryptedWalletData | null> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readonly\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.get(ethereumAddress);\n request.onerror = () =>\n reject(\n new StorageError(\"Failed to retrieve wallet data\", request.error)\n );\n request.onsuccess = () => resolve(request.result || null);\n });\n }\n\n async delete(ethereumAddress: string): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.delete(ethereumAddress);\n request.onerror = () =>\n reject(new StorageError(\"Failed to delete wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n\n async clear(): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.clear();\n request.onerror = () =>\n reject(new StorageError(\"Failed to clear wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n}\n","/**\n * Message signing with encrypted wallet\n */\n\nimport { WalletError } from \"../core/errors\";\nimport { createWalletFromMnemonic } from \"./generate\";\nimport { deriveEncryptionKey, decryptData } from \"./crypto\";\nimport type { IndexedDBWalletStorage } from \"./storage\";\n\nexport class WalletSigner {\n constructor(private storage: IndexedDBWalletStorage) {}\n\n /**\n * Sign a message with the encrypted wallet\n * Requires fresh WebAuthn authentication\n */\n async signMessage(\n ethereumAddress: string,\n message: string,\n credentialId: string,\n challenge: string\n ): Promise<string> {\n try {\n // Retrieve encrypted wallet data\n const walletData = await this.storage.retrieve(ethereumAddress);\n if (!walletData) {\n throw new Error(\"No wallet found for this address\");\n }\n\n // Derive encryption key from WebAuthn credentials\n const encryptionKey = await deriveEncryptionKey(credentialId, challenge);\n\n // Decrypt mnemonic\n const mnemonic = await decryptData(\n walletData.encryptedMnemonic,\n encryptionKey\n );\n\n // Create wallet from mnemonic\n const wallet = createWalletFromMnemonic(mnemonic);\n\n // Verify address matches\n if (wallet.address.toLowerCase() !== ethereumAddress.toLowerCase()) {\n throw new Error(\"Wallet address mismatch\");\n }\n\n // Sign message\n const signature = await wallet.signMessage(message);\n\n // Clear mnemonic from memory (wallet will be garbage collected)\n return signature;\n } catch (error) {\n throw new WalletError(\"Failed to sign message\", error);\n }\n }\n\n /**\n * Check if wallet exists for address\n */\n async hasWallet(ethereumAddress: string): Promise<boolean> {\n const walletData = await this.storage.retrieve(ethereumAddress);\n return walletData !== null;\n }\n}\n","/**\n * BIP39 wallet generation\n */\n\nimport { ethers } from \"ethers\";\nimport { WalletError } from \"../core/errors\";\nimport type { WalletData } from \"./types\";\n\n/**\n * Generates a new BIP39 wallet with HD derivation\n * Uses BIP44 path: m/44'/60'/0'/0/0 for Ethereum\n */\nexport function generateBIP39Wallet(): WalletData {\n try {\n // Generate random mnemonic using ethers' utility\n const mnemonic = ethers.Wallet.createRandom().mnemonic;\n\n if (!mnemonic) {\n throw new Error(\"Failed to generate mnemonic\");\n }\n\n const mnemonicPhrase = mnemonic.phrase;\n\n // Create HD wallet from mnemonic phrase with derivation path\n const derivationPath = \"m/44'/60'/0'/0/0\";\n const hdWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonicPhrase,\n undefined,\n derivationPath\n );\n\n return {\n address: hdWallet.address,\n mnemonic: mnemonicPhrase,\n };\n } catch (error) {\n throw new WalletError(\"Wallet generation failed\", error);\n }\n}\n\n/**\n * Creates wallet from mnemonic phrase\n * Uses BIP44 path: m/44'/60'/0'/0/0\n */\nexport function createWalletFromMnemonic(\n mnemonic: string\n): ethers.HDNodeWallet {\n try {\n if (!mnemonic || mnemonic.trim().split(/\\s+/).length < 12) {\n throw new Error(\"Invalid mnemonic: must be at least 12 words\");\n }\n\n // Create HD wallet with derivation path directly\n const derivationPath = \"m/44'/60'/0'/0/0\";\n const wallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic.trim(),\n undefined,\n derivationPath\n );\n\n return wallet;\n } catch (error) {\n throw new WalletError(\n `Wallet creation failed: ${\n error instanceof Error ? error.message : \"Invalid mnemonic\"\n }`,\n error\n );\n }\n}\n\n/**\n * Derives HD wallet address and private key at specific index\n * Uses BIP44 path: m/44'/60'/0'/0/{index}\n */\nexport function deriveWalletFromMnemonic(\n mnemonic: string,\n index: number = 0\n): { address: string; privateKey: string } {\n try {\n if (!mnemonic || mnemonic.trim().split(/\\s+/).length < 12) {\n throw new Error(\"Invalid mnemonic: must be at least 12 words\");\n }\n\n if (index < 0 || !Number.isInteger(index)) {\n throw new Error(\"Index must be a non-negative integer\");\n }\n\n // Create HD wallet with derivation path including index\n const derivationPath = `m/44'/60'/0'/0/${index}`;\n const wallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic.trim(),\n undefined,\n derivationPath\n );\n\n return {\n address: wallet.address,\n privateKey: wallet.privateKey,\n };\n } catch (error) {\n throw new WalletError(\n `HD wallet derivation failed: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n error\n );\n }\n}\n","/**\n * Cryptographic utilities for wallet encryption\n */\n\nimport { CryptoError } from \"../core/errors\";\n\n/**\n * Derives an encryption key from WebAuthn credential data\n */\nexport async function deriveEncryptionKey(\n credentialId: string,\n challenge: string\n): Promise<CryptoKey> {\n try {\n const keyMaterial = new TextEncoder().encode(credentialId + challenge);\n\n const importedKey = await crypto.subtle.importKey(\n \"raw\",\n keyMaterial,\n { name: \"PBKDF2\" },\n false,\n [\"deriveKey\"]\n );\n\n return crypto.subtle.deriveKey(\n {\n name: \"PBKDF2\",\n salt: new TextEncoder().encode(\"webauthn-wallet-salt-w3pk\"),\n iterations: 100000,\n hash: \"SHA-256\",\n },\n importedKey,\n { name: \"AES-GCM\", length: 256 },\n false,\n [\"encrypt\", \"decrypt\"]\n );\n } catch (error) {\n throw new CryptoError(\"Failed to derive encryption key\", error);\n }\n}\n\n/**\n * Encrypts data using AES-GCM\n */\nexport async function encryptData(\n data: string,\n key: CryptoKey\n): Promise<string> {\n try {\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const encodedData = new TextEncoder().encode(data);\n\n const encrypted = await crypto.subtle.encrypt(\n { name: \"AES-GCM\", iv },\n key,\n encodedData\n );\n\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\n combined.set(iv);\n combined.set(new Uint8Array(encrypted), iv.length);\n\n return btoa(String.fromCharCode(...combined));\n } catch (error) {\n throw new CryptoError(\"Failed to encrypt data\", error);\n }\n}\n\n/**\n * Decrypts data using AES-GCM\n */\nexport async function decryptData(\n encryptedData: string,\n key: CryptoKey\n): Promise<string> {\n try {\n if (!encryptedData || encryptedData.length < 16) {\n throw new Error(\"Invalid encrypted data: too small\");\n }\n\n const combined = new Uint8Array(\n atob(encryptedData)\n .split(\"\")\n .map((char) => char.charCodeAt(0))\n );\n\n if (combined.length < 12) {\n throw new Error(\"Invalid encrypted data: missing IV\");\n }\n\n const iv = combined.slice(0, 12);\n const encrypted = combined.slice(12);\n\n if (encrypted.length === 0) {\n throw new Error(\"Invalid encrypted data: no content\");\n }\n\n const decrypted = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv },\n key,\n encrypted\n );\n\n return new TextDecoder().decode(decrypted);\n } catch (error) {\n throw new CryptoError(\n `Data decryption failed: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n error\n );\n }\n}\n","/**\n * Stealth Address Module for w3pk SDK\n * Provides privacy-preserving stealth address generation capabilities\n */\n\nimport { ethers } from \"ethers\";\nimport { Web3PasskeyError, AuthenticationError } from \"../core/errors\";\nimport { deriveStealthKeys } from \"./crypto\";\nimport type { StealthKeys } from \"./crypto\";\n\nexport interface StealthAddressConfig {\n // Network-agnostic - no provider needed\n}\n\nexport interface StealthAddressResult {\n stealthAddress: string;\n stealthPrivateKey: string;\n ephemeralPublicKey: string;\n}\n\n/**\n * Main Stealth Address Module\n * Integrates with w3pk WebAuthn for seamless privacy-preserving stealth address generation\n */\nexport class StealthAddressModule {\n private config: StealthAddressConfig;\n private getMnemonic: () => Promise<string | null>;\n\n constructor(config: StealthAddressConfig, getMnemonic: () => Promise<string | null>) {\n this.config = config;\n this.getMnemonic = getMnemonic;\n }\n\n // ========================================\n // Stealth Address Generation\n // ========================================\n\n /**\n * Generate a fresh stealth address for privacy-preserving transactions\n * Returns the stealth address and private key for the user to handle transactions\n */\n async generateStealthAddress(): Promise<StealthAddressResult> {\n try {\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new AuthenticationError(\"Not authenticated. Please login first.\");\n }\n\n const stealthKeys = deriveStealthKeys(mnemonic);\n const { generateStealthAddress } = await import(\"./crypto\");\n const stealthResult = generateStealthAddress(stealthKeys.metaAddress);\n\n return {\n stealthAddress: stealthResult.stealthAddress,\n stealthPrivateKey: stealthResult.stealthPrivkey,\n ephemeralPublicKey: stealthResult.ephemeralPubkey\n };\n } catch (error) {\n throw new Web3PasskeyError(\n \"Failed to generate stealth address\",\n \"STEALTH_GENERATION_ERROR\",\n error\n );\n }\n }\n\n\n // ========================================\n // Privacy & Key Management\n // ========================================\n\n /**\n * Get stealth keys for manual operations\n */\n async getKeys(): Promise<StealthKeys> {\n try {\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new AuthenticationError(\"Not authenticated. Please login first.\");\n }\n\n return deriveStealthKeys(mnemonic);\n } catch (error) {\n throw new Web3PasskeyError(\n \"Failed to get stealth keys\",\n \"STEALTH_KEYS_ERROR\",\n error\n );\n }\n }\n\n // ========================================\n // Status & Management\n // ========================================\n\n /**\n * Check if stealth addresses are available (always true if properly configured)\n */\n get isAvailable(): boolean {\n return true;\n }\n}\n\n// Export types for stealth module\nexport type { StealthKeys };","/**\n * SDK Configuration\n */\n\nimport type { UserInfo } from \"../types\";\nimport type { Web3PasskeyError } from \"./errors\";\nimport type { ethers } from \"ethers\";\n\nexport interface StealthAddressConfig {}\n\nexport interface Web3PasskeyConfig {\n /**\n * Base URL of the WebAuthn API\n * @example 'https://webauthn.w3hc.org'\n */\n apiBaseUrl: string;\n\n /**\n * Timeout for API requests in milliseconds\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom error handler\n */\n onError?: (error: Web3PasskeyError) => void;\n\n /**\n * Auth state change callback\n */\n onAuthStateChanged?: (isAuthenticated: boolean, user?: UserInfo) => void;\n\n /**\n * Optional stealth address configuration\n * If provided, enables privacy-preserving stealth address generation\n */\n stealthAddresses?: StealthAddressConfig;\n}\n\nexport interface InternalConfig extends Required<Web3PasskeyConfig> {\n // Normalized config with all defaults applied\n}\n\nexport const DEFAULT_CONFIG: Partial<Web3PasskeyConfig> = {\n timeout: 30000,\n debug: false,\n};\n"],"mappings":"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","names":["Web3PasskeyError","AuthenticationError","RegistrationError","WalletError","CryptoError","StorageError","ApiError","init_errors","__esmMin","message","code","originalError","statusCode","crypto_exports","__export","canControlStealthAddress","deriveStealthKeys","generateStealthAddress","mnemonic","viewingWallet","spendingWallet","computeMetaAddress","error","CryptoError","metaAddress","ephemeralWallet","stealthSeed","stealthWallet","viewingKey","spendingKey","ephemeralPubkey","targetAddress","viewingPubkey","spendingPubkey","combined","import_ethers","init_crypto","__esmMin","init_errors","index_exports","__export","ApiError","AuthenticationError","CryptoError","RegistrationError","StealthAddressModule","StorageError","WalletError","Web3Passkey","Web3PasskeyError","canControlStealthAddress","createWalletFromMnemonic","createWeb3Passkey","index_default","deriveWalletFromMnemonic","generateBIP39Wallet","__toCommonJS","import_browser","init_errors","ApiClient","baseUrl","timeout","url","options","controller","timeoutId","response","error","endpoint","body","ApiError","init_errors","DB_NAME","DB_VERSION","STORE_NAME","IndexedDBWalletStorage","resolve","reject","request","StorageError","db","data","ethereumAddress","init_errors","import_ethers","init_errors","generateBIP39Wallet","mnemonic","mnemonicPhrase","error","WalletError","createWalletFromMnemonic","deriveWalletFromMnemonic","index","derivationPath","wallet","init_errors","deriveEncryptionKey","credentialId","challenge","keyMaterial","importedKey","error","CryptoError","encryptData","data","key","iv","encodedData","encrypted","combined","decryptData","encryptedData","char","decrypted","WalletSigner","storage","ethereumAddress","message","credentialId","challenge","walletData","encryptionKey","deriveEncryptionKey","mnemonic","decryptData","wallet","createWalletFromMnemonic","error","WalletError","init_errors","init_crypto","StealthAddressModule","config","getMnemonic","mnemonic","AuthenticationError","stealthKeys","deriveStealthKeys","generateStealthAddress","stealthResult","error","Web3PasskeyError","DEFAULT_CONFIG","Web3Passkey","config","DEFAULT_CONFIG","ApiClient","IndexedDBWalletStorage","WalletSigner","StealthAddressModule","error","storedUser","storedAuth","user","isAuthenticated","username","ethereumAddress","walletData","encryptionKey","deriveEncryptionKey","decryptData","wallet","generateBIP39Wallet","index","mnemonic","derivedWallet","deriveWalletFromMnemonic","options","beginResponse","webauthnOptions","credential","encryptedMnemonic","encryptData","completeResponse","serverUser","message","signature","init_errors","init_crypto","createWeb3Passkey","config","Web3Passkey","index_default"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var q=Object.defineProperty;var T=(n,e)=>()=>(n&&(e=n(n=0)),e);var L=(n,e)=>{for(var t in e)q(n,t,{get:e[t],enumerable:!0})};var a,f,x,m,c,g,d,p=T(()=>{"use strict";a=class extends Error{constructor(t,r,s){super(t);this.code=r;this.originalError=s;this.name="Web3PasskeyError"}},f=class extends a{constructor(e,t){super(e,"AUTHENTICATION_ERROR",t),this.name="AuthenticationError"}},x=class extends a{constructor(e,t){super(e,"REGISTRATION_ERROR",t),this.name="RegistrationError"}},m=class extends a{constructor(e,t){super(e,"WALLET_ERROR",t),this.name="WalletError"}},c=class extends a{constructor(e,t){super(e,"CRYPTO_ERROR",t),this.name="CryptoError"}},g=class extends a{constructor(e,t){super(e,"STORAGE_ERROR",t),this.name="StorageError"}},d=class extends a{constructor(t,r,s){super(t,"API_ERROR",s);this.statusCode=r;this.name="ApiError"}}});var B={};L(B,{canControlStealthAddress:()=>N,deriveStealthKeys:()=>W,generateStealthAddress:()=>H});import{ethers as l}from"ethers";function W(n){try{let e=l.HDNodeWallet.fromPhrase(n,void 0,"m/44'/60'/1'/0/0"),t=l.HDNodeWallet.fromPhrase(n,void 0,"m/44'/60'/1'/0/1");return{metaAddress:M(e.signingKey.publicKey,t.signingKey.publicKey),viewingKey:e.privateKey,spendingKey:t.privateKey}}catch(e){throw new c("Failed to derive stealth keys",e)}}function H(n){try{let e=l.Wallet.createRandom(),t=l.solidityPackedKeccak256(["bytes","address"],[e.signingKey.publicKey,n]),r=new l.Wallet(t);return{stealthAddress:r.address,stealthPrivkey:r.privateKey,ephemeralPubkey:e.signingKey.publicKey}}catch(e){throw new c("Failed to generate stealth address",e)}}function N(n,e,t,r){try{let s=new l.Wallet(n),o=new l.Wallet(e),i=M(s.signingKey.publicKey,o.signingKey.publicKey),u=l.solidityPackedKeccak256(["bytes","address"],[t,i]);return new l.Wallet(u).address.toLowerCase()===r.toLowerCase()}catch{return!1}}function M(n,e){let t=l.solidityPackedKeccak256(["bytes","bytes"],[n,e]);return l.getAddress("0x"+t.slice(26))}var R=T(()=>{"use strict";p()});import{startRegistration as $,startAuthentication as O}from"@simplewebauthn/browser";p();var v=class{constructor(e,t=3e4){this.baseUrl=e;this.timeout=t}async fetchWithTimeout(e,t){let r=new AbortController,s=setTimeout(()=>r.abort(),this.timeout);try{let o=await fetch(e,{...t,signal:r.signal});return clearTimeout(s),o}catch(o){throw clearTimeout(s),o}}async post(e,t,r){try{let s=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:"POST",headers:{"Content-Type":"application/json",...r?.headers},body:JSON.stringify(t),...r});if(!s.ok)throw new d(`API request failed: ${s.statusText}`,s.status);return await s.json()}catch(s){throw s instanceof d?s:new d("Network request failed",void 0,s)}}async get(e,t){try{let r=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:"GET",headers:{"Content-Type":"application/json",...t?.headers},...t});if(!r.ok)throw new d(`API request failed: ${r.statusText}`,r.status);return await r.json()}catch(r){throw r instanceof d?r:new d("Network request failed",void 0,r)}}};p();var j="Web3PasskeyWallet",G=1,h="wallets",S=class{constructor(){this.db=null}async init(){return new Promise((e,t)=>{let r=indexedDB.open(j,G);r.onerror=()=>t(new g("Failed to open database",r.error)),r.onsuccess=()=>{this.db=r.result,e()},r.onupgradeneeded=()=>{let s=r.result;s.objectStoreNames.contains(h)||s.createObjectStore(h,{keyPath:"ethereumAddress"})}})}async store(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([h],"readwrite").objectStore(h).put(e);i.onerror=()=>r(new g("Failed to store wallet data",i.error)),i.onsuccess=()=>t()})}async retrieve(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([h],"readonly").objectStore(h).get(e);i.onerror=()=>r(new g("Failed to retrieve wallet data",i.error)),i.onsuccess=()=>t(i.result||null)})}async delete(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([h],"readwrite").objectStore(h).delete(e);i.onerror=()=>r(new g("Failed to delete wallet data",i.error)),i.onsuccess=()=>t()})}async clear(){return this.db||await this.init(),new Promise((e,t)=>{let o=this.db.transaction([h],"readwrite").objectStore(h).clear();o.onerror=()=>t(new g("Failed to clear wallet data",o.error)),o.onsuccess=()=>e()})}};p();p();import{ethers as k}from"ethers";function I(){try{let n=k.Wallet.createRandom().mnemonic;if(!n)throw new Error("Failed to generate mnemonic");let e=n.phrase;return{address:k.HDNodeWallet.fromPhrase(e,void 0,"m/44'/60'/0'/0/0").address,mnemonic:e}}catch(n){throw new m("Wallet generation failed",n)}}function D(n){try{if(!n||n.trim().split(/\s+/).length<12)throw new Error("Invalid mnemonic: must be at least 12 words");return k.HDNodeWallet.fromPhrase(n.trim(),void 0,"m/44'/60'/0'/0/0")}catch(e){throw new m(`Wallet creation failed: ${e instanceof Error?e.message:"Invalid mnemonic"}`,e)}}p();async function y(n,e){try{let t=new TextEncoder().encode(n+e),r=await crypto.subtle.importKey("raw",t,{name:"PBKDF2"},!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:new TextEncoder().encode("webauthn-wallet-salt-w3pk"),iterations:1e5,hash:"SHA-256"},r,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new c("Failed to derive encryption key",t)}}async function F(n,e){try{let t=crypto.getRandomValues(new Uint8Array(12)),r=new TextEncoder().encode(n),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:t},e,r),o=new Uint8Array(t.length+s.byteLength);return o.set(t),o.set(new Uint8Array(s),t.length),btoa(String.fromCharCode(...o))}catch(t){throw new c("Failed to encrypt data",t)}}async function E(n,e){try{if(!n||n.length<16)throw new Error("Invalid encrypted data: too small");let t=new Uint8Array(atob(n).split("").map(i=>i.charCodeAt(0)));if(t.length<12)throw new Error("Invalid encrypted data: missing IV");let r=t.slice(0,12),s=t.slice(12);if(s.length===0)throw new Error("Invalid encrypted data: no content");let o=await crypto.subtle.decrypt({name:"AES-GCM",iv:r},e,s);return new TextDecoder().decode(o)}catch(t){throw new c(`Data decryption failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}var P=class{constructor(e){this.storage=e}async signMessage(e,t,r,s){try{let o=await this.storage.retrieve(e);if(!o)throw new Error("No wallet found for this address");let i=await y(r,s),u=await E(o.encryptedMnemonic,i),w=D(u);if(w.address.toLowerCase()!==e.toLowerCase())throw new Error("Wallet address mismatch");return await w.signMessage(t)}catch(o){throw new m("Failed to sign message",o)}}async hasWallet(e){return await this.storage.retrieve(e)!==null}};p();R();var b=class{constructor(e,t){this.config=e,this.getMnemonic=t}async generateStealthAddress(){try{let e=await this.getMnemonic();if(!e)throw new f("Not authenticated. Please login first.");let t=W(e),{generateStealthAddress:r}=await Promise.resolve().then(()=>(R(),B)),s=r(t.metaAddress);return{stealthAddress:s.stealthAddress,stealthPrivateKey:s.stealthPrivkey,ephemeralPublicKey:s.ephemeralPubkey}}catch(e){throw new a("Failed to generate stealth address","STEALTH_GENERATION_ERROR",e)}}async getKeys(){try{let e=await this.getMnemonic();if(!e)throw new f("Not authenticated. Please login first.");return W(e)}catch(e){throw new a("Failed to get stealth keys","STEALTH_KEYS_ERROR",e)}}get isAvailable(){return!0}};var C={timeout:3e4,debug:!1};var A=class{constructor(e){this.currentUser=null;this.isAuthenticatedState=!1;this.stealthAddresses=null;this.isBrowser=typeof window<"u"&&typeof localStorage<"u",this.config={...C,...e,timeout:e.timeout??C.timeout,debug:e.debug??C.debug},this.apiClient=new v(this.config.apiBaseUrl,this.config.timeout),this.walletStorage=new S,this.walletSigner=new P(this.walletStorage),e.stealthAddresses&&(this.stealthAddresses=new b(e.stealthAddresses,this.getMnemonic.bind(this))),this.isBrowser?(this.walletStorage.init().catch(t=>{this.config.debug&&console.error("Failed to initialize wallet storage:",t)}),this.loadAuthState()):this.config.debug&&console.warn("w3pk: Running in non-browser environment, some features disabled")}loadAuthState(){if(this.isBrowser)try{let e=localStorage.getItem("w3pk_user"),t=localStorage.getItem("w3pk_authenticated");e&&t==="true"&&(this.currentUser=JSON.parse(e),this.isAuthenticatedState=!0,this.notifyAuthStateChange(!0,this.currentUser??void 0))}catch(e){this.config.debug&&console.error("Failed to load auth state:",e),this.clearAuthState()}}saveAuthState(e){if(!this.isBrowser){console.warn("w3pk: Cannot save auth state in non-browser environment");return}try{localStorage.setItem("w3pk_user",JSON.stringify(e)),localStorage.setItem("w3pk_authenticated","true"),this.currentUser=e,this.isAuthenticatedState=!0,this.notifyAuthStateChange(!0,e)}catch(t){this.config.debug&&console.error("Failed to save auth state:",t)}}clearAuthState(){if(this.isBrowser){try{localStorage.removeItem("w3pk_user"),localStorage.removeItem("w3pk_authenticated")}catch(e){this.config.debug&&console.error("Failed to clear auth state:",e)}this.currentUser=null,this.isAuthenticatedState=!1,this.notifyAuthStateChange(!1)}}notifyAuthStateChange(e,t){this.config.onAuthStateChanged&&this.config.onAuthStateChanged(e,t)}createUserInfo(e,t){return{id:t,username:e,displayName:e,ethereumAddress:t}}async getMnemonic(){if(!this.isBrowser||!this.currentUser)return null;try{let e=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!e)return null;let t=await y(e.credentialId,e.challenge);return await E(e.encryptedMnemonic,t)}catch(e){return this.config.debug&&console.error("Failed to get mnemonic:",e),null}}async generateWallet(){try{let e=I();return this.config.debug&&console.log("Wallet generated:",e.address),e}catch(e){throw this.config.onError&&this.config.onError(e),e}}async hasWallet(){if(!this.isBrowser)return console.warn("w3pk: Wallet storage not available in non-browser environment"),!1;if(!this.currentUser)return!1;try{return await this.walletSigner.hasWallet(this.currentUser.ethereumAddress)}catch(e){return this.config.debug&&console.error("Failed to check wallet existence:",e),!1}}async register(e){if(!this.isBrowser)throw new Error("Registration requires browser environment with WebAuthn support");try{let{username:t}=e,{ethereumAddress:r,mnemonic:s}=e;if(!r||!s){let U=I();r=U.address,s=U.mnemonic}let o=await this.apiClient.post("/webauthn/register/begin",{username:t,ethereumAddress:r});if(!o.success||!o.data)throw new Error("Failed to get registration options from server");let i=o.data.options||o.data,u=await $(i),w=await y(u.id,i.challenge),K=await F(s,w);if(await this.walletStorage.store({ethereumAddress:r,encryptedMnemonic:K,credentialId:u.id,challenge:i.challenge,createdAt:Date.now()}),!(await this.apiClient.post("/webauthn/register/complete",{ethereumAddress:r,response:u})).success)throw new Error("Registration verification failed");let _=this.createUserInfo(t,r);return this.saveAuthState(_),this.config.debug&&console.log("Registration successful for:",r),{ethereumAddress:r,mnemonic:e.mnemonic?void 0:s}}catch(t){throw this.config.onError&&this.config.onError(t),t}}async login(){if(!this.isBrowser)throw new Error("Authentication requires browser environment with WebAuthn support");try{let e=await this.apiClient.post("/webauthn/authenticate/usernameless/begin",{});if(!e.success||!e.data)throw new Error("Failed to get usernameless authentication options from server");let t=e.data.options||e.data,r=await O(t),s=await this.apiClient.post("/webauthn/authenticate/usernameless/complete",{response:r});if(!s.success)throw new Error("Usernameless authentication verification failed");let o=s.data?.user;if(!o)throw new Error("No user data received from server");let i=this.createUserInfo(o.username,o.ethereumAddress||o.id);return this.saveAuthState(i),this.config.debug&&console.log("Usernameless authentication successful for:",i.ethereumAddress),{verified:!0,user:i}}catch(e){throw this.config.onError&&this.config.onError(e),e}}logout(){this.clearAuthState(),this.config.debug&&console.log("User logged out")}async signMessage(e){if(!this.isBrowser)throw new Error("Message signing requires browser environment");if(!this.currentUser)throw new Error("Not authenticated");try{let t=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!t)throw new Error("No wallet found on this device. Please register to create a new wallet.");this.config.debug&&console.log("Requesting WebAuthn authentication for signing...");let r=await this.apiClient.post("/webauthn/authenticate/usernameless/begin",{});if(!r.success||!r.data)throw new Error("Failed to begin authentication for signing");let s=r.data.options||r.data,o=await O(s);if(!(await this.apiClient.post("/webauthn/authenticate/usernameless/complete",{response:o})).success)throw new Error("Authentication verification failed for signing");let u=await this.walletSigner.signMessage(this.currentUser.ethereumAddress,e,t.credentialId,t.challenge);return this.config.debug&&console.log("Message signed successfully"),u}catch(t){throw this.config.onError&&this.config.onError(t),t}}get isAuthenticated(){return this.isAuthenticatedState}get user(){return this.currentUser}get version(){return"0.4.0"}get isBrowserEnvironment(){return this.isBrowser}get stealth(){return this.stealthAddresses}};p();R();function J(n){return new A(n)}var Re=J;export{d as ApiError,f as AuthenticationError,c as CryptoError,x as RegistrationError,b as StealthAddressModule,g as StorageError,m as WalletError,A as Web3Passkey,a as Web3PasskeyError,N as canControlStealthAddress,J as createWeb3Passkey,Re as default};
|
|
1
|
+
var H=Object.defineProperty;var F=(s,e)=>()=>(s&&(e=s(s=0)),e);var L=(s,e)=>{for(var t in e)H(s,t,{get:e[t],enumerable:!0})};var a,f,k,g,c,m,d,p=F(()=>{"use strict";a=class extends Error{constructor(t,r,n){super(t);this.code=r;this.originalError=n;this.name="Web3PasskeyError"}},f=class extends a{constructor(e,t){super(e,"AUTHENTICATION_ERROR",t),this.name="AuthenticationError"}},k=class extends a{constructor(e,t){super(e,"REGISTRATION_ERROR",t),this.name="RegistrationError"}},g=class extends a{constructor(e,t){super(e,"WALLET_ERROR",t),this.name="WalletError"}},c=class extends a{constructor(e,t){super(e,"CRYPTO_ERROR",t),this.name="CryptoError"}},m=class extends a{constructor(e,t){super(e,"STORAGE_ERROR",t),this.name="StorageError"}},d=class extends a{constructor(t,r,n){super(t,"API_ERROR",n);this.statusCode=r;this.name="ApiError"}}});var O={};L(O,{canControlStealthAddress:()=>N,deriveStealthKeys:()=>C,generateStealthAddress:()=>G});import{ethers as l}from"ethers";function C(s){try{let e=l.HDNodeWallet.fromPhrase(s,void 0,"m/44'/60'/1'/0/0"),t=l.HDNodeWallet.fromPhrase(s,void 0,"m/44'/60'/1'/0/1");return{metaAddress:B(e.signingKey.publicKey,t.signingKey.publicKey),viewingKey:e.privateKey,spendingKey:t.privateKey}}catch(e){throw new c("Failed to derive stealth keys",e)}}function G(s){try{let e=l.Wallet.createRandom(),t=l.solidityPackedKeccak256(["bytes","address"],[e.signingKey.publicKey,s]),r=new l.Wallet(t);return{stealthAddress:r.address,stealthPrivkey:r.privateKey,ephemeralPubkey:e.signingKey.publicKey}}catch(e){throw new c("Failed to generate stealth address",e)}}function N(s,e,t,r){try{let n=new l.Wallet(s),o=new l.Wallet(e),i=B(n.signingKey.publicKey,o.signingKey.publicKey),u=l.solidityPackedKeccak256(["bytes","address"],[t,i]);return new l.Wallet(u).address.toLowerCase()===r.toLowerCase()}catch{return!1}}function B(s,e){let t=l.solidityPackedKeccak256(["bytes","bytes"],[s,e]);return l.getAddress("0x"+t.slice(26))}var x=F(()=>{"use strict";p()});import{startRegistration as J,startAuthentication as _}from"@simplewebauthn/browser";p();var A=class{constructor(e,t=3e4){this.baseUrl=e;this.timeout=t}async fetchWithTimeout(e,t){let r=new AbortController,n=setTimeout(()=>r.abort(),this.timeout);try{let o=await fetch(e,{...t,signal:r.signal});return clearTimeout(n),o}catch(o){throw clearTimeout(n),o}}async post(e,t,r){try{let n=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:"POST",headers:{"Content-Type":"application/json",...r?.headers},body:JSON.stringify(t),...r});if(!n.ok)throw new d(`API request failed: ${n.statusText}`,n.status);return await n.json()}catch(n){throw n instanceof d?n:new d("Network request failed",void 0,n)}}async get(e,t){try{let r=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:"GET",headers:{"Content-Type":"application/json",...t?.headers},...t});if(!r.ok)throw new d(`API request failed: ${r.statusText}`,r.status);return await r.json()}catch(r){throw r instanceof d?r:new d("Network request failed",void 0,r)}}};p();var $="Web3PasskeyWallet",j=1,h="wallets",S=class{constructor(){this.db=null}async init(){return new Promise((e,t)=>{let r=indexedDB.open($,j);r.onerror=()=>t(new m("Failed to open database",r.error)),r.onsuccess=()=>{this.db=r.result,e()},r.onupgradeneeded=()=>{let n=r.result;n.objectStoreNames.contains(h)||n.createObjectStore(h,{keyPath:"ethereumAddress"})}})}async store(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([h],"readwrite").objectStore(h).put(e);i.onerror=()=>r(new m("Failed to store wallet data",i.error)),i.onsuccess=()=>t()})}async retrieve(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([h],"readonly").objectStore(h).get(e);i.onerror=()=>r(new m("Failed to retrieve wallet data",i.error)),i.onsuccess=()=>t(i.result||null)})}async delete(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([h],"readwrite").objectStore(h).delete(e);i.onerror=()=>r(new m("Failed to delete wallet data",i.error)),i.onsuccess=()=>t()})}async clear(){return this.db||await this.init(),new Promise((e,t)=>{let o=this.db.transaction([h],"readwrite").objectStore(h).clear();o.onerror=()=>t(new m("Failed to clear wallet data",o.error)),o.onsuccess=()=>e()})}};p();p();import{ethers as E}from"ethers";function P(){try{let s=E.Wallet.createRandom().mnemonic;if(!s)throw new Error("Failed to generate mnemonic");let e=s.phrase;return{address:E.HDNodeWallet.fromPhrase(e,void 0,"m/44'/60'/0'/0/0").address,mnemonic:e}}catch(s){throw new g("Wallet generation failed",s)}}function K(s){try{if(!s||s.trim().split(/\s+/).length<12)throw new Error("Invalid mnemonic: must be at least 12 words");return E.HDNodeWallet.fromPhrase(s.trim(),void 0,"m/44'/60'/0'/0/0")}catch(e){throw new g(`Wallet creation failed: ${e instanceof Error?e.message:"Invalid mnemonic"}`,e)}}function U(s,e=0){try{if(!s||s.trim().split(/\s+/).length<12)throw new Error("Invalid mnemonic: must be at least 12 words");if(e<0||!Number.isInteger(e))throw new Error("Index must be a non-negative integer");let t=`m/44'/60'/0'/0/${e}`,r=E.HDNodeWallet.fromPhrase(s.trim(),void 0,t);return{address:r.address,privateKey:r.privateKey}}catch(t){throw new g(`HD wallet derivation failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}p();async function y(s,e){try{let t=new TextEncoder().encode(s+e),r=await crypto.subtle.importKey("raw",t,{name:"PBKDF2"},!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:new TextEncoder().encode("webauthn-wallet-salt-w3pk"),iterations:1e5,hash:"SHA-256"},r,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new c("Failed to derive encryption key",t)}}async function M(s,e){try{let t=crypto.getRandomValues(new Uint8Array(12)),r=new TextEncoder().encode(s),n=await crypto.subtle.encrypt({name:"AES-GCM",iv:t},e,r),o=new Uint8Array(t.length+n.byteLength);return o.set(t),o.set(new Uint8Array(n),t.length),btoa(String.fromCharCode(...o))}catch(t){throw new c("Failed to encrypt data",t)}}async function W(s,e){try{if(!s||s.length<16)throw new Error("Invalid encrypted data: too small");let t=new Uint8Array(atob(s).split("").map(i=>i.charCodeAt(0)));if(t.length<12)throw new Error("Invalid encrypted data: missing IV");let r=t.slice(0,12),n=t.slice(12);if(n.length===0)throw new Error("Invalid encrypted data: no content");let o=await crypto.subtle.decrypt({name:"AES-GCM",iv:r},e,n);return new TextDecoder().decode(o)}catch(t){throw new c(`Data decryption failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}var R=class{constructor(e){this.storage=e}async signMessage(e,t,r,n){try{let o=await this.storage.retrieve(e);if(!o)throw new Error("No wallet found for this address");let i=await y(r,n),u=await W(o.encryptedMnemonic,i),w=K(u);if(w.address.toLowerCase()!==e.toLowerCase())throw new Error("Wallet address mismatch");return await w.signMessage(t)}catch(o){throw new g("Failed to sign message",o)}}async hasWallet(e){return await this.storage.retrieve(e)!==null}};p();x();var b=class{constructor(e,t){this.config=e,this.getMnemonic=t}async generateStealthAddress(){try{let e=await this.getMnemonic();if(!e)throw new f("Not authenticated. Please login first.");let t=C(e),{generateStealthAddress:r}=await Promise.resolve().then(()=>(x(),O)),n=r(t.metaAddress);return{stealthAddress:n.stealthAddress,stealthPrivateKey:n.stealthPrivkey,ephemeralPublicKey:n.ephemeralPubkey}}catch(e){throw new a("Failed to generate stealth address","STEALTH_GENERATION_ERROR",e)}}async getKeys(){try{let e=await this.getMnemonic();if(!e)throw new f("Not authenticated. Please login first.");return C(e)}catch(e){throw new a("Failed to get stealth keys","STEALTH_KEYS_ERROR",e)}}get isAvailable(){return!0}};var I={timeout:3e4,debug:!1};var v=class{constructor(e){this.currentUser=null;this.isAuthenticatedState=!1;this.stealthAddresses=null;this.isBrowser=typeof window<"u"&&typeof localStorage<"u",this.config={...I,...e,timeout:e.timeout??I.timeout,debug:e.debug??I.debug},this.apiClient=new A(this.config.apiBaseUrl,this.config.timeout),this.walletStorage=new S,this.walletSigner=new R(this.walletStorage),e.stealthAddresses&&(this.stealthAddresses=new b(e.stealthAddresses,this.getMnemonic.bind(this))),this.isBrowser?(this.walletStorage.init().catch(t=>{this.config.debug&&console.error("Failed to initialize wallet storage:",t)}),this.loadAuthState()):this.config.debug&&console.warn("w3pk: Running in non-browser environment, some features disabled")}loadAuthState(){if(this.isBrowser)try{let e=localStorage.getItem("w3pk_user"),t=localStorage.getItem("w3pk_authenticated");e&&t==="true"&&(this.currentUser=JSON.parse(e),this.isAuthenticatedState=!0,this.notifyAuthStateChange(!0,this.currentUser??void 0))}catch(e){this.config.debug&&console.error("Failed to load auth state:",e),this.clearAuthState()}}saveAuthState(e){if(!this.isBrowser){console.warn("w3pk: Cannot save auth state in non-browser environment");return}try{localStorage.setItem("w3pk_user",JSON.stringify(e)),localStorage.setItem("w3pk_authenticated","true"),this.currentUser=e,this.isAuthenticatedState=!0,this.notifyAuthStateChange(!0,e)}catch(t){this.config.debug&&console.error("Failed to save auth state:",t)}}clearAuthState(){if(this.isBrowser){try{localStorage.removeItem("w3pk_user"),localStorage.removeItem("w3pk_authenticated")}catch(e){this.config.debug&&console.error("Failed to clear auth state:",e)}this.currentUser=null,this.isAuthenticatedState=!1,this.notifyAuthStateChange(!1)}}notifyAuthStateChange(e,t){this.config.onAuthStateChanged&&this.config.onAuthStateChanged(e,t)}createUserInfo(e,t){return{id:t,username:e,displayName:e,ethereumAddress:t}}async getMnemonic(){if(!this.isBrowser||!this.currentUser)return null;try{let e=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!e)return null;let t=await y(e.credentialId,e.challenge);return await W(e.encryptedMnemonic,t)}catch(e){return this.config.debug&&console.error("Failed to get mnemonic:",e),null}}async generateWallet(){try{let e=P();return this.config.debug&&console.log("Wallet generated:",e.address),e}catch(e){throw this.config.onError&&this.config.onError(e),e}}async hasWallet(){if(!this.isBrowser)return console.warn("w3pk: Wallet storage not available in non-browser environment"),!1;if(!this.currentUser)return!1;try{return await this.walletSigner.hasWallet(this.currentUser.ethereumAddress)}catch(e){return this.config.debug&&console.error("Failed to check wallet existence:",e),!1}}async deriveWallet(e=0){if(!this.isBrowser)throw new Error("HD wallet derivation requires browser environment");if(!this.currentUser)throw new Error("Not authenticated");try{let t=await this.getMnemonic();if(!t)throw new Error("No wallet found for this user");let r=U(t,e);return this.config.debug&&console.log(`HD wallet derived at index ${e}:`,r.address),r}catch(t){throw this.config.onError&&this.config.onError(t),t}}async register(e){if(!this.isBrowser)throw new Error("Registration requires browser environment with WebAuthn support");try{let{username:t}=e,{ethereumAddress:r,mnemonic:n}=e;if(!r||!n){let T=P();r=T.address,n=T.mnemonic}let o=await this.apiClient.post("/webauthn/register/begin",{username:t,ethereumAddress:r});if(!o.success||!o.data)throw new Error("Failed to get registration options from server");let i=o.data.options||o.data,u=await J(i),w=await y(u.id,i.challenge),D=await M(n,w);if(await this.walletStorage.store({ethereumAddress:r,encryptedMnemonic:D,credentialId:u.id,challenge:i.challenge,createdAt:Date.now()}),!(await this.apiClient.post("/webauthn/register/complete",{ethereumAddress:r,response:u})).success)throw new Error("Registration verification failed");let q=this.createUserInfo(t,r);return this.saveAuthState(q),this.config.debug&&console.log("Registration successful for:",r),{ethereumAddress:r,mnemonic:e.mnemonic?void 0:n}}catch(t){throw this.config.onError&&this.config.onError(t),t}}async login(){if(!this.isBrowser)throw new Error("Authentication requires browser environment with WebAuthn support");try{let e=await this.apiClient.post("/webauthn/authenticate/usernameless/begin",{});if(!e.success||!e.data)throw new Error("Failed to get usernameless authentication options from server");let t=e.data.options||e.data,r=await _(t),n=await this.apiClient.post("/webauthn/authenticate/usernameless/complete",{response:r});if(!n.success)throw new Error("Usernameless authentication verification failed");let o=n.data?.user;if(!o)throw new Error("No user data received from server");let i=this.createUserInfo(o.username,o.ethereumAddress||o.id);return this.saveAuthState(i),this.config.debug&&console.log("Usernameless authentication successful for:",i.ethereumAddress),{verified:!0,user:i}}catch(e){throw this.config.onError&&this.config.onError(e),e}}logout(){this.clearAuthState(),this.config.debug&&console.log("User logged out")}async signMessage(e){if(!this.isBrowser)throw new Error("Message signing requires browser environment");if(!this.currentUser)throw new Error("Not authenticated");try{let t=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!t)throw new Error("No wallet found on this device. Please register to create a new wallet.");this.config.debug&&console.log("Requesting WebAuthn authentication for signing...");let r=await this.apiClient.post("/webauthn/authenticate/usernameless/begin",{});if(!r.success||!r.data)throw new Error("Failed to begin authentication for signing");let n=r.data.options||r.data,o=await _(n);if(!(await this.apiClient.post("/webauthn/authenticate/usernameless/complete",{response:o})).success)throw new Error("Authentication verification failed for signing");let u=await this.walletSigner.signMessage(this.currentUser.ethereumAddress,e,t.credentialId,t.challenge);return this.config.debug&&console.log("Message signed successfully"),u}catch(t){throw this.config.onError&&this.config.onError(t),t}}get isAuthenticated(){return this.isAuthenticatedState}get user(){return this.currentUser}get version(){return"0.4.1"}get isBrowserEnvironment(){return this.isBrowser}get stealth(){return this.stealthAddresses}};p();x();function V(s){return new v(s)}var Ce=V;export{d as ApiError,f as AuthenticationError,c as CryptoError,k as RegistrationError,b as StealthAddressModule,m as StorageError,g as WalletError,v as Web3Passkey,a as Web3PasskeyError,N as canControlStealthAddress,K as createWalletFromMnemonic,V as createWeb3Passkey,Ce as default,U as deriveWalletFromMnemonic,P as generateBIP39Wallet};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/errors.ts","../src/stealth/crypto.ts","../src/core/sdk.ts","../src/utils/api.ts","../src/wallet/storage.ts","../src/wallet/signing.ts","../src/wallet/generate.ts","../src/wallet/crypto.ts","../src/stealth/index.ts","../src/core/config.ts","../src/index.ts"],"sourcesContent":["/**\n * Custom error classes for better error handling\n */\n\nexport class Web3PasskeyError extends Error {\n constructor(\n message: string,\n public code: string,\n public originalError?: unknown\n ) {\n super(message);\n this.name = \"Web3PasskeyError\";\n }\n}\n\nexport class AuthenticationError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"AUTHENTICATION_ERROR\", originalError);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class RegistrationError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"REGISTRATION_ERROR\", originalError);\n this.name = \"RegistrationError\";\n }\n}\n\nexport class WalletError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"WALLET_ERROR\", originalError);\n this.name = \"WalletError\";\n }\n}\n\nexport class CryptoError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"CRYPTO_ERROR\", originalError);\n this.name = \"CryptoError\";\n }\n}\n\nexport class StorageError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"STORAGE_ERROR\", originalError);\n this.name = \"StorageError\";\n }\n}\n\nexport class ApiError extends Web3PasskeyError {\n constructor(\n message: string,\n public statusCode?: number,\n originalError?: unknown\n ) {\n super(message, \"API_ERROR\", originalError);\n this.name = \"ApiError\";\n }\n}\n","/**\n * Stealth address cryptography for privacy-preserving transactions\n */\n\nimport { ethers } from \"ethers\";\nimport { CryptoError } from \"../core/errors\";\n\nexport interface StealthKeys {\n metaAddress: string;\n viewingKey: string;\n spendingKey: string;\n}\n\nexport interface StealthAddressResult {\n stealthAddress: string;\n stealthPrivkey: string;\n ephemeralPubkey: string;\n}\n\n/**\n * Derive stealth keys from w3pk mnemonic using HD paths\n */\nexport function deriveStealthKeys(mnemonic: string): StealthKeys {\n try {\n // Use specific derivation paths for stealth keys\n const viewingWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic,\n undefined,\n \"m/44'/60'/1'/0/0\" // Viewing key path\n );\n\n const spendingWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic,\n undefined,\n \"m/44'/60'/1'/0/1\" // Spending key path\n );\n\n // Meta address is derived from viewing key\n const metaAddress = computeMetaAddress(\n viewingWallet.signingKey.publicKey,\n spendingWallet.signingKey.publicKey\n );\n\n return {\n metaAddress,\n viewingKey: viewingWallet.privateKey,\n spendingKey: spendingWallet.privateKey,\n };\n } catch (error) {\n throw new CryptoError(\"Failed to derive stealth keys\", error);\n }\n}\n\n/**\n * Generate a stealth address using ECDH\n */\nexport function generateStealthAddress(\n metaAddress: string\n): StealthAddressResult {\n try {\n // Generate ephemeral keypair\n const ephemeralWallet = ethers.Wallet.createRandom();\n\n // For simplified implementation, derive stealth address from ephemeral key + meta address\n const stealthSeed = ethers.solidityPackedKeccak256(\n [\"bytes\", \"address\"],\n [ephemeralWallet.signingKey.publicKey, metaAddress]\n );\n\n const stealthWallet = new ethers.Wallet(stealthSeed);\n\n return {\n stealthAddress: stealthWallet.address,\n stealthPrivkey: stealthWallet.privateKey,\n ephemeralPubkey: ephemeralWallet.signingKey.publicKey,\n };\n } catch (error) {\n throw new CryptoError(\"Failed to generate stealth address\", error);\n }\n}\n\n/**\n * Check if a stealth address can be controlled by the stealth keys\n * Useful for scanning and proving ownership of stealth addresses\n */\nexport function canControlStealthAddress(\n viewingKey: string,\n spendingKey: string,\n ephemeralPubkey: string,\n targetAddress: string\n): boolean {\n try {\n // Reconstruct stealth address using both viewing and spending keys\n const viewingWallet = new ethers.Wallet(viewingKey);\n const spendingWallet = new ethers.Wallet(spendingKey);\n \n const metaAddress = computeMetaAddress(\n viewingWallet.signingKey.publicKey,\n spendingWallet.signingKey.publicKey\n );\n\n const stealthSeed = ethers.solidityPackedKeccak256(\n [\"bytes\", \"address\"],\n [ephemeralPubkey, metaAddress]\n );\n\n const derivedWallet = new ethers.Wallet(stealthSeed);\n\n return derivedWallet.address.toLowerCase() === targetAddress.toLowerCase();\n } catch (error) {\n return false;\n }\n}\n\n/**\n * Compute meta address from public keys (simplified)\n */\nfunction computeMetaAddress(\n viewingPubkey: string,\n spendingPubkey: string\n): string {\n const combined = ethers.solidityPackedKeccak256(\n [\"bytes\", \"bytes\"],\n [viewingPubkey, spendingPubkey]\n );\n\n // Take first 20 bytes as address\n return ethers.getAddress(\"0x\" + combined.slice(26));\n}\n","/**\n * Main Web3Passkey SDK class\n */\n\nimport {\n startRegistration,\n startAuthentication,\n} from \"@simplewebauthn/browser\";\nimport { ApiClient } from \"../utils/api\";\nimport { IndexedDBWalletStorage } from \"../wallet/storage\";\nimport { WalletSigner } from \"../wallet/signing\";\nimport { generateBIP39Wallet } from \"../wallet/generate\";\nimport {\n deriveEncryptionKey,\n encryptData,\n decryptData,\n} from \"../wallet/crypto\";\nimport { StealthAddressModule } from \"../stealth\";\nimport type {\n Web3PasskeyConfig,\n InternalConfig,\n StealthAddressConfig,\n} from \"./config\";\nimport { DEFAULT_CONFIG } from \"./config\";\nimport type { UserInfo, WalletInfo } from \"../types\";\n\nexport interface AuthResult {\n verified: boolean;\n user?: UserInfo;\n}\n\nexport class Web3Passkey {\n private config: InternalConfig;\n private apiClient: ApiClient;\n private walletStorage: IndexedDBWalletStorage;\n private walletSigner: WalletSigner;\n private currentUser: UserInfo | null = null;\n private isAuthenticatedState: boolean = false;\n private isBrowser: boolean;\n private stealthAddresses: StealthAddressModule | null = null;\n\n constructor(config: Web3PasskeyConfig) {\n // Check if running in browser\n this.isBrowser =\n typeof window !== \"undefined\" && typeof localStorage !== \"undefined\";\n\n // Merge with defaults\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n timeout: config.timeout ?? DEFAULT_CONFIG.timeout!,\n debug: config.debug ?? DEFAULT_CONFIG.debug!,\n } as InternalConfig;\n\n // Initialize components\n this.apiClient = new ApiClient(this.config.apiBaseUrl, this.config.timeout);\n this.walletStorage = new IndexedDBWalletStorage();\n this.walletSigner = new WalletSigner(this.walletStorage);\n\n // Initialize stealth addresses if configured\n if (config.stealthAddresses) {\n this.stealthAddresses = new StealthAddressModule(\n config.stealthAddresses,\n this.getMnemonic.bind(this)\n );\n }\n\n // Initialize storage only in browser\n if (this.isBrowser) {\n this.walletStorage.init().catch((error) => {\n if (this.config.debug) {\n console.error(\"Failed to initialize wallet storage:\", error);\n }\n });\n\n // Load persisted auth state\n this.loadAuthState();\n } else if (this.config.debug) {\n console.warn(\n \"w3pk: Running in non-browser environment, some features disabled\"\n );\n }\n }\n\n // ========================================\n // Auth State Management\n // ========================================\n\n private loadAuthState(): void {\n if (!this.isBrowser) return;\n\n try {\n const storedUser = localStorage.getItem(\"w3pk_user\");\n const storedAuth = localStorage.getItem(\"w3pk_authenticated\");\n\n if (storedUser && storedAuth === \"true\") {\n this.currentUser = JSON.parse(storedUser);\n this.isAuthenticatedState = true;\n this.notifyAuthStateChange(true, this.currentUser ?? undefined);\n }\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to load auth state:\", error);\n }\n this.clearAuthState();\n }\n }\n\n private saveAuthState(user: UserInfo): void {\n if (!this.isBrowser) {\n console.warn(\"w3pk: Cannot save auth state in non-browser environment\");\n return;\n }\n\n try {\n localStorage.setItem(\"w3pk_user\", JSON.stringify(user));\n localStorage.setItem(\"w3pk_authenticated\", \"true\");\n this.currentUser = user;\n this.isAuthenticatedState = true;\n this.notifyAuthStateChange(true, user);\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to save auth state:\", error);\n }\n }\n }\n\n private clearAuthState(): void {\n if (!this.isBrowser) return;\n\n try {\n localStorage.removeItem(\"w3pk_user\");\n localStorage.removeItem(\"w3pk_authenticated\");\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to clear auth state:\", error);\n }\n }\n\n this.currentUser = null;\n this.isAuthenticatedState = false;\n this.notifyAuthStateChange(false);\n }\n\n private notifyAuthStateChange(\n isAuthenticated: boolean,\n user?: UserInfo\n ): void {\n if (this.config.onAuthStateChanged) {\n this.config.onAuthStateChanged(isAuthenticated, user);\n }\n }\n\n private createUserInfo(username: string, ethereumAddress: string): UserInfo {\n return {\n id: ethereumAddress,\n username,\n displayName: username,\n ethereumAddress,\n };\n }\n\n /**\n * Get mnemonic for current authenticated user\n * Used by stealth address module\n */\n private async getMnemonic(): Promise<string | null> {\n if (!this.isBrowser || !this.currentUser) {\n return null;\n }\n\n try {\n // Get encrypted wallet data\n const walletData = await this.walletStorage.retrieve(\n this.currentUser.ethereumAddress\n );\n if (!walletData) {\n return null;\n }\n\n // Derive encryption key from stored credentials\n const encryptionKey = await deriveEncryptionKey(\n walletData.credentialId,\n walletData.challenge\n );\n\n // Decrypt mnemonic\n return await decryptData(walletData.encryptedMnemonic, encryptionKey);\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to get mnemonic:\", error);\n }\n return null;\n }\n }\n\n // ========================================\n // Public API - Wallet\n // ========================================\n\n /**\n * Generate a new BIP39 wallet\n * @returns Wallet info with mnemonic (user MUST backup)\n */\n async generateWallet(): Promise<WalletInfo> {\n try {\n const wallet = generateBIP39Wallet();\n\n if (this.config.debug) {\n console.log(\"Wallet generated:\", wallet.address);\n }\n\n return wallet;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Check if wallet exists for current user\n */\n async hasWallet(): Promise<boolean> {\n if (!this.isBrowser) {\n console.warn(\n \"w3pk: Wallet storage not available in non-browser environment\"\n );\n return false;\n }\n\n if (!this.currentUser) {\n return false;\n }\n\n try {\n return await this.walletSigner.hasWallet(\n this.currentUser.ethereumAddress\n );\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to check wallet existence:\", error);\n }\n return false;\n }\n }\n\n // ========================================\n // Public API - Authentication\n // ========================================\n\n /**\n * Register a new user with WebAuthn\n * Handles the complete registration flow internally\n * Automatically generates wallet if not provided\n *\n * @param username Username for the account\n * @param ethereumAddress Optional: Ethereum address (will generate if not provided)\n * @param mnemonic Optional: BIP39 mnemonic (will generate if not provided)\n * @returns Object containing ethereumAddress and mnemonic (only if generated)\n */\n async register(options: {\n username: string;\n ethereumAddress?: string;\n mnemonic?: string;\n }): Promise<{ ethereumAddress: string; mnemonic?: string }> {\n if (!this.isBrowser) {\n throw new Error(\n \"Registration requires browser environment with WebAuthn support\"\n );\n }\n\n try {\n const { username } = options;\n let { ethereumAddress, mnemonic } = options;\n\n // Generate wallet if not provided\n if (!ethereumAddress || !mnemonic) {\n const wallet = generateBIP39Wallet();\n ethereumAddress = wallet.address;\n mnemonic = wallet.mnemonic;\n }\n\n // Step 1: Begin registration - get WebAuthn options from server\n const beginResponse = await this.apiClient.post(\n \"/webauthn/register/begin\",\n {\n username,\n ethereumAddress,\n }\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\"Failed to get registration options from server\");\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 2: Perform WebAuthn registration (browser prompt)\n const credential = await startRegistration(webauthnOptions);\n\n // Step 3: Encrypt mnemonic with WebAuthn-derived key\n const encryptionKey = await deriveEncryptionKey(\n credential.id,\n webauthnOptions.challenge\n );\n const encryptedMnemonic = await encryptData(mnemonic, encryptionKey);\n\n // Step 4: Store encrypted mnemonic in IndexedDB\n await this.walletStorage.store({\n ethereumAddress,\n encryptedMnemonic,\n credentialId: credential.id,\n challenge: webauthnOptions.challenge,\n createdAt: Date.now(),\n });\n\n // Step 5: Complete registration with server\n const completeResponse = await this.apiClient.post(\n \"/webauthn/register/complete\",\n {\n ethereumAddress,\n response: credential,\n }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Registration verification failed\");\n }\n\n // Step 6: Save auth state with displayName\n const user = this.createUserInfo(username, ethereumAddress);\n this.saveAuthState(user);\n\n if (this.config.debug) {\n console.log(\"Registration successful for:\", ethereumAddress);\n }\n\n // Return the wallet info (mnemonic only if we generated it)\n return {\n ethereumAddress,\n mnemonic: options.mnemonic ? undefined : mnemonic,\n };\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Authenticate without username (usernameless flow)\n */\n async login(): Promise<AuthResult> {\n if (!this.isBrowser) {\n throw new Error(\n \"Authentication requires browser environment with WebAuthn support\"\n );\n }\n\n try {\n // Step 1: Begin usernameless authentication\n const beginResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/begin\",\n {}\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\n \"Failed to get usernameless authentication options from server\"\n );\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 2: WebAuthn authentication\n const credential = await startAuthentication(webauthnOptions);\n\n // Step 3: Complete authentication\n const completeResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/complete\",\n { response: credential }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Usernameless authentication verification failed\");\n }\n\n const serverUser = completeResponse.data?.user;\n if (!serverUser) {\n throw new Error(\"No user data received from server\");\n }\n\n // Create UserInfo with displayName\n const user = this.createUserInfo(\n serverUser.username,\n serverUser.ethereumAddress || serverUser.id\n );\n this.saveAuthState(user);\n\n if (this.config.debug) {\n console.log(\n \"Usernameless authentication successful for:\",\n user.ethereumAddress\n );\n }\n\n return {\n verified: true,\n user,\n };\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Logout current user\n */\n logout(): void {\n this.clearAuthState();\n\n if (this.config.debug) {\n console.log(\"User logged out\");\n }\n }\n\n // ========================================\n // Public API - Message Signing\n // ========================================\n\n /**\n * Sign a message with encrypted wallet\n * Handles fresh WebAuthn authentication internally\n *\n * @param message Message to sign\n */\n async signMessage(message: string): Promise<string> {\n if (!this.isBrowser) {\n throw new Error(\"Message signing requires browser environment\");\n }\n\n if (!this.currentUser) {\n throw new Error(\"Not authenticated\");\n }\n\n try {\n // Step 1: Check if wallet exists\n const walletData = await this.walletStorage.retrieve(\n this.currentUser.ethereumAddress\n );\n if (!walletData) {\n throw new Error(\n \"No wallet found on this device. Please register to create a new wallet.\"\n );\n }\n\n // Step 2: Request fresh WebAuthn authentication\n if (this.config.debug) {\n console.log(\"Requesting WebAuthn authentication for signing...\");\n }\n\n const beginResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/begin\",\n {}\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\"Failed to begin authentication for signing\");\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 3: Perform WebAuthn authentication (browser prompt)\n const credential = await startAuthentication(webauthnOptions);\n\n // Step 4: Verify authentication with server\n const completeResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/complete\",\n { response: credential }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Authentication verification failed for signing\");\n }\n\n // Step 5: Use the authenticated credentials to sign\n const signature = await this.walletSigner.signMessage(\n this.currentUser.ethereumAddress,\n message,\n walletData.credentialId,\n walletData.challenge\n );\n\n if (this.config.debug) {\n console.log(\"Message signed successfully\");\n }\n\n return signature;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n // ========================================\n // Public API - Getters\n // ========================================\n\n /**\n * Check if user is authenticated\n */\n get isAuthenticated(): boolean {\n return this.isAuthenticatedState;\n }\n\n /**\n * Get current user info\n */\n get user(): UserInfo | null {\n return this.currentUser;\n }\n\n /**\n * Get SDK version\n */\n get version(): string {\n return \"0.4.0\";\n }\n\n /**\n * Check if running in browser environment\n */\n get isBrowserEnvironment(): boolean {\n return this.isBrowser;\n }\n\n /**\n * Get stealth address module (if configured)\n */\n get stealth(): StealthAddressModule | null {\n return this.stealthAddresses;\n }\n}\n","/**\n * API client for backend communication\n */\n\nimport { ApiError } from \"../core/errors\";\nimport type { ApiResponse } from \"../types\";\n\nexport class ApiClient {\n constructor(private baseUrl: string, private timeout: number = 30000) {}\n\n private async fetchWithTimeout(\n url: string,\n options: RequestInit\n ): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n async post<T = any>(\n endpoint: string,\n body: any,\n options?: RequestInit\n ): Promise<ApiResponse<T>> {\n try {\n const response = await this.fetchWithTimeout(\n `${this.baseUrl}${endpoint}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n body: JSON.stringify(body),\n ...options,\n }\n );\n\n if (!response.ok) {\n throw new ApiError(\n `API request failed: ${response.statusText}`,\n response.status\n );\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n throw new ApiError(\"Network request failed\", undefined, error);\n }\n }\n\n async get<T = any>(\n endpoint: string,\n options?: RequestInit\n ): Promise<ApiResponse<T>> {\n try {\n const response = await this.fetchWithTimeout(\n `${this.baseUrl}${endpoint}`,\n {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n ...options,\n }\n );\n\n if (!response.ok) {\n throw new ApiError(\n `API request failed: ${response.statusText}`,\n response.status\n );\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n throw new ApiError(\"Network request failed\", undefined, error);\n }\n }\n}\n","/**\n * IndexedDB storage for encrypted wallet data\n */\n\nimport { StorageError } from \"../core/errors\";\nimport type { EncryptedWalletData, WalletStorage } from \"./types\";\n\nconst DB_NAME = \"Web3PasskeyWallet\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"wallets\";\n\nexport class IndexedDBWalletStorage implements WalletStorage {\n private db: IDBDatabase | null = null;\n\n async init(): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n\n request.onerror = () =>\n reject(new StorageError(\"Failed to open database\", request.error));\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: \"ethereumAddress\" });\n }\n };\n });\n }\n\n async store(data: EncryptedWalletData): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.put(data);\n request.onerror = () =>\n reject(new StorageError(\"Failed to store wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n\n async retrieve(ethereumAddress: string): Promise<EncryptedWalletData | null> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readonly\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.get(ethereumAddress);\n request.onerror = () =>\n reject(\n new StorageError(\"Failed to retrieve wallet data\", request.error)\n );\n request.onsuccess = () => resolve(request.result || null);\n });\n }\n\n async delete(ethereumAddress: string): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.delete(ethereumAddress);\n request.onerror = () =>\n reject(new StorageError(\"Failed to delete wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n\n async clear(): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.clear();\n request.onerror = () =>\n reject(new StorageError(\"Failed to clear wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n}\n","/**\n * Message signing with encrypted wallet\n */\n\nimport { WalletError } from \"../core/errors\";\nimport { createWalletFromMnemonic } from \"./generate\";\nimport { deriveEncryptionKey, decryptData } from \"./crypto\";\nimport type { IndexedDBWalletStorage } from \"./storage\";\n\nexport class WalletSigner {\n constructor(private storage: IndexedDBWalletStorage) {}\n\n /**\n * Sign a message with the encrypted wallet\n * Requires fresh WebAuthn authentication\n */\n async signMessage(\n ethereumAddress: string,\n message: string,\n credentialId: string,\n challenge: string\n ): Promise<string> {\n try {\n // Retrieve encrypted wallet data\n const walletData = await this.storage.retrieve(ethereumAddress);\n if (!walletData) {\n throw new Error(\"No wallet found for this address\");\n }\n\n // Derive encryption key from WebAuthn credentials\n const encryptionKey = await deriveEncryptionKey(credentialId, challenge);\n\n // Decrypt mnemonic\n const mnemonic = await decryptData(\n walletData.encryptedMnemonic,\n encryptionKey\n );\n\n // Create wallet from mnemonic\n const wallet = createWalletFromMnemonic(mnemonic);\n\n // Verify address matches\n if (wallet.address.toLowerCase() !== ethereumAddress.toLowerCase()) {\n throw new Error(\"Wallet address mismatch\");\n }\n\n // Sign message\n const signature = await wallet.signMessage(message);\n\n // Clear mnemonic from memory (wallet will be garbage collected)\n return signature;\n } catch (error) {\n throw new WalletError(\"Failed to sign message\", error);\n }\n }\n\n /**\n * Check if wallet exists for address\n */\n async hasWallet(ethereumAddress: string): Promise<boolean> {\n const walletData = await this.storage.retrieve(ethereumAddress);\n return walletData !== null;\n }\n}\n","/**\n * BIP39 wallet generation\n */\n\nimport { ethers } from \"ethers\";\nimport { WalletError } from \"../core/errors\";\nimport type { WalletData } from \"./types\";\n\n/**\n * Generates a new BIP39 wallet with HD derivation\n * Uses BIP44 path: m/44'/60'/0'/0/0 for Ethereum\n */\nexport function generateBIP39Wallet(): WalletData {\n try {\n // Generate random mnemonic using ethers' utility\n const mnemonic = ethers.Wallet.createRandom().mnemonic;\n\n if (!mnemonic) {\n throw new Error(\"Failed to generate mnemonic\");\n }\n\n const mnemonicPhrase = mnemonic.phrase;\n\n // Create HD wallet from mnemonic phrase with derivation path\n const derivationPath = \"m/44'/60'/0'/0/0\";\n const hdWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonicPhrase,\n undefined,\n derivationPath\n );\n\n return {\n address: hdWallet.address,\n mnemonic: mnemonicPhrase,\n };\n } catch (error) {\n throw new WalletError(\"Wallet generation failed\", error);\n }\n}\n\n/**\n * Creates wallet from mnemonic phrase\n * Uses BIP44 path: m/44'/60'/0'/0/0\n */\nexport function createWalletFromMnemonic(\n mnemonic: string\n): ethers.HDNodeWallet {\n try {\n if (!mnemonic || mnemonic.trim().split(/\\s+/).length < 12) {\n throw new Error(\"Invalid mnemonic: must be at least 12 words\");\n }\n\n // Create HD wallet with derivation path directly\n const derivationPath = \"m/44'/60'/0'/0/0\";\n const wallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic.trim(),\n undefined,\n derivationPath\n );\n\n return wallet;\n } catch (error) {\n throw new WalletError(\n `Wallet creation failed: ${\n error instanceof Error ? error.message : \"Invalid mnemonic\"\n }`,\n error\n );\n }\n}\n","/**\n * Cryptographic utilities for wallet encryption\n */\n\nimport { CryptoError } from \"../core/errors\";\n\n/**\n * Derives an encryption key from WebAuthn credential data\n */\nexport async function deriveEncryptionKey(\n credentialId: string,\n challenge: string\n): Promise<CryptoKey> {\n try {\n const keyMaterial = new TextEncoder().encode(credentialId + challenge);\n\n const importedKey = await crypto.subtle.importKey(\n \"raw\",\n keyMaterial,\n { name: \"PBKDF2\" },\n false,\n [\"deriveKey\"]\n );\n\n return crypto.subtle.deriveKey(\n {\n name: \"PBKDF2\",\n salt: new TextEncoder().encode(\"webauthn-wallet-salt-w3pk\"),\n iterations: 100000,\n hash: \"SHA-256\",\n },\n importedKey,\n { name: \"AES-GCM\", length: 256 },\n false,\n [\"encrypt\", \"decrypt\"]\n );\n } catch (error) {\n throw new CryptoError(\"Failed to derive encryption key\", error);\n }\n}\n\n/**\n * Encrypts data using AES-GCM\n */\nexport async function encryptData(\n data: string,\n key: CryptoKey\n): Promise<string> {\n try {\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const encodedData = new TextEncoder().encode(data);\n\n const encrypted = await crypto.subtle.encrypt(\n { name: \"AES-GCM\", iv },\n key,\n encodedData\n );\n\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\n combined.set(iv);\n combined.set(new Uint8Array(encrypted), iv.length);\n\n return btoa(String.fromCharCode(...combined));\n } catch (error) {\n throw new CryptoError(\"Failed to encrypt data\", error);\n }\n}\n\n/**\n * Decrypts data using AES-GCM\n */\nexport async function decryptData(\n encryptedData: string,\n key: CryptoKey\n): Promise<string> {\n try {\n if (!encryptedData || encryptedData.length < 16) {\n throw new Error(\"Invalid encrypted data: too small\");\n }\n\n const combined = new Uint8Array(\n atob(encryptedData)\n .split(\"\")\n .map((char) => char.charCodeAt(0))\n );\n\n if (combined.length < 12) {\n throw new Error(\"Invalid encrypted data: missing IV\");\n }\n\n const iv = combined.slice(0, 12);\n const encrypted = combined.slice(12);\n\n if (encrypted.length === 0) {\n throw new Error(\"Invalid encrypted data: no content\");\n }\n\n const decrypted = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv },\n key,\n encrypted\n );\n\n return new TextDecoder().decode(decrypted);\n } catch (error) {\n throw new CryptoError(\n `Data decryption failed: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n error\n );\n }\n}\n","/**\n * Stealth Address Module for w3pk SDK\n * Provides privacy-preserving stealth address generation capabilities\n */\n\nimport { ethers } from \"ethers\";\nimport { Web3PasskeyError, AuthenticationError } from \"../core/errors\";\nimport { deriveStealthKeys } from \"./crypto\";\nimport type { StealthKeys } from \"./crypto\";\n\nexport interface StealthAddressConfig {\n // Network-agnostic - no provider needed\n}\n\nexport interface StealthAddressResult {\n stealthAddress: string;\n stealthPrivateKey: string;\n ephemeralPublicKey: string;\n}\n\n/**\n * Main Stealth Address Module\n * Integrates with w3pk WebAuthn for seamless privacy-preserving stealth address generation\n */\nexport class StealthAddressModule {\n private config: StealthAddressConfig;\n private getMnemonic: () => Promise<string | null>;\n\n constructor(config: StealthAddressConfig, getMnemonic: () => Promise<string | null>) {\n this.config = config;\n this.getMnemonic = getMnemonic;\n }\n\n // ========================================\n // Stealth Address Generation\n // ========================================\n\n /**\n * Generate a fresh stealth address for privacy-preserving transactions\n * Returns the stealth address and private key for the user to handle transactions\n */\n async generateStealthAddress(): Promise<StealthAddressResult> {\n try {\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new AuthenticationError(\"Not authenticated. Please login first.\");\n }\n\n const stealthKeys = deriveStealthKeys(mnemonic);\n const { generateStealthAddress } = await import(\"./crypto\");\n const stealthResult = generateStealthAddress(stealthKeys.metaAddress);\n\n return {\n stealthAddress: stealthResult.stealthAddress,\n stealthPrivateKey: stealthResult.stealthPrivkey,\n ephemeralPublicKey: stealthResult.ephemeralPubkey\n };\n } catch (error) {\n throw new Web3PasskeyError(\n \"Failed to generate stealth address\",\n \"STEALTH_GENERATION_ERROR\",\n error\n );\n }\n }\n\n\n // ========================================\n // Privacy & Key Management\n // ========================================\n\n /**\n * Get stealth keys for manual operations\n */\n async getKeys(): Promise<StealthKeys> {\n try {\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new AuthenticationError(\"Not authenticated. Please login first.\");\n }\n\n return deriveStealthKeys(mnemonic);\n } catch (error) {\n throw new Web3PasskeyError(\n \"Failed to get stealth keys\",\n \"STEALTH_KEYS_ERROR\",\n error\n );\n }\n }\n\n // ========================================\n // Status & Management\n // ========================================\n\n /**\n * Check if stealth addresses are available (always true if properly configured)\n */\n get isAvailable(): boolean {\n return true;\n }\n}\n\n// Export types for stealth module\nexport type { StealthKeys };","/**\n * SDK Configuration\n */\n\nimport type { UserInfo } from \"../types\";\nimport type { Web3PasskeyError } from \"./errors\";\nimport type { ethers } from \"ethers\";\n\nexport interface StealthAddressConfig {}\n\nexport interface Web3PasskeyConfig {\n /**\n * Base URL of the WebAuthn API\n * @example 'https://webauthn.w3hc.org'\n */\n apiBaseUrl: string;\n\n /**\n * Timeout for API requests in milliseconds\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom error handler\n */\n onError?: (error: Web3PasskeyError) => void;\n\n /**\n * Auth state change callback\n */\n onAuthStateChanged?: (isAuthenticated: boolean, user?: UserInfo) => void;\n\n /**\n * Optional stealth address configuration\n * If provided, enables privacy-preserving stealth address generation\n */\n stealthAddresses?: StealthAddressConfig;\n}\n\nexport interface InternalConfig extends Required<Web3PasskeyConfig> {\n // Normalized config with all defaults applied\n}\n\nexport const DEFAULT_CONFIG: Partial<Web3PasskeyConfig> = {\n timeout: 30000,\n debug: false,\n};\n","/**\n * w3pk - Web3 Passkey SDK\n * WebAuthn SDK for passwordless authentication and encrypted wallet management\n */\n\nimport { Web3Passkey } from \"./core/sdk\";\nimport type { Web3PasskeyConfig } from \"./core/config\";\n\n// Main factory function\nexport function createWeb3Passkey(config: Web3PasskeyConfig): Web3Passkey {\n return new Web3Passkey(config);\n}\n\n// Export types\nexport type { Web3PasskeyConfig, StealthAddressConfig } from \"./core/config\";\nexport type { UserInfo, WalletInfo } from \"./types\";\nexport type { StealthKeys, StealthAddressResult } from \"./stealth\";\n\n// Export errors for custom error handling\nexport {\n Web3PasskeyError,\n AuthenticationError,\n RegistrationError,\n WalletError,\n CryptoError,\n StorageError,\n ApiError,\n} from \"./core/errors\";\n\n// Export SDK class for advanced usage\nexport { Web3Passkey } from \"./core/sdk\";\n\n// Export stealth address module for advanced usage\nexport { StealthAddressModule } from \"./stealth\";\n\n// Export crypto utilities\nexport { canControlStealthAddress } from \"./stealth/crypto\";\n\n// Default export\nexport default createWeb3Passkey;\n"],"mappings":"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","names":["Web3PasskeyError","AuthenticationError","RegistrationError","WalletError","CryptoError","StorageError","ApiError","init_errors","__esmMin","message","code","originalError","statusCode","crypto_exports","__export","canControlStealthAddress","deriveStealthKeys","generateStealthAddress","ethers","mnemonic","viewingWallet","spendingWallet","computeMetaAddress","error","CryptoError","metaAddress","ephemeralWallet","stealthSeed","stealthWallet","viewingKey","spendingKey","ephemeralPubkey","targetAddress","viewingPubkey","spendingPubkey","combined","init_crypto","__esmMin","init_errors","startRegistration","startAuthentication","init_errors","ApiClient","baseUrl","timeout","url","options","controller","timeoutId","response","error","endpoint","body","ApiError","init_errors","DB_NAME","DB_VERSION","STORE_NAME","IndexedDBWalletStorage","resolve","reject","request","StorageError","db","data","ethereumAddress","init_errors","init_errors","ethers","generateBIP39Wallet","mnemonic","mnemonicPhrase","error","WalletError","createWalletFromMnemonic","init_errors","deriveEncryptionKey","credentialId","challenge","keyMaterial","importedKey","error","CryptoError","encryptData","data","key","iv","encodedData","encrypted","combined","decryptData","encryptedData","char","decrypted","WalletSigner","storage","ethereumAddress","message","credentialId","challenge","walletData","encryptionKey","deriveEncryptionKey","mnemonic","decryptData","wallet","createWalletFromMnemonic","error","WalletError","init_errors","init_crypto","StealthAddressModule","config","getMnemonic","mnemonic","AuthenticationError","stealthKeys","deriveStealthKeys","generateStealthAddress","stealthResult","error","Web3PasskeyError","DEFAULT_CONFIG","Web3Passkey","config","DEFAULT_CONFIG","ApiClient","IndexedDBWalletStorage","WalletSigner","StealthAddressModule","error","storedUser","storedAuth","user","isAuthenticated","username","ethereumAddress","walletData","encryptionKey","deriveEncryptionKey","decryptData","wallet","generateBIP39Wallet","options","mnemonic","beginResponse","webauthnOptions","credential","startRegistration","encryptedMnemonic","encryptData","startAuthentication","completeResponse","serverUser","message","signature","init_errors","init_crypto","createWeb3Passkey","config","Web3Passkey","index_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/errors.ts","../src/stealth/crypto.ts","../src/core/sdk.ts","../src/utils/api.ts","../src/wallet/storage.ts","../src/wallet/signing.ts","../src/wallet/generate.ts","../src/wallet/crypto.ts","../src/stealth/index.ts","../src/core/config.ts","../src/index.ts"],"sourcesContent":["/**\n * Custom error classes for better error handling\n */\n\nexport class Web3PasskeyError extends Error {\n constructor(\n message: string,\n public code: string,\n public originalError?: unknown\n ) {\n super(message);\n this.name = \"Web3PasskeyError\";\n }\n}\n\nexport class AuthenticationError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"AUTHENTICATION_ERROR\", originalError);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class RegistrationError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"REGISTRATION_ERROR\", originalError);\n this.name = \"RegistrationError\";\n }\n}\n\nexport class WalletError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"WALLET_ERROR\", originalError);\n this.name = \"WalletError\";\n }\n}\n\nexport class CryptoError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"CRYPTO_ERROR\", originalError);\n this.name = \"CryptoError\";\n }\n}\n\nexport class StorageError extends Web3PasskeyError {\n constructor(message: string, originalError?: unknown) {\n super(message, \"STORAGE_ERROR\", originalError);\n this.name = \"StorageError\";\n }\n}\n\nexport class ApiError extends Web3PasskeyError {\n constructor(\n message: string,\n public statusCode?: number,\n originalError?: unknown\n ) {\n super(message, \"API_ERROR\", originalError);\n this.name = \"ApiError\";\n }\n}\n","/**\n * Stealth address cryptography for privacy-preserving transactions\n */\n\nimport { ethers } from \"ethers\";\nimport { CryptoError } from \"../core/errors\";\n\nexport interface StealthKeys {\n metaAddress: string;\n viewingKey: string;\n spendingKey: string;\n}\n\nexport interface StealthAddressResult {\n stealthAddress: string;\n stealthPrivkey: string;\n ephemeralPubkey: string;\n}\n\n/**\n * Derive stealth keys from w3pk mnemonic using HD paths\n */\nexport function deriveStealthKeys(mnemonic: string): StealthKeys {\n try {\n // Use specific derivation paths for stealth keys\n const viewingWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic,\n undefined,\n \"m/44'/60'/1'/0/0\" // Viewing key path\n );\n\n const spendingWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic,\n undefined,\n \"m/44'/60'/1'/0/1\" // Spending key path\n );\n\n // Meta address is derived from viewing key\n const metaAddress = computeMetaAddress(\n viewingWallet.signingKey.publicKey,\n spendingWallet.signingKey.publicKey\n );\n\n return {\n metaAddress,\n viewingKey: viewingWallet.privateKey,\n spendingKey: spendingWallet.privateKey,\n };\n } catch (error) {\n throw new CryptoError(\"Failed to derive stealth keys\", error);\n }\n}\n\n/**\n * Generate a stealth address using ECDH\n */\nexport function generateStealthAddress(\n metaAddress: string\n): StealthAddressResult {\n try {\n // Generate ephemeral keypair\n const ephemeralWallet = ethers.Wallet.createRandom();\n\n // For simplified implementation, derive stealth address from ephemeral key + meta address\n const stealthSeed = ethers.solidityPackedKeccak256(\n [\"bytes\", \"address\"],\n [ephemeralWallet.signingKey.publicKey, metaAddress]\n );\n\n const stealthWallet = new ethers.Wallet(stealthSeed);\n\n return {\n stealthAddress: stealthWallet.address,\n stealthPrivkey: stealthWallet.privateKey,\n ephemeralPubkey: ephemeralWallet.signingKey.publicKey,\n };\n } catch (error) {\n throw new CryptoError(\"Failed to generate stealth address\", error);\n }\n}\n\n/**\n * Check if a stealth address can be controlled by the stealth keys\n * Useful for scanning and proving ownership of stealth addresses\n */\nexport function canControlStealthAddress(\n viewingKey: string,\n spendingKey: string,\n ephemeralPubkey: string,\n targetAddress: string\n): boolean {\n try {\n // Reconstruct stealth address using both viewing and spending keys\n const viewingWallet = new ethers.Wallet(viewingKey);\n const spendingWallet = new ethers.Wallet(spendingKey);\n \n const metaAddress = computeMetaAddress(\n viewingWallet.signingKey.publicKey,\n spendingWallet.signingKey.publicKey\n );\n\n const stealthSeed = ethers.solidityPackedKeccak256(\n [\"bytes\", \"address\"],\n [ephemeralPubkey, metaAddress]\n );\n\n const derivedWallet = new ethers.Wallet(stealthSeed);\n\n return derivedWallet.address.toLowerCase() === targetAddress.toLowerCase();\n } catch (error) {\n return false;\n }\n}\n\n/**\n * Compute meta address from public keys (simplified)\n */\nfunction computeMetaAddress(\n viewingPubkey: string,\n spendingPubkey: string\n): string {\n const combined = ethers.solidityPackedKeccak256(\n [\"bytes\", \"bytes\"],\n [viewingPubkey, spendingPubkey]\n );\n\n // Take first 20 bytes as address\n return ethers.getAddress(\"0x\" + combined.slice(26));\n}\n","/**\n * Main Web3Passkey SDK class\n */\n\nimport {\n startRegistration,\n startAuthentication,\n} from \"@simplewebauthn/browser\";\nimport { ApiClient } from \"../utils/api\";\nimport { IndexedDBWalletStorage } from \"../wallet/storage\";\nimport { WalletSigner } from \"../wallet/signing\";\nimport {\n generateBIP39Wallet,\n deriveWalletFromMnemonic,\n} from \"../wallet/generate\";\nimport {\n deriveEncryptionKey,\n encryptData,\n decryptData,\n} from \"../wallet/crypto\";\nimport { StealthAddressModule } from \"../stealth\";\nimport type {\n Web3PasskeyConfig,\n InternalConfig,\n StealthAddressConfig,\n} from \"./config\";\nimport { DEFAULT_CONFIG } from \"./config\";\nimport type { UserInfo, WalletInfo } from \"../types\";\n\nexport interface AuthResult {\n verified: boolean;\n user?: UserInfo;\n}\n\nexport class Web3Passkey {\n private config: InternalConfig;\n private apiClient: ApiClient;\n private walletStorage: IndexedDBWalletStorage;\n private walletSigner: WalletSigner;\n private currentUser: UserInfo | null = null;\n private isAuthenticatedState: boolean = false;\n private isBrowser: boolean;\n private stealthAddresses: StealthAddressModule | null = null;\n\n constructor(config: Web3PasskeyConfig) {\n // Check if running in browser\n this.isBrowser =\n typeof window !== \"undefined\" && typeof localStorage !== \"undefined\";\n\n // Merge with defaults\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n timeout: config.timeout ?? DEFAULT_CONFIG.timeout!,\n debug: config.debug ?? DEFAULT_CONFIG.debug!,\n } as InternalConfig;\n\n // Initialize components\n this.apiClient = new ApiClient(this.config.apiBaseUrl, this.config.timeout);\n this.walletStorage = new IndexedDBWalletStorage();\n this.walletSigner = new WalletSigner(this.walletStorage);\n\n // Initialize stealth addresses if configured\n if (config.stealthAddresses) {\n this.stealthAddresses = new StealthAddressModule(\n config.stealthAddresses,\n this.getMnemonic.bind(this)\n );\n }\n\n // Initialize storage only in browser\n if (this.isBrowser) {\n this.walletStorage.init().catch((error) => {\n if (this.config.debug) {\n console.error(\"Failed to initialize wallet storage:\", error);\n }\n });\n\n // Load persisted auth state\n this.loadAuthState();\n } else if (this.config.debug) {\n console.warn(\n \"w3pk: Running in non-browser environment, some features disabled\"\n );\n }\n }\n\n // ========================================\n // Auth State Management\n // ========================================\n\n private loadAuthState(): void {\n if (!this.isBrowser) return;\n\n try {\n const storedUser = localStorage.getItem(\"w3pk_user\");\n const storedAuth = localStorage.getItem(\"w3pk_authenticated\");\n\n if (storedUser && storedAuth === \"true\") {\n this.currentUser = JSON.parse(storedUser);\n this.isAuthenticatedState = true;\n this.notifyAuthStateChange(true, this.currentUser ?? undefined);\n }\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to load auth state:\", error);\n }\n this.clearAuthState();\n }\n }\n\n private saveAuthState(user: UserInfo): void {\n if (!this.isBrowser) {\n console.warn(\"w3pk: Cannot save auth state in non-browser environment\");\n return;\n }\n\n try {\n localStorage.setItem(\"w3pk_user\", JSON.stringify(user));\n localStorage.setItem(\"w3pk_authenticated\", \"true\");\n this.currentUser = user;\n this.isAuthenticatedState = true;\n this.notifyAuthStateChange(true, user);\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to save auth state:\", error);\n }\n }\n }\n\n private clearAuthState(): void {\n if (!this.isBrowser) return;\n\n try {\n localStorage.removeItem(\"w3pk_user\");\n localStorage.removeItem(\"w3pk_authenticated\");\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to clear auth state:\", error);\n }\n }\n\n this.currentUser = null;\n this.isAuthenticatedState = false;\n this.notifyAuthStateChange(false);\n }\n\n private notifyAuthStateChange(\n isAuthenticated: boolean,\n user?: UserInfo\n ): void {\n if (this.config.onAuthStateChanged) {\n this.config.onAuthStateChanged(isAuthenticated, user);\n }\n }\n\n private createUserInfo(username: string, ethereumAddress: string): UserInfo {\n return {\n id: ethereumAddress,\n username,\n displayName: username,\n ethereumAddress,\n };\n }\n\n /**\n * Get mnemonic for current authenticated user\n * Used by stealth address module\n */\n private async getMnemonic(): Promise<string | null> {\n if (!this.isBrowser || !this.currentUser) {\n return null;\n }\n\n try {\n // Get encrypted wallet data\n const walletData = await this.walletStorage.retrieve(\n this.currentUser.ethereumAddress\n );\n if (!walletData) {\n return null;\n }\n\n // Derive encryption key from stored credentials\n const encryptionKey = await deriveEncryptionKey(\n walletData.credentialId,\n walletData.challenge\n );\n\n // Decrypt mnemonic\n return await decryptData(walletData.encryptedMnemonic, encryptionKey);\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to get mnemonic:\", error);\n }\n return null;\n }\n }\n\n // ========================================\n // Public API - Wallet\n // ========================================\n\n /**\n * Generate a new BIP39 wallet\n * @returns Wallet info with mnemonic (user MUST backup)\n */\n async generateWallet(): Promise<WalletInfo> {\n try {\n const wallet = generateBIP39Wallet();\n\n if (this.config.debug) {\n console.log(\"Wallet generated:\", wallet.address);\n }\n\n return wallet;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Check if wallet exists for current user\n */\n async hasWallet(): Promise<boolean> {\n if (!this.isBrowser) {\n console.warn(\n \"w3pk: Wallet storage not available in non-browser environment\"\n );\n return false;\n }\n\n if (!this.currentUser) {\n return false;\n }\n\n try {\n return await this.walletSigner.hasWallet(\n this.currentUser.ethereumAddress\n );\n } catch (error) {\n if (this.config.debug) {\n console.error(\"Failed to check wallet existence:\", error);\n }\n return false;\n }\n }\n\n /**\n * Derive HD wallet address and private key at specific index\n * Requires authentication to access encrypted mnemonic\n *\n * @param index HD derivation index (default: 0)\n * @returns Object with address and privateKey\n */\n async deriveWallet(\n index: number = 0\n ): Promise<{ address: string; privateKey: string }> {\n if (!this.isBrowser) {\n throw new Error(\"HD wallet derivation requires browser environment\");\n }\n\n if (!this.currentUser) {\n throw new Error(\"Not authenticated\");\n }\n\n try {\n // Get mnemonic for current authenticated user\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new Error(\"No wallet found for this user\");\n }\n\n // Derive wallet at specific index\n const derivedWallet = deriveWalletFromMnemonic(mnemonic, index);\n\n if (this.config.debug) {\n console.log(\n `HD wallet derived at index ${index}:`,\n derivedWallet.address\n );\n }\n\n return derivedWallet;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n // ========================================\n // Public API - Authentication\n // ========================================\n\n /**\n * Register a new user with WebAuthn\n * Handles the complete registration flow internally\n * Automatically generates wallet if not provided\n *\n * @param username Username for the account\n * @param ethereumAddress Optional: Ethereum address (will generate if not provided)\n * @param mnemonic Optional: BIP39 mnemonic (will generate if not provided)\n * @returns Object containing ethereumAddress and mnemonic (only if generated)\n */\n async register(options: {\n username: string;\n ethereumAddress?: string;\n mnemonic?: string;\n }): Promise<{ ethereumAddress: string; mnemonic?: string }> {\n if (!this.isBrowser) {\n throw new Error(\n \"Registration requires browser environment with WebAuthn support\"\n );\n }\n\n try {\n const { username } = options;\n let { ethereumAddress, mnemonic } = options;\n\n // Generate wallet if not provided\n if (!ethereumAddress || !mnemonic) {\n const wallet = generateBIP39Wallet();\n ethereumAddress = wallet.address;\n mnemonic = wallet.mnemonic;\n }\n\n // Step 1: Begin registration - get WebAuthn options from server\n const beginResponse = await this.apiClient.post(\n \"/webauthn/register/begin\",\n {\n username,\n ethereumAddress,\n }\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\"Failed to get registration options from server\");\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 2: Perform WebAuthn registration (browser prompt)\n const credential = await startRegistration(webauthnOptions);\n\n // Step 3: Encrypt mnemonic with WebAuthn-derived key\n const encryptionKey = await deriveEncryptionKey(\n credential.id,\n webauthnOptions.challenge\n );\n const encryptedMnemonic = await encryptData(mnemonic, encryptionKey);\n\n // Step 4: Store encrypted mnemonic in IndexedDB\n await this.walletStorage.store({\n ethereumAddress,\n encryptedMnemonic,\n credentialId: credential.id,\n challenge: webauthnOptions.challenge,\n createdAt: Date.now(),\n });\n\n // Step 5: Complete registration with server\n const completeResponse = await this.apiClient.post(\n \"/webauthn/register/complete\",\n {\n ethereumAddress,\n response: credential,\n }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Registration verification failed\");\n }\n\n // Step 6: Save auth state with displayName\n const user = this.createUserInfo(username, ethereumAddress);\n this.saveAuthState(user);\n\n if (this.config.debug) {\n console.log(\"Registration successful for:\", ethereumAddress);\n }\n\n // Return the wallet info (mnemonic only if we generated it)\n return {\n ethereumAddress,\n mnemonic: options.mnemonic ? undefined : mnemonic,\n };\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Authenticate without username (usernameless flow)\n */\n async login(): Promise<AuthResult> {\n if (!this.isBrowser) {\n throw new Error(\n \"Authentication requires browser environment with WebAuthn support\"\n );\n }\n\n try {\n // Step 1: Begin usernameless authentication\n const beginResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/begin\",\n {}\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\n \"Failed to get usernameless authentication options from server\"\n );\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 2: WebAuthn authentication\n const credential = await startAuthentication(webauthnOptions);\n\n // Step 3: Complete authentication\n const completeResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/complete\",\n { response: credential }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Usernameless authentication verification failed\");\n }\n\n const serverUser = completeResponse.data?.user;\n if (!serverUser) {\n throw new Error(\"No user data received from server\");\n }\n\n // Create UserInfo with displayName\n const user = this.createUserInfo(\n serverUser.username,\n serverUser.ethereumAddress || serverUser.id\n );\n this.saveAuthState(user);\n\n if (this.config.debug) {\n console.log(\n \"Usernameless authentication successful for:\",\n user.ethereumAddress\n );\n }\n\n return {\n verified: true,\n user,\n };\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n /**\n * Logout current user\n */\n logout(): void {\n this.clearAuthState();\n\n if (this.config.debug) {\n console.log(\"User logged out\");\n }\n }\n\n // ========================================\n // Public API - Message Signing\n // ========================================\n\n /**\n * Sign a message with encrypted wallet\n * Handles fresh WebAuthn authentication internally\n *\n * @param message Message to sign\n */\n async signMessage(message: string): Promise<string> {\n if (!this.isBrowser) {\n throw new Error(\"Message signing requires browser environment\");\n }\n\n if (!this.currentUser) {\n throw new Error(\"Not authenticated\");\n }\n\n try {\n // Step 1: Check if wallet exists\n const walletData = await this.walletStorage.retrieve(\n this.currentUser.ethereumAddress\n );\n if (!walletData) {\n throw new Error(\n \"No wallet found on this device. Please register to create a new wallet.\"\n );\n }\n\n // Step 2: Request fresh WebAuthn authentication\n if (this.config.debug) {\n console.log(\"Requesting WebAuthn authentication for signing...\");\n }\n\n const beginResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/begin\",\n {}\n );\n\n if (!beginResponse.success || !beginResponse.data) {\n throw new Error(\"Failed to begin authentication for signing\");\n }\n\n // Handle different response formats\n const webauthnOptions = beginResponse.data.options || beginResponse.data;\n\n // Step 3: Perform WebAuthn authentication (browser prompt)\n const credential = await startAuthentication(webauthnOptions);\n\n // Step 4: Verify authentication with server\n const completeResponse = await this.apiClient.post(\n \"/webauthn/authenticate/usernameless/complete\",\n { response: credential }\n );\n\n if (!completeResponse.success) {\n throw new Error(\"Authentication verification failed for signing\");\n }\n\n // Step 5: Use the authenticated credentials to sign\n const signature = await this.walletSigner.signMessage(\n this.currentUser.ethereumAddress,\n message,\n walletData.credentialId,\n walletData.challenge\n );\n\n if (this.config.debug) {\n console.log(\"Message signed successfully\");\n }\n\n return signature;\n } catch (error) {\n if (this.config.onError) {\n this.config.onError(error as any);\n }\n throw error;\n }\n }\n\n // ========================================\n // Public API - Getters\n // ========================================\n\n /**\n * Check if user is authenticated\n */\n get isAuthenticated(): boolean {\n return this.isAuthenticatedState;\n }\n\n /**\n * Get current user info\n */\n get user(): UserInfo | null {\n return this.currentUser;\n }\n\n /**\n * Get SDK version\n */\n get version(): string {\n return \"0.4.1\";\n }\n\n /**\n * Check if running in browser environment\n */\n get isBrowserEnvironment(): boolean {\n return this.isBrowser;\n }\n\n /**\n * Get stealth address module (if configured)\n */\n get stealth(): StealthAddressModule | null {\n return this.stealthAddresses;\n }\n}\n","/**\n * API client for backend communication\n */\n\nimport { ApiError } from \"../core/errors\";\nimport type { ApiResponse } from \"../types\";\n\nexport class ApiClient {\n constructor(private baseUrl: string, private timeout: number = 30000) {}\n\n private async fetchWithTimeout(\n url: string,\n options: RequestInit\n ): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n async post<T = any>(\n endpoint: string,\n body: any,\n options?: RequestInit\n ): Promise<ApiResponse<T>> {\n try {\n const response = await this.fetchWithTimeout(\n `${this.baseUrl}${endpoint}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n body: JSON.stringify(body),\n ...options,\n }\n );\n\n if (!response.ok) {\n throw new ApiError(\n `API request failed: ${response.statusText}`,\n response.status\n );\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n throw new ApiError(\"Network request failed\", undefined, error);\n }\n }\n\n async get<T = any>(\n endpoint: string,\n options?: RequestInit\n ): Promise<ApiResponse<T>> {\n try {\n const response = await this.fetchWithTimeout(\n `${this.baseUrl}${endpoint}`,\n {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n ...options,\n }\n );\n\n if (!response.ok) {\n throw new ApiError(\n `API request failed: ${response.statusText}`,\n response.status\n );\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n throw new ApiError(\"Network request failed\", undefined, error);\n }\n }\n}\n","/**\n * IndexedDB storage for encrypted wallet data\n */\n\nimport { StorageError } from \"../core/errors\";\nimport type { EncryptedWalletData, WalletStorage } from \"./types\";\n\nconst DB_NAME = \"Web3PasskeyWallet\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"wallets\";\n\nexport class IndexedDBWalletStorage implements WalletStorage {\n private db: IDBDatabase | null = null;\n\n async init(): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n\n request.onerror = () =>\n reject(new StorageError(\"Failed to open database\", request.error));\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: \"ethereumAddress\" });\n }\n };\n });\n }\n\n async store(data: EncryptedWalletData): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.put(data);\n request.onerror = () =>\n reject(new StorageError(\"Failed to store wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n\n async retrieve(ethereumAddress: string): Promise<EncryptedWalletData | null> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readonly\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.get(ethereumAddress);\n request.onerror = () =>\n reject(\n new StorageError(\"Failed to retrieve wallet data\", request.error)\n );\n request.onsuccess = () => resolve(request.result || null);\n });\n }\n\n async delete(ethereumAddress: string): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.delete(ethereumAddress);\n request.onerror = () =>\n reject(new StorageError(\"Failed to delete wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n\n async clear(): Promise<void> {\n if (!this.db) await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], \"readwrite\");\n const store = transaction.objectStore(STORE_NAME);\n\n const request = store.clear();\n request.onerror = () =>\n reject(new StorageError(\"Failed to clear wallet data\", request.error));\n request.onsuccess = () => resolve();\n });\n }\n}\n","/**\n * Message signing with encrypted wallet\n */\n\nimport { WalletError } from \"../core/errors\";\nimport { createWalletFromMnemonic } from \"./generate\";\nimport { deriveEncryptionKey, decryptData } from \"./crypto\";\nimport type { IndexedDBWalletStorage } from \"./storage\";\n\nexport class WalletSigner {\n constructor(private storage: IndexedDBWalletStorage) {}\n\n /**\n * Sign a message with the encrypted wallet\n * Requires fresh WebAuthn authentication\n */\n async signMessage(\n ethereumAddress: string,\n message: string,\n credentialId: string,\n challenge: string\n ): Promise<string> {\n try {\n // Retrieve encrypted wallet data\n const walletData = await this.storage.retrieve(ethereumAddress);\n if (!walletData) {\n throw new Error(\"No wallet found for this address\");\n }\n\n // Derive encryption key from WebAuthn credentials\n const encryptionKey = await deriveEncryptionKey(credentialId, challenge);\n\n // Decrypt mnemonic\n const mnemonic = await decryptData(\n walletData.encryptedMnemonic,\n encryptionKey\n );\n\n // Create wallet from mnemonic\n const wallet = createWalletFromMnemonic(mnemonic);\n\n // Verify address matches\n if (wallet.address.toLowerCase() !== ethereumAddress.toLowerCase()) {\n throw new Error(\"Wallet address mismatch\");\n }\n\n // Sign message\n const signature = await wallet.signMessage(message);\n\n // Clear mnemonic from memory (wallet will be garbage collected)\n return signature;\n } catch (error) {\n throw new WalletError(\"Failed to sign message\", error);\n }\n }\n\n /**\n * Check if wallet exists for address\n */\n async hasWallet(ethereumAddress: string): Promise<boolean> {\n const walletData = await this.storage.retrieve(ethereumAddress);\n return walletData !== null;\n }\n}\n","/**\n * BIP39 wallet generation\n */\n\nimport { ethers } from \"ethers\";\nimport { WalletError } from \"../core/errors\";\nimport type { WalletData } from \"./types\";\n\n/**\n * Generates a new BIP39 wallet with HD derivation\n * Uses BIP44 path: m/44'/60'/0'/0/0 for Ethereum\n */\nexport function generateBIP39Wallet(): WalletData {\n try {\n // Generate random mnemonic using ethers' utility\n const mnemonic = ethers.Wallet.createRandom().mnemonic;\n\n if (!mnemonic) {\n throw new Error(\"Failed to generate mnemonic\");\n }\n\n const mnemonicPhrase = mnemonic.phrase;\n\n // Create HD wallet from mnemonic phrase with derivation path\n const derivationPath = \"m/44'/60'/0'/0/0\";\n const hdWallet = ethers.HDNodeWallet.fromPhrase(\n mnemonicPhrase,\n undefined,\n derivationPath\n );\n\n return {\n address: hdWallet.address,\n mnemonic: mnemonicPhrase,\n };\n } catch (error) {\n throw new WalletError(\"Wallet generation failed\", error);\n }\n}\n\n/**\n * Creates wallet from mnemonic phrase\n * Uses BIP44 path: m/44'/60'/0'/0/0\n */\nexport function createWalletFromMnemonic(\n mnemonic: string\n): ethers.HDNodeWallet {\n try {\n if (!mnemonic || mnemonic.trim().split(/\\s+/).length < 12) {\n throw new Error(\"Invalid mnemonic: must be at least 12 words\");\n }\n\n // Create HD wallet with derivation path directly\n const derivationPath = \"m/44'/60'/0'/0/0\";\n const wallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic.trim(),\n undefined,\n derivationPath\n );\n\n return wallet;\n } catch (error) {\n throw new WalletError(\n `Wallet creation failed: ${\n error instanceof Error ? error.message : \"Invalid mnemonic\"\n }`,\n error\n );\n }\n}\n\n/**\n * Derives HD wallet address and private key at specific index\n * Uses BIP44 path: m/44'/60'/0'/0/{index}\n */\nexport function deriveWalletFromMnemonic(\n mnemonic: string,\n index: number = 0\n): { address: string; privateKey: string } {\n try {\n if (!mnemonic || mnemonic.trim().split(/\\s+/).length < 12) {\n throw new Error(\"Invalid mnemonic: must be at least 12 words\");\n }\n\n if (index < 0 || !Number.isInteger(index)) {\n throw new Error(\"Index must be a non-negative integer\");\n }\n\n // Create HD wallet with derivation path including index\n const derivationPath = `m/44'/60'/0'/0/${index}`;\n const wallet = ethers.HDNodeWallet.fromPhrase(\n mnemonic.trim(),\n undefined,\n derivationPath\n );\n\n return {\n address: wallet.address,\n privateKey: wallet.privateKey,\n };\n } catch (error) {\n throw new WalletError(\n `HD wallet derivation failed: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n error\n );\n }\n}\n","/**\n * Cryptographic utilities for wallet encryption\n */\n\nimport { CryptoError } from \"../core/errors\";\n\n/**\n * Derives an encryption key from WebAuthn credential data\n */\nexport async function deriveEncryptionKey(\n credentialId: string,\n challenge: string\n): Promise<CryptoKey> {\n try {\n const keyMaterial = new TextEncoder().encode(credentialId + challenge);\n\n const importedKey = await crypto.subtle.importKey(\n \"raw\",\n keyMaterial,\n { name: \"PBKDF2\" },\n false,\n [\"deriveKey\"]\n );\n\n return crypto.subtle.deriveKey(\n {\n name: \"PBKDF2\",\n salt: new TextEncoder().encode(\"webauthn-wallet-salt-w3pk\"),\n iterations: 100000,\n hash: \"SHA-256\",\n },\n importedKey,\n { name: \"AES-GCM\", length: 256 },\n false,\n [\"encrypt\", \"decrypt\"]\n );\n } catch (error) {\n throw new CryptoError(\"Failed to derive encryption key\", error);\n }\n}\n\n/**\n * Encrypts data using AES-GCM\n */\nexport async function encryptData(\n data: string,\n key: CryptoKey\n): Promise<string> {\n try {\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const encodedData = new TextEncoder().encode(data);\n\n const encrypted = await crypto.subtle.encrypt(\n { name: \"AES-GCM\", iv },\n key,\n encodedData\n );\n\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\n combined.set(iv);\n combined.set(new Uint8Array(encrypted), iv.length);\n\n return btoa(String.fromCharCode(...combined));\n } catch (error) {\n throw new CryptoError(\"Failed to encrypt data\", error);\n }\n}\n\n/**\n * Decrypts data using AES-GCM\n */\nexport async function decryptData(\n encryptedData: string,\n key: CryptoKey\n): Promise<string> {\n try {\n if (!encryptedData || encryptedData.length < 16) {\n throw new Error(\"Invalid encrypted data: too small\");\n }\n\n const combined = new Uint8Array(\n atob(encryptedData)\n .split(\"\")\n .map((char) => char.charCodeAt(0))\n );\n\n if (combined.length < 12) {\n throw new Error(\"Invalid encrypted data: missing IV\");\n }\n\n const iv = combined.slice(0, 12);\n const encrypted = combined.slice(12);\n\n if (encrypted.length === 0) {\n throw new Error(\"Invalid encrypted data: no content\");\n }\n\n const decrypted = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv },\n key,\n encrypted\n );\n\n return new TextDecoder().decode(decrypted);\n } catch (error) {\n throw new CryptoError(\n `Data decryption failed: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n error\n );\n }\n}\n","/**\n * Stealth Address Module for w3pk SDK\n * Provides privacy-preserving stealth address generation capabilities\n */\n\nimport { ethers } from \"ethers\";\nimport { Web3PasskeyError, AuthenticationError } from \"../core/errors\";\nimport { deriveStealthKeys } from \"./crypto\";\nimport type { StealthKeys } from \"./crypto\";\n\nexport interface StealthAddressConfig {\n // Network-agnostic - no provider needed\n}\n\nexport interface StealthAddressResult {\n stealthAddress: string;\n stealthPrivateKey: string;\n ephemeralPublicKey: string;\n}\n\n/**\n * Main Stealth Address Module\n * Integrates with w3pk WebAuthn for seamless privacy-preserving stealth address generation\n */\nexport class StealthAddressModule {\n private config: StealthAddressConfig;\n private getMnemonic: () => Promise<string | null>;\n\n constructor(config: StealthAddressConfig, getMnemonic: () => Promise<string | null>) {\n this.config = config;\n this.getMnemonic = getMnemonic;\n }\n\n // ========================================\n // Stealth Address Generation\n // ========================================\n\n /**\n * Generate a fresh stealth address for privacy-preserving transactions\n * Returns the stealth address and private key for the user to handle transactions\n */\n async generateStealthAddress(): Promise<StealthAddressResult> {\n try {\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new AuthenticationError(\"Not authenticated. Please login first.\");\n }\n\n const stealthKeys = deriveStealthKeys(mnemonic);\n const { generateStealthAddress } = await import(\"./crypto\");\n const stealthResult = generateStealthAddress(stealthKeys.metaAddress);\n\n return {\n stealthAddress: stealthResult.stealthAddress,\n stealthPrivateKey: stealthResult.stealthPrivkey,\n ephemeralPublicKey: stealthResult.ephemeralPubkey\n };\n } catch (error) {\n throw new Web3PasskeyError(\n \"Failed to generate stealth address\",\n \"STEALTH_GENERATION_ERROR\",\n error\n );\n }\n }\n\n\n // ========================================\n // Privacy & Key Management\n // ========================================\n\n /**\n * Get stealth keys for manual operations\n */\n async getKeys(): Promise<StealthKeys> {\n try {\n const mnemonic = await this.getMnemonic();\n if (!mnemonic) {\n throw new AuthenticationError(\"Not authenticated. Please login first.\");\n }\n\n return deriveStealthKeys(mnemonic);\n } catch (error) {\n throw new Web3PasskeyError(\n \"Failed to get stealth keys\",\n \"STEALTH_KEYS_ERROR\",\n error\n );\n }\n }\n\n // ========================================\n // Status & Management\n // ========================================\n\n /**\n * Check if stealth addresses are available (always true if properly configured)\n */\n get isAvailable(): boolean {\n return true;\n }\n}\n\n// Export types for stealth module\nexport type { StealthKeys };","/**\n * SDK Configuration\n */\n\nimport type { UserInfo } from \"../types\";\nimport type { Web3PasskeyError } from \"./errors\";\nimport type { ethers } from \"ethers\";\n\nexport interface StealthAddressConfig {}\n\nexport interface Web3PasskeyConfig {\n /**\n * Base URL of the WebAuthn API\n * @example 'https://webauthn.w3hc.org'\n */\n apiBaseUrl: string;\n\n /**\n * Timeout for API requests in milliseconds\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom error handler\n */\n onError?: (error: Web3PasskeyError) => void;\n\n /**\n * Auth state change callback\n */\n onAuthStateChanged?: (isAuthenticated: boolean, user?: UserInfo) => void;\n\n /**\n * Optional stealth address configuration\n * If provided, enables privacy-preserving stealth address generation\n */\n stealthAddresses?: StealthAddressConfig;\n}\n\nexport interface InternalConfig extends Required<Web3PasskeyConfig> {\n // Normalized config with all defaults applied\n}\n\nexport const DEFAULT_CONFIG: Partial<Web3PasskeyConfig> = {\n timeout: 30000,\n debug: false,\n};\n","/**\n * w3pk - Web3 Passkey SDK\n * WebAuthn SDK for passwordless authentication and encrypted wallet management\n */\n\nimport { Web3Passkey } from \"./core/sdk\";\nimport type { Web3PasskeyConfig } from \"./core/config\";\n\n// Main factory function\nexport function createWeb3Passkey(config: Web3PasskeyConfig): Web3Passkey {\n return new Web3Passkey(config);\n}\n\n// Export types\nexport type { Web3PasskeyConfig, StealthAddressConfig } from \"./core/config\";\nexport type { UserInfo, WalletInfo } from \"./types\";\nexport type { StealthKeys, StealthAddressResult } from \"./stealth\";\n\n// Export errors for custom error handling\nexport {\n Web3PasskeyError,\n AuthenticationError,\n RegistrationError,\n WalletError,\n CryptoError,\n StorageError,\n ApiError,\n} from \"./core/errors\";\n\n// Export SDK class for advanced usage\nexport { Web3Passkey } from \"./core/sdk\";\n\n// Export stealth address module for advanced usage\nexport { StealthAddressModule } from \"./stealth\";\n\n// Export crypto utilities\nexport { canControlStealthAddress } from \"./stealth/crypto\";\n\n// Export wallet generation utilities\nexport { generateBIP39Wallet, createWalletFromMnemonic, deriveWalletFromMnemonic } from \"./wallet/generate\";\n\n// Default export\nexport default createWeb3Passkey;\n"],"mappings":"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","names":["Web3PasskeyError","AuthenticationError","RegistrationError","WalletError","CryptoError","StorageError","ApiError","init_errors","__esmMin","message","code","originalError","statusCode","crypto_exports","__export","canControlStealthAddress","deriveStealthKeys","generateStealthAddress","ethers","mnemonic","viewingWallet","spendingWallet","computeMetaAddress","error","CryptoError","metaAddress","ephemeralWallet","stealthSeed","stealthWallet","viewingKey","spendingKey","ephemeralPubkey","targetAddress","viewingPubkey","spendingPubkey","combined","init_crypto","__esmMin","init_errors","startRegistration","startAuthentication","init_errors","ApiClient","baseUrl","timeout","url","options","controller","timeoutId","response","error","endpoint","body","ApiError","init_errors","DB_NAME","DB_VERSION","STORE_NAME","IndexedDBWalletStorage","resolve","reject","request","StorageError","db","data","ethereumAddress","init_errors","init_errors","ethers","generateBIP39Wallet","mnemonic","mnemonicPhrase","error","WalletError","createWalletFromMnemonic","deriveWalletFromMnemonic","index","derivationPath","wallet","init_errors","deriveEncryptionKey","credentialId","challenge","keyMaterial","importedKey","error","CryptoError","encryptData","data","key","iv","encodedData","encrypted","combined","decryptData","encryptedData","char","decrypted","WalletSigner","storage","ethereumAddress","message","credentialId","challenge","walletData","encryptionKey","deriveEncryptionKey","mnemonic","decryptData","wallet","createWalletFromMnemonic","error","WalletError","init_errors","init_crypto","StealthAddressModule","config","getMnemonic","mnemonic","AuthenticationError","stealthKeys","deriveStealthKeys","generateStealthAddress","stealthResult","error","Web3PasskeyError","DEFAULT_CONFIG","Web3Passkey","config","DEFAULT_CONFIG","ApiClient","IndexedDBWalletStorage","WalletSigner","StealthAddressModule","error","storedUser","storedAuth","user","isAuthenticated","username","ethereumAddress","walletData","encryptionKey","deriveEncryptionKey","decryptData","wallet","generateBIP39Wallet","index","mnemonic","derivedWallet","deriveWalletFromMnemonic","options","beginResponse","webauthnOptions","credential","startRegistration","encryptedMnemonic","encryptData","startAuthentication","completeResponse","serverUser","message","signature","init_errors","init_crypto","createWeb3Passkey","config","Web3Passkey","index_default"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "w3pk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "WebAuthn SDK for passwordless authentication, encrypted wallets, and privacy-preserving stealth addresses",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -22,8 +22,6 @@
|
|
|
22
22
|
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
23
23
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
24
24
|
"test": "tsx test/test.ts && tsx test/comprehensive.test.ts",
|
|
25
|
-
"test:basic": "tsx test/test.ts",
|
|
26
|
-
"test:comprehensive": "tsx test/comprehensive.test.ts",
|
|
27
25
|
"prepublishOnly": "pnpm build"
|
|
28
26
|
},
|
|
29
27
|
"keywords": [
|