w3pk 0.10.3 → 0.10.4

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 CHANGED
@@ -512,11 +512,4 @@ GPL-3.0
512
512
 
513
513
  ## Contact
514
514
 
515
- **Julien Béranger** ([GitHub](https://github.com/julienbrg))
516
- - Element: [@julienbrg:matrix.org](https://matrix.to/#/@julienbrg:matrix.org)
517
- - Farcaster: [julien-](https://warpcast.com/julien-)
518
- - Telegram: [@julienbrg](https://t.me/julienbrg)
519
- - Twitter: [@julienbrg](https://twitter.com/julienbrg)
520
-
521
-
522
- <img src="https://bafkreid5xwxz4bed67bxb2wjmwsec4uhlcjviwy7pkzwoyu5oesjd3sp64.ipfs.w3s.link" alt="built-with-ethereum-w3hc" width="100"/>
515
+ Questions or feedback? Get in touch with [Julien](https://github.com/julienbrg): [https://julienberanger.com/contact](https://julienberanger.com/contact)
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Chainlist types
3
+ */
4
+ interface Chain {
5
+ name: string;
6
+ chain: string;
7
+ icon?: string;
8
+ rpc: string[];
9
+ features?: Array<{
10
+ name: string;
11
+ }>;
12
+ faucets: string[];
13
+ nativeCurrency: {
14
+ name: string;
15
+ symbol: string;
16
+ decimals: number;
17
+ };
18
+ infoURL: string;
19
+ shortName: string;
20
+ chainId: number;
21
+ networkId: number;
22
+ slip44?: number;
23
+ ens?: {
24
+ registry: string;
25
+ };
26
+ explorers?: Array<{
27
+ name: string;
28
+ url: string;
29
+ icon?: string;
30
+ standard: string;
31
+ }>;
32
+ title?: string;
33
+ status?: string;
34
+ redFlags?: string[];
35
+ }
36
+ interface ChainlistOptions {
37
+ /**
38
+ * Custom URL for chains.json data
39
+ * @default 'https://chainid.network/chains.json'
40
+ */
41
+ chainsJsonUrl?: string;
42
+ /**
43
+ * Cache duration in milliseconds
44
+ * @default 3600000 (1 hour)
45
+ */
46
+ cacheDuration?: number;
47
+ }
48
+
49
+ /**
50
+ * Chainlist module for fetching RPC endpoints
51
+ */
52
+
53
+ /**
54
+ * Get RPC endpoints for a specific chain ID, excluding those that require API keys
55
+ *
56
+ * @param chainId - The chain ID to get endpoints for
57
+ * @param options - Optional configuration
58
+ * @returns Array of RPC URLs that don't require API keys
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { getEndpoints } from 'w3pk/chainlist'
63
+ *
64
+ * // Get Ethereum mainnet RPCs
65
+ * const endpoints = await getEndpoints(1)
66
+ * console.log(endpoints)
67
+ * // [
68
+ * // "https://api.mycryptoapi.com/eth",
69
+ * // "https://cloudflare-eth.com",
70
+ * // "https://ethereum-rpc.publicnode.com",
71
+ * // ...
72
+ * // ]
73
+ * ```
74
+ */
75
+ declare function getEndpoints(chainId: number, options?: ChainlistOptions): Promise<string[]>;
76
+ /**
77
+ * Get all available chains
78
+ *
79
+ * @param options - Optional configuration
80
+ * @returns Array of all chains
81
+ */
82
+ declare function getAllChains(options?: ChainlistOptions): Promise<Chain[]>;
83
+ /**
84
+ * Get chain information by chain ID
85
+ *
86
+ * @param chainId - The chain ID to get information for
87
+ * @param options - Optional configuration
88
+ * @returns Chain information or undefined if not found
89
+ */
90
+ declare function getChainById(chainId: number, options?: ChainlistOptions): Promise<Chain | undefined>;
91
+ /**
92
+ * Clear the chains data cache
93
+ */
94
+ declare function clearCache(): void;
95
+
96
+ export { type Chain, type ChainlistOptions, clearCache, getAllChains, getChainById, getEndpoints };
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Chainlist types
3
+ */
4
+ interface Chain {
5
+ name: string;
6
+ chain: string;
7
+ icon?: string;
8
+ rpc: string[];
9
+ features?: Array<{
10
+ name: string;
11
+ }>;
12
+ faucets: string[];
13
+ nativeCurrency: {
14
+ name: string;
15
+ symbol: string;
16
+ decimals: number;
17
+ };
18
+ infoURL: string;
19
+ shortName: string;
20
+ chainId: number;
21
+ networkId: number;
22
+ slip44?: number;
23
+ ens?: {
24
+ registry: string;
25
+ };
26
+ explorers?: Array<{
27
+ name: string;
28
+ url: string;
29
+ icon?: string;
30
+ standard: string;
31
+ }>;
32
+ title?: string;
33
+ status?: string;
34
+ redFlags?: string[];
35
+ }
36
+ interface ChainlistOptions {
37
+ /**
38
+ * Custom URL for chains.json data
39
+ * @default 'https://chainid.network/chains.json'
40
+ */
41
+ chainsJsonUrl?: string;
42
+ /**
43
+ * Cache duration in milliseconds
44
+ * @default 3600000 (1 hour)
45
+ */
46
+ cacheDuration?: number;
47
+ }
48
+
49
+ /**
50
+ * Chainlist module for fetching RPC endpoints
51
+ */
52
+
53
+ /**
54
+ * Get RPC endpoints for a specific chain ID, excluding those that require API keys
55
+ *
56
+ * @param chainId - The chain ID to get endpoints for
57
+ * @param options - Optional configuration
58
+ * @returns Array of RPC URLs that don't require API keys
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { getEndpoints } from 'w3pk/chainlist'
63
+ *
64
+ * // Get Ethereum mainnet RPCs
65
+ * const endpoints = await getEndpoints(1)
66
+ * console.log(endpoints)
67
+ * // [
68
+ * // "https://api.mycryptoapi.com/eth",
69
+ * // "https://cloudflare-eth.com",
70
+ * // "https://ethereum-rpc.publicnode.com",
71
+ * // ...
72
+ * // ]
73
+ * ```
74
+ */
75
+ declare function getEndpoints(chainId: number, options?: ChainlistOptions): Promise<string[]>;
76
+ /**
77
+ * Get all available chains
78
+ *
79
+ * @param options - Optional configuration
80
+ * @returns Array of all chains
81
+ */
82
+ declare function getAllChains(options?: ChainlistOptions): Promise<Chain[]>;
83
+ /**
84
+ * Get chain information by chain ID
85
+ *
86
+ * @param chainId - The chain ID to get information for
87
+ * @param options - Optional configuration
88
+ * @returns Chain information or undefined if not found
89
+ */
90
+ declare function getChainById(chainId: number, options?: ChainlistOptions): Promise<Chain | undefined>;
91
+ /**
92
+ * Clear the chains data cache
93
+ */
94
+ declare function clearCache(): void;
95
+
96
+ export { type Chain, type ChainlistOptions, clearCache, getAllChains, getChainById, getEndpoints };
package/dist/index.d.mts CHANGED
@@ -246,6 +246,47 @@ declare class StealthAddressModule {
246
246
  get isAvailable(): boolean;
247
247
  }
248
248
 
249
+ /** Client extension results consumed by w3pk (subset of the WebAuthn spec) */
250
+ interface PrfExtensionResults {
251
+ prf?: {
252
+ enabled?: boolean;
253
+ results?: {
254
+ first?: ArrayBuffer;
255
+ };
256
+ };
257
+ }
258
+ /**
259
+ * Native WebAuthn credential response (authentication)
260
+ */
261
+ interface AuthenticationCredential {
262
+ id: string;
263
+ rawId: ArrayBuffer;
264
+ type: 'public-key';
265
+ response: {
266
+ clientDataJSON: ArrayBuffer;
267
+ authenticatorData: ArrayBuffer;
268
+ signature: ArrayBuffer;
269
+ userHandle?: ArrayBuffer;
270
+ };
271
+ getClientExtensionResults(): PrfExtensionResults;
272
+ }
273
+
274
+ /**
275
+ * WebAuthn PRF evaluation
276
+ *
277
+ * The PRF extension releases HMAC(credential secret, salt) only on a live,
278
+ * user-verified assertion. The browser hashes each input as
279
+ * SHA-256("WebAuthn PRF" || 0x00 || input) before it reaches the
280
+ * authenticator, so inputs here can be any bytes.
281
+ */
282
+
283
+ interface PrfSecret {
284
+ /** 32-byte secret for this origin and tag */
285
+ secret: Uint8Array;
286
+ /** Credential the secret is bound to; a new credential gives a new secret */
287
+ credentialId: string;
288
+ }
289
+
249
290
  /**
250
291
  * Shared types used across the SDK
251
292
  */
@@ -396,6 +437,23 @@ declare class WalletMissingError extends Web3PasskeyError {
396
437
  ethereumAddress: string;
397
438
  constructor(credentialId: string, ethereumAddress: string);
398
439
  }
440
+ type SyncBootstrapReason = "PASSKEY_BACKUP" | "NO_CREDENTIAL" | "CREDENTIAL_MISMATCH" | "PUBLIC_KEY_MISMATCH";
441
+ /**
442
+ * A sync can't set up this device's passkey metadata from the backup.
443
+ */
444
+ declare class SyncBootstrapError extends Web3PasskeyError {
445
+ reason: SyncBootstrapReason;
446
+ credentialId: string;
447
+ constructor(reason: SyncBootstrapReason, credentialId: string);
448
+ }
449
+ /**
450
+ * The authenticator returned no WebAuthn PRF output, so no
451
+ * passkey-bound secret can be derived. There is no fallback.
452
+ */
453
+ declare class PrfUnsupportedError extends Web3PasskeyError {
454
+ credentialId: string;
455
+ constructor(credentialId: string);
456
+ }
399
457
 
400
458
  /**
401
459
  * Persistent Session Storage
@@ -487,6 +545,7 @@ interface Web3PasskeyConfig {
487
545
  type BackupMethod = 'file' | 'qr' | 'phrase';
488
546
  interface BackupStatus {
489
547
  hasBackup: boolean;
548
+ evictionRisk: boolean;
490
549
  lastBackupAt?: string;
491
550
  methods: BackupMethod[];
492
551
  passkeySync: PasskeySyncStatus;
@@ -622,6 +681,7 @@ declare class Web3Passkey {
622
681
  address: string;
623
682
  username: string;
624
683
  hasBackup: boolean;
684
+ evictionRisk: boolean;
625
685
  }>;
626
686
  /**
627
687
  * Login with WebAuthn using resident credentials
@@ -1007,6 +1067,7 @@ declare class Web3Passkey {
1007
1067
  blob: Blob;
1008
1068
  filename: string;
1009
1069
  }>;
1070
+ private backupCredential;
1010
1071
  /**
1011
1072
  * Set up social recovery by splitting backup file among guardians
1012
1073
  * Uses Shamir Secret Sharing to split the backup - requires M-of-N guardians to recover
@@ -1066,6 +1127,9 @@ declare class Web3Passkey {
1066
1127
  *
1067
1128
  * This allows the user to use the same PRIMARY mode webauthn account on multiple devices.
1068
1129
  *
1130
+ * A PRF backup (from exportForSync()) takes a single assertion restricted
1131
+ * to its passkey and no password.
1132
+ *
1069
1133
  * @param backupData - Backup file (JSON string or Blob) - can be pasted by user
1070
1134
  * @param password - Password to decrypt backup (if password-encrypted)
1071
1135
  * @returns Restored wallet info
@@ -1074,6 +1138,18 @@ declare class Web3Passkey {
1074
1138
  mnemonic: string;
1075
1139
  ethereumAddress: string;
1076
1140
  }>;
1141
+ /**
1142
+ * Restore a PRF backup with its passkey and set this device up for it.
1143
+ * The public key is this device's when it has the passkey's metadata,
1144
+ * else the backup's, checked against the assertion's signature.
1145
+ */
1146
+ private restorePrfBackup;
1147
+ /**
1148
+ * Set this device up for a passkey and a synced wallet: saves the
1149
+ * passkey's metadata (or points it at the wallet), stores the wallet
1150
+ * under the passkey-derived key and starts a session
1151
+ */
1152
+ private bootstrapCredential;
1077
1153
  /**
1078
1154
  * Register new passkey with wallet from backup file
1079
1155
  * Use case: Fresh device, user has backup file but no passkey yet
@@ -1094,16 +1170,30 @@ declare class Web3Passkey {
1094
1170
  getSyncStatus(): Promise<any>;
1095
1171
  /**
1096
1172
  * Export wallet for syncing to another device
1097
- * Uses passkey encryption so it works on devices where the passkey is synced
1173
+ *
1174
+ * Prompts for the passkey and encrypts with a key derived from its WebAuthn
1175
+ * PRF output (`encryptionMethod: 'prf'`): a device where the passkey synced
1176
+ * restores it with one prompt and no password. Where the authenticator has
1177
+ * no PRF support, `password` makes it fall back to a password backup.
1178
+ *
1179
+ * @param password - Fallback password when PRF is unavailable
1180
+ * @throws PrfUnsupportedError when PRF is unavailable and no password is given
1098
1181
  */
1099
- exportForSync(): Promise<{
1182
+ exportForSync(password?: string): Promise<{
1100
1183
  blob: Blob;
1101
1184
  filename: string;
1102
1185
  qrCode?: string;
1103
1186
  }>;
1104
1187
  /**
1105
1188
  * Import wallet from another device (sync wallet to this device)
1106
- * Use case: User has passkey on both devices, wallet only on one
1189
+ *
1190
+ * Takes a PRF backup from exportForSync(): one assertion restricted to
1191
+ * the backup's passkey decrypts it, with no password, on any device where
1192
+ * the passkey synced, including one with no data for it. Works without a
1193
+ * login. For a password backup (exportForSync()'s fallback), use
1194
+ * syncWalletWithPasskey().
1195
+ *
1196
+ * @throws SyncBootstrapError ('CREDENTIAL_MISMATCH') when logged in with another passkey
1107
1197
  */
1108
1198
  importFromSync(syncData: string | Blob): Promise<{
1109
1199
  ethereumAddress: string;
@@ -1158,6 +1248,23 @@ declare class Web3Passkey {
1158
1248
  * @param hours - Duration in hours
1159
1249
  */
1160
1250
  setPersistentSessionDuration(hours: number): void;
1251
+ /**
1252
+ * Derive a 32-byte secret bound to the passkey, separate per origin and tag
1253
+ *
1254
+ * Evaluates the WebAuthn PRF extension on a fresh user-verified assertion
1255
+ * and runs HKDF-SHA256 on the output. The secret is never derived from or
1256
+ * stored with the mnemonic, so it never appears in backups, recovery
1257
+ * phrases, sessions or storage. When logged in, the assertion is
1258
+ * restricted to the current user's passkey.
1259
+ *
1260
+ * @param tag - Non-empty label without ':', e.g. "zk-identity"
1261
+ * @returns The secret and the credential it is bound to
1262
+ * @throws PrfUnsupportedError when the authenticator doesn't support PRF
1263
+ *
1264
+ * @example
1265
+ * const { secret, credentialId } = await w3pk.derivePrfSecret("zk-identity")
1266
+ */
1267
+ derivePrfSecret(tag: string): Promise<PrfSecret>;
1161
1268
  /**
1162
1269
  * Derive ML-KEM-1024 public key from the current wallet
1163
1270
  *
@@ -1443,31 +1550,6 @@ declare function verifyEIP7702Authorization(chainId: bigint, contractAddress: st
1443
1550
  s: string;
1444
1551
  } | string, expectedSigner: string): boolean;
1445
1552
 
1446
- /** Client extension results consumed by w3pk (subset of the WebAuthn spec) */
1447
- interface PrfExtensionResults {
1448
- prf?: {
1449
- enabled?: boolean;
1450
- results?: {
1451
- first?: ArrayBuffer;
1452
- };
1453
- };
1454
- }
1455
- /**
1456
- * Native WebAuthn credential response (authentication)
1457
- */
1458
- interface AuthenticationCredential {
1459
- id: string;
1460
- rawId: ArrayBuffer;
1461
- type: 'public-key';
1462
- response: {
1463
- clientDataJSON: ArrayBuffer;
1464
- authenticatorData: ArrayBuffer;
1465
- signature: ArrayBuffer;
1466
- userHandle?: ArrayBuffer;
1467
- };
1468
- getClientExtensionResults(): PrfExtensionResults;
1469
- }
1470
-
1471
1553
  /**
1472
1554
  * Sync Authentication Helper
1473
1555
  * Handles passkey selection and authentication for cross-device sync scenarios
@@ -1477,6 +1559,9 @@ interface PasskeySelectionResult {
1477
1559
  credentialId: string;
1478
1560
  publicKey: string;
1479
1561
  ethereumAddress?: string;
1562
+ username?: string;
1563
+ /** The selection assertion, to verify against a public key from a backup */
1564
+ assertion: AuthenticationCredential;
1480
1565
  }
1481
1566
  /**
1482
1567
  * Prompts the user to select a passkey/webauthn credential
@@ -2352,4 +2437,4 @@ declare function mlkemDecryptWithKey(payload: EncryptedPayload, privateKey: stri
2352
2437
 
2353
2438
  declare function createWeb3Passkey(config?: Web3PasskeyConfig): Web3Passkey;
2354
2439
 
2355
- export { ApiError, AuthenticationError, type BackupMethod, type BackupStatus, type BrowserInspectOptions, type BrowserInspectResult, CryptoError, DEFAULT_MODE, DEFAULT_TAG, type DeviceInfo, type EIP1193Provider, type EIP7702Authorization, type EncryptedBackupInfo, type EncryptedPayload, type Guardian, type GuardianInvite, type MLKemKeypair, type PasskeySelectionResult, type QRBackupOptions, type RecoveryProgress, type RecoveryScenario, type RecoveryShare, RecoverySimulator, RegistrationError, type SecurityScore, type SignAuthorizationParams, type SimulationResult, type SiweMessage, type SocialRecoveryConfig, SocialRecoveryManager, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, type SyncCapabilities, SyncRequiredError, type SyncStatus, type SyncVault, type UserInfo, WalletError, type WalletInfo, WalletMissingError, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, arrayBufferToBase64Url, assertEthereumAddress, assertMnemonic, assertUsername, authenticateWithPasskey, base64ToArrayBuffer, base64UrlDecode, base64UrlToArrayBuffer, canControlStealthAddress, checkStealthAddress, clearCache, computeStealthPrivateKey, createSiweMessage, createWalletFromMnemonic, createWeb3Passkey, createWeb3Passkey as default, deriveAddressFromP256PublicKey, deriveIndexFromOriginModeAndTag, deriveMLKemKeypair, deriveStealthKeys, deriveWalletFromMnemonic, detectWalletProvider, encodeEIP7702AuthorizationMessage, extractRS, generateBIP39Wallet, generateSiweNonce, generateStealthAddress, getAllChains, getAllTopics, getChainById, getCurrentBuildHash, getCurrentOrigin, getDefaultProvider, getEndpoints, getExplainer, getOriginSpecificAddress, getPackageVersion, getW3pkBuildHash, hashEIP7702AuthorizationMessage, inspect, inspectNow, isStrongPassword, mlkemDecrypt, mlkemDecryptWithKey, mlkemEncrypt, mlkemEncryptWithKey, normalizeOrigin, parseSiweMessage, promptPasskeySelection, requestExternalWalletAuthorization, safeAtob, safeBtoa, searchExplainers, supportsEIP7702Authorization, validateEthereumAddress, validateMnemonic, validateSiweMessage, validateUsername, verifyBuildHash, verifyEIP7702Authorization, verifySiweSignature };
2440
+ export { ApiError, AuthenticationError, type BackupMethod, type BackupStatus, type BrowserInspectOptions, type BrowserInspectResult, CryptoError, DEFAULT_MODE, DEFAULT_TAG, type DeviceInfo, type EIP1193Provider, type EIP7702Authorization, type EncryptedBackupInfo, type EncryptedPayload, type Guardian, type GuardianInvite, type MLKemKeypair, type PasskeySelectionResult, type PrfSecret, PrfUnsupportedError, type QRBackupOptions, type RecoveryProgress, type RecoveryScenario, type RecoveryShare, RecoverySimulator, RegistrationError, type SecurityScore, type SignAuthorizationParams, type SimulationResult, type SiweMessage, type SocialRecoveryConfig, SocialRecoveryManager, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, SyncBootstrapError, type SyncBootstrapReason, type SyncCapabilities, SyncRequiredError, type SyncStatus, type SyncVault, type UserInfo, WalletError, type WalletInfo, WalletMissingError, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, arrayBufferToBase64Url, assertEthereumAddress, assertMnemonic, assertUsername, authenticateWithPasskey, base64ToArrayBuffer, base64UrlDecode, base64UrlToArrayBuffer, canControlStealthAddress, checkStealthAddress, clearCache, computeStealthPrivateKey, createSiweMessage, createWalletFromMnemonic, createWeb3Passkey, createWeb3Passkey as default, deriveAddressFromP256PublicKey, deriveIndexFromOriginModeAndTag, deriveMLKemKeypair, deriveStealthKeys, deriveWalletFromMnemonic, detectWalletProvider, encodeEIP7702AuthorizationMessage, extractRS, generateBIP39Wallet, generateSiweNonce, generateStealthAddress, getAllChains, getAllTopics, getChainById, getCurrentBuildHash, getCurrentOrigin, getDefaultProvider, getEndpoints, getExplainer, getOriginSpecificAddress, getPackageVersion, getW3pkBuildHash, hashEIP7702AuthorizationMessage, inspect, inspectNow, isStrongPassword, mlkemDecrypt, mlkemDecryptWithKey, mlkemEncrypt, mlkemEncryptWithKey, normalizeOrigin, parseSiweMessage, promptPasskeySelection, requestExternalWalletAuthorization, safeAtob, safeBtoa, searchExplainers, supportsEIP7702Authorization, validateEthereumAddress, validateMnemonic, validateSiweMessage, validateUsername, verifyBuildHash, verifyEIP7702Authorization, verifySiweSignature };
package/dist/index.d.ts CHANGED
@@ -246,6 +246,47 @@ declare class StealthAddressModule {
246
246
  get isAvailable(): boolean;
247
247
  }
248
248
 
249
+ /** Client extension results consumed by w3pk (subset of the WebAuthn spec) */
250
+ interface PrfExtensionResults {
251
+ prf?: {
252
+ enabled?: boolean;
253
+ results?: {
254
+ first?: ArrayBuffer;
255
+ };
256
+ };
257
+ }
258
+ /**
259
+ * Native WebAuthn credential response (authentication)
260
+ */
261
+ interface AuthenticationCredential {
262
+ id: string;
263
+ rawId: ArrayBuffer;
264
+ type: 'public-key';
265
+ response: {
266
+ clientDataJSON: ArrayBuffer;
267
+ authenticatorData: ArrayBuffer;
268
+ signature: ArrayBuffer;
269
+ userHandle?: ArrayBuffer;
270
+ };
271
+ getClientExtensionResults(): PrfExtensionResults;
272
+ }
273
+
274
+ /**
275
+ * WebAuthn PRF evaluation
276
+ *
277
+ * The PRF extension releases HMAC(credential secret, salt) only on a live,
278
+ * user-verified assertion. The browser hashes each input as
279
+ * SHA-256("WebAuthn PRF" || 0x00 || input) before it reaches the
280
+ * authenticator, so inputs here can be any bytes.
281
+ */
282
+
283
+ interface PrfSecret {
284
+ /** 32-byte secret for this origin and tag */
285
+ secret: Uint8Array;
286
+ /** Credential the secret is bound to; a new credential gives a new secret */
287
+ credentialId: string;
288
+ }
289
+
249
290
  /**
250
291
  * Shared types used across the SDK
251
292
  */
@@ -396,6 +437,23 @@ declare class WalletMissingError extends Web3PasskeyError {
396
437
  ethereumAddress: string;
397
438
  constructor(credentialId: string, ethereumAddress: string);
398
439
  }
440
+ type SyncBootstrapReason = "PASSKEY_BACKUP" | "NO_CREDENTIAL" | "CREDENTIAL_MISMATCH" | "PUBLIC_KEY_MISMATCH";
441
+ /**
442
+ * A sync can't set up this device's passkey metadata from the backup.
443
+ */
444
+ declare class SyncBootstrapError extends Web3PasskeyError {
445
+ reason: SyncBootstrapReason;
446
+ credentialId: string;
447
+ constructor(reason: SyncBootstrapReason, credentialId: string);
448
+ }
449
+ /**
450
+ * The authenticator returned no WebAuthn PRF output, so no
451
+ * passkey-bound secret can be derived. There is no fallback.
452
+ */
453
+ declare class PrfUnsupportedError extends Web3PasskeyError {
454
+ credentialId: string;
455
+ constructor(credentialId: string);
456
+ }
399
457
 
400
458
  /**
401
459
  * Persistent Session Storage
@@ -487,6 +545,7 @@ interface Web3PasskeyConfig {
487
545
  type BackupMethod = 'file' | 'qr' | 'phrase';
488
546
  interface BackupStatus {
489
547
  hasBackup: boolean;
548
+ evictionRisk: boolean;
490
549
  lastBackupAt?: string;
491
550
  methods: BackupMethod[];
492
551
  passkeySync: PasskeySyncStatus;
@@ -622,6 +681,7 @@ declare class Web3Passkey {
622
681
  address: string;
623
682
  username: string;
624
683
  hasBackup: boolean;
684
+ evictionRisk: boolean;
625
685
  }>;
626
686
  /**
627
687
  * Login with WebAuthn using resident credentials
@@ -1007,6 +1067,7 @@ declare class Web3Passkey {
1007
1067
  blob: Blob;
1008
1068
  filename: string;
1009
1069
  }>;
1070
+ private backupCredential;
1010
1071
  /**
1011
1072
  * Set up social recovery by splitting backup file among guardians
1012
1073
  * Uses Shamir Secret Sharing to split the backup - requires M-of-N guardians to recover
@@ -1066,6 +1127,9 @@ declare class Web3Passkey {
1066
1127
  *
1067
1128
  * This allows the user to use the same PRIMARY mode webauthn account on multiple devices.
1068
1129
  *
1130
+ * A PRF backup (from exportForSync()) takes a single assertion restricted
1131
+ * to its passkey and no password.
1132
+ *
1069
1133
  * @param backupData - Backup file (JSON string or Blob) - can be pasted by user
1070
1134
  * @param password - Password to decrypt backup (if password-encrypted)
1071
1135
  * @returns Restored wallet info
@@ -1074,6 +1138,18 @@ declare class Web3Passkey {
1074
1138
  mnemonic: string;
1075
1139
  ethereumAddress: string;
1076
1140
  }>;
1141
+ /**
1142
+ * Restore a PRF backup with its passkey and set this device up for it.
1143
+ * The public key is this device's when it has the passkey's metadata,
1144
+ * else the backup's, checked against the assertion's signature.
1145
+ */
1146
+ private restorePrfBackup;
1147
+ /**
1148
+ * Set this device up for a passkey and a synced wallet: saves the
1149
+ * passkey's metadata (or points it at the wallet), stores the wallet
1150
+ * under the passkey-derived key and starts a session
1151
+ */
1152
+ private bootstrapCredential;
1077
1153
  /**
1078
1154
  * Register new passkey with wallet from backup file
1079
1155
  * Use case: Fresh device, user has backup file but no passkey yet
@@ -1094,16 +1170,30 @@ declare class Web3Passkey {
1094
1170
  getSyncStatus(): Promise<any>;
1095
1171
  /**
1096
1172
  * Export wallet for syncing to another device
1097
- * Uses passkey encryption so it works on devices where the passkey is synced
1173
+ *
1174
+ * Prompts for the passkey and encrypts with a key derived from its WebAuthn
1175
+ * PRF output (`encryptionMethod: 'prf'`): a device where the passkey synced
1176
+ * restores it with one prompt and no password. Where the authenticator has
1177
+ * no PRF support, `password` makes it fall back to a password backup.
1178
+ *
1179
+ * @param password - Fallback password when PRF is unavailable
1180
+ * @throws PrfUnsupportedError when PRF is unavailable and no password is given
1098
1181
  */
1099
- exportForSync(): Promise<{
1182
+ exportForSync(password?: string): Promise<{
1100
1183
  blob: Blob;
1101
1184
  filename: string;
1102
1185
  qrCode?: string;
1103
1186
  }>;
1104
1187
  /**
1105
1188
  * Import wallet from another device (sync wallet to this device)
1106
- * Use case: User has passkey on both devices, wallet only on one
1189
+ *
1190
+ * Takes a PRF backup from exportForSync(): one assertion restricted to
1191
+ * the backup's passkey decrypts it, with no password, on any device where
1192
+ * the passkey synced, including one with no data for it. Works without a
1193
+ * login. For a password backup (exportForSync()'s fallback), use
1194
+ * syncWalletWithPasskey().
1195
+ *
1196
+ * @throws SyncBootstrapError ('CREDENTIAL_MISMATCH') when logged in with another passkey
1107
1197
  */
1108
1198
  importFromSync(syncData: string | Blob): Promise<{
1109
1199
  ethereumAddress: string;
@@ -1158,6 +1248,23 @@ declare class Web3Passkey {
1158
1248
  * @param hours - Duration in hours
1159
1249
  */
1160
1250
  setPersistentSessionDuration(hours: number): void;
1251
+ /**
1252
+ * Derive a 32-byte secret bound to the passkey, separate per origin and tag
1253
+ *
1254
+ * Evaluates the WebAuthn PRF extension on a fresh user-verified assertion
1255
+ * and runs HKDF-SHA256 on the output. The secret is never derived from or
1256
+ * stored with the mnemonic, so it never appears in backups, recovery
1257
+ * phrases, sessions or storage. When logged in, the assertion is
1258
+ * restricted to the current user's passkey.
1259
+ *
1260
+ * @param tag - Non-empty label without ':', e.g. "zk-identity"
1261
+ * @returns The secret and the credential it is bound to
1262
+ * @throws PrfUnsupportedError when the authenticator doesn't support PRF
1263
+ *
1264
+ * @example
1265
+ * const { secret, credentialId } = await w3pk.derivePrfSecret("zk-identity")
1266
+ */
1267
+ derivePrfSecret(tag: string): Promise<PrfSecret>;
1161
1268
  /**
1162
1269
  * Derive ML-KEM-1024 public key from the current wallet
1163
1270
  *
@@ -1443,31 +1550,6 @@ declare function verifyEIP7702Authorization(chainId: bigint, contractAddress: st
1443
1550
  s: string;
1444
1551
  } | string, expectedSigner: string): boolean;
1445
1552
 
1446
- /** Client extension results consumed by w3pk (subset of the WebAuthn spec) */
1447
- interface PrfExtensionResults {
1448
- prf?: {
1449
- enabled?: boolean;
1450
- results?: {
1451
- first?: ArrayBuffer;
1452
- };
1453
- };
1454
- }
1455
- /**
1456
- * Native WebAuthn credential response (authentication)
1457
- */
1458
- interface AuthenticationCredential {
1459
- id: string;
1460
- rawId: ArrayBuffer;
1461
- type: 'public-key';
1462
- response: {
1463
- clientDataJSON: ArrayBuffer;
1464
- authenticatorData: ArrayBuffer;
1465
- signature: ArrayBuffer;
1466
- userHandle?: ArrayBuffer;
1467
- };
1468
- getClientExtensionResults(): PrfExtensionResults;
1469
- }
1470
-
1471
1553
  /**
1472
1554
  * Sync Authentication Helper
1473
1555
  * Handles passkey selection and authentication for cross-device sync scenarios
@@ -1477,6 +1559,9 @@ interface PasskeySelectionResult {
1477
1559
  credentialId: string;
1478
1560
  publicKey: string;
1479
1561
  ethereumAddress?: string;
1562
+ username?: string;
1563
+ /** The selection assertion, to verify against a public key from a backup */
1564
+ assertion: AuthenticationCredential;
1480
1565
  }
1481
1566
  /**
1482
1567
  * Prompts the user to select a passkey/webauthn credential
@@ -2352,4 +2437,4 @@ declare function mlkemDecryptWithKey(payload: EncryptedPayload, privateKey: stri
2352
2437
 
2353
2438
  declare function createWeb3Passkey(config?: Web3PasskeyConfig): Web3Passkey;
2354
2439
 
2355
- export { ApiError, AuthenticationError, type BackupMethod, type BackupStatus, type BrowserInspectOptions, type BrowserInspectResult, CryptoError, DEFAULT_MODE, DEFAULT_TAG, type DeviceInfo, type EIP1193Provider, type EIP7702Authorization, type EncryptedBackupInfo, type EncryptedPayload, type Guardian, type GuardianInvite, type MLKemKeypair, type PasskeySelectionResult, type QRBackupOptions, type RecoveryProgress, type RecoveryScenario, type RecoveryShare, RecoverySimulator, RegistrationError, type SecurityScore, type SignAuthorizationParams, type SimulationResult, type SiweMessage, type SocialRecoveryConfig, SocialRecoveryManager, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, type SyncCapabilities, SyncRequiredError, type SyncStatus, type SyncVault, type UserInfo, WalletError, type WalletInfo, WalletMissingError, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, arrayBufferToBase64Url, assertEthereumAddress, assertMnemonic, assertUsername, authenticateWithPasskey, base64ToArrayBuffer, base64UrlDecode, base64UrlToArrayBuffer, canControlStealthAddress, checkStealthAddress, clearCache, computeStealthPrivateKey, createSiweMessage, createWalletFromMnemonic, createWeb3Passkey, createWeb3Passkey as default, deriveAddressFromP256PublicKey, deriveIndexFromOriginModeAndTag, deriveMLKemKeypair, deriveStealthKeys, deriveWalletFromMnemonic, detectWalletProvider, encodeEIP7702AuthorizationMessage, extractRS, generateBIP39Wallet, generateSiweNonce, generateStealthAddress, getAllChains, getAllTopics, getChainById, getCurrentBuildHash, getCurrentOrigin, getDefaultProvider, getEndpoints, getExplainer, getOriginSpecificAddress, getPackageVersion, getW3pkBuildHash, hashEIP7702AuthorizationMessage, inspect, inspectNow, isStrongPassword, mlkemDecrypt, mlkemDecryptWithKey, mlkemEncrypt, mlkemEncryptWithKey, normalizeOrigin, parseSiweMessage, promptPasskeySelection, requestExternalWalletAuthorization, safeAtob, safeBtoa, searchExplainers, supportsEIP7702Authorization, validateEthereumAddress, validateMnemonic, validateSiweMessage, validateUsername, verifyBuildHash, verifyEIP7702Authorization, verifySiweSignature };
2440
+ export { ApiError, AuthenticationError, type BackupMethod, type BackupStatus, type BrowserInspectOptions, type BrowserInspectResult, CryptoError, DEFAULT_MODE, DEFAULT_TAG, type DeviceInfo, type EIP1193Provider, type EIP7702Authorization, type EncryptedBackupInfo, type EncryptedPayload, type Guardian, type GuardianInvite, type MLKemKeypair, type PasskeySelectionResult, type PrfSecret, PrfUnsupportedError, type QRBackupOptions, type RecoveryProgress, type RecoveryScenario, type RecoveryShare, RecoverySimulator, RegistrationError, type SecurityScore, type SignAuthorizationParams, type SimulationResult, type SiweMessage, type SocialRecoveryConfig, SocialRecoveryManager, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, SyncBootstrapError, type SyncBootstrapReason, type SyncCapabilities, SyncRequiredError, type SyncStatus, type SyncVault, type UserInfo, WalletError, type WalletInfo, WalletMissingError, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, arrayBufferToBase64Url, assertEthereumAddress, assertMnemonic, assertUsername, authenticateWithPasskey, base64ToArrayBuffer, base64UrlDecode, base64UrlToArrayBuffer, canControlStealthAddress, checkStealthAddress, clearCache, computeStealthPrivateKey, createSiweMessage, createWalletFromMnemonic, createWeb3Passkey, createWeb3Passkey as default, deriveAddressFromP256PublicKey, deriveIndexFromOriginModeAndTag, deriveMLKemKeypair, deriveStealthKeys, deriveWalletFromMnemonic, detectWalletProvider, encodeEIP7702AuthorizationMessage, extractRS, generateBIP39Wallet, generateSiweNonce, generateStealthAddress, getAllChains, getAllTopics, getChainById, getCurrentBuildHash, getCurrentOrigin, getDefaultProvider, getEndpoints, getExplainer, getOriginSpecificAddress, getPackageVersion, getW3pkBuildHash, hashEIP7702AuthorizationMessage, inspect, inspectNow, isStrongPassword, mlkemDecrypt, mlkemDecryptWithKey, mlkemEncrypt, mlkemEncryptWithKey, normalizeOrigin, parseSiweMessage, promptPasskeySelection, requestExternalWalletAuthorization, safeAtob, safeBtoa, searchExplainers, supportsEIP7702Authorization, validateEthereumAddress, validateMnemonic, validateSiweMessage, validateUsername, verifyBuildHash, verifyEIP7702Authorization, verifySiweSignature };