w3pk 0.7.2 → 0.7.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
@@ -5,7 +5,8 @@
5
5
 
6
6
  Passwordless Web3 authentication SDK with encrypted wallets and privacy features.
7
7
 
8
- **Demo: [w3pk.w3hc.org](https://w3pk.w3hc.org)**
8
+ - **Live demo: [w3pk.w3hc.org](https://w3pk.w3hc.org)**
9
+ - [Quick start](./docs/QUICK_START.md)
9
10
 
10
11
  ## Install
11
12
  ```bash
@@ -39,7 +40,6 @@ const rpcUrl = endpoints[0]
39
40
 
40
41
  ## Features
41
42
 
42
- **Core (Included)**
43
43
  - 🔐 Passwordless authentication (WebAuthn/FIDO2)
44
44
  - 🔒 Client-only biometric-gated wallet encryption (AES-GCM-256)
45
45
  - ⏱️ Session management (configurable duration, prevents repeated prompts)
@@ -289,14 +289,9 @@ See [Recovery Guide](./docs/RECOVERY.md) for complete documentation.
289
289
  ## Documentation
290
290
 
291
291
  - [Quick Start Guide](./docs/QUICK_START.md) - Get started in 5 minutes
292
- - [Recovery & Backup System](./docs/RECOVERY.md) - Three-layer backup architecture
293
- - [Browser Compatibility](./docs/BROWSER_COMPATIBILITY.md) - Supported browsers, devices, and OS versions
292
+ - [API Reference](./docs/API_REFERENCE.md) - Complete API documentation
294
293
  - [Security Architecture](./docs/SECURITY.md) - Integration best practices
295
- - [ERC-5564 Stealth Addresses](./docs/ERC5564_STEALTH_ADDRESSES.md) - Complete guide with examples
296
- - [ERC-5564 Flow Diagrams](./docs/ERC5564_FLOW_DIAGRAM.md) - Visual explanations of how stealth addresses work
297
- - [RPC Endpoints](./docs/CHAINLIST.md) - Chainlist integration guide
298
- - [ZK Integration Guide](./docs/ZK_INTEGRATION_GUIDE.md) - Zero-knowledge proofs (optional)
299
- - [Bundle Size Comparison](./docs/BUNDLE_SIZES.md) - Core vs ZK bundle sizes
294
+ - [Recovery & Backup System](./docs/RECOVERY.md) - Three-layer backup architecture
300
295
 
301
296
  ## Contributing
302
297
 
package/dist/index.d.mts CHANGED
@@ -21,8 +21,6 @@ interface StealthKeys {
21
21
  viewingKey: string;
22
22
  /** Spending private key (32 bytes) */
23
23
  spendingKey: string;
24
- /** @deprecated Legacy meta-address format (kept for backward compatibility) */
25
- metaAddress?: string;
26
24
  }
27
25
  /**
28
26
  * ERC-5564 Stealth Address Generation Result
@@ -34,10 +32,6 @@ interface StealthAddressResult$1 {
34
32
  ephemeralPubKey: string;
35
33
  /** View tag (1 byte) for efficient scanning */
36
34
  viewTag: string;
37
- /** @deprecated Use ephemeralPubKey instead */
38
- ephemeralPubkey?: string;
39
- /** @deprecated Sender doesn't get the private key in ERC-5564 */
40
- stealthPrivkey?: string;
41
35
  }
42
36
  /**
43
37
  * ERC-5564 Parse/Check Result
@@ -108,9 +102,18 @@ declare function checkStealthAddress(viewingKey: string, spendingPubKey: string,
108
102
  */
109
103
  declare function computeStealthPrivateKey(viewingKey: string, spendingKey: string, ephemeralPubKey: string): string;
110
104
  /**
111
- * @deprecated Use checkStealthAddress instead
105
+ * ERC-5564: Check if user can control a stealth address
106
+ * Verifies that the user's keys can derive the correct private key for a stealth address.
107
+ *
108
+ * @param viewingKey - Recipient's viewing private key
109
+ * @param spendingKey - Recipient's spending private key
110
+ * @param spendingPubKey - Recipient's spending public key (compressed)
111
+ * @param ephemeralPubKey - Ephemeral public key from announcement
112
+ * @param stealthAddress - The stealth address to verify control of
113
+ * @param viewTag - View tag from announcement (optional, for optimization)
114
+ * @returns True if the user can control the stealth address
112
115
  */
113
- declare function canControlStealthAddress(viewingKey: string, spendingKey: string, ephemeralPubkey: string, targetAddress: string): boolean;
116
+ declare function canControlStealthAddress(viewingKey: string, spendingKey: string, spendingPubKey: string, ephemeralPubKey: string, stealthAddress: string, viewTag?: string): boolean;
114
117
 
115
118
  /**
116
119
  * ERC-5564 Stealth Address Module for w3pk SDK
@@ -132,8 +135,6 @@ interface StealthAddressResult {
132
135
  ephemeralPublicKey: string;
133
136
  /** View tag (1 byte) for efficient scanning */
134
137
  viewTag: string;
135
- /** @deprecated Legacy field - sender doesn't get the private key in ERC-5564 */
136
- stealthPrivateKey?: string;
137
138
  }
138
139
  /**
139
140
  * ERC-5564 Announcement (what gets published on-chain)
@@ -552,10 +553,6 @@ declare class Web3Passkey {
552
553
  * @param hours - Session duration in hours
553
554
  */
554
555
  setSessionDuration(hours: number): void;
555
- /**
556
- * SDK version
557
- */
558
- get version(): string;
559
556
  }
560
557
 
561
558
  /**
@@ -852,10 +849,11 @@ declare class SocialRecoveryManager {
852
849
  generateGuardianInvite(guardian: Guardian): Promise<GuardianInvite>;
853
850
  /**
854
851
  * Generate QR code from share data
852
+ * Uses 'qrcode' library if available, falls back to canvas text
855
853
  */
856
854
  private generateQRCode;
857
855
  /**
858
- * Create placeholder QR code
856
+ * Create fallback QR representation
859
857
  */
860
858
  private createPlaceholderQR;
861
859
  /**
package/dist/index.d.ts CHANGED
@@ -21,8 +21,6 @@ interface StealthKeys {
21
21
  viewingKey: string;
22
22
  /** Spending private key (32 bytes) */
23
23
  spendingKey: string;
24
- /** @deprecated Legacy meta-address format (kept for backward compatibility) */
25
- metaAddress?: string;
26
24
  }
27
25
  /**
28
26
  * ERC-5564 Stealth Address Generation Result
@@ -34,10 +32,6 @@ interface StealthAddressResult$1 {
34
32
  ephemeralPubKey: string;
35
33
  /** View tag (1 byte) for efficient scanning */
36
34
  viewTag: string;
37
- /** @deprecated Use ephemeralPubKey instead */
38
- ephemeralPubkey?: string;
39
- /** @deprecated Sender doesn't get the private key in ERC-5564 */
40
- stealthPrivkey?: string;
41
35
  }
42
36
  /**
43
37
  * ERC-5564 Parse/Check Result
@@ -108,9 +102,18 @@ declare function checkStealthAddress(viewingKey: string, spendingPubKey: string,
108
102
  */
109
103
  declare function computeStealthPrivateKey(viewingKey: string, spendingKey: string, ephemeralPubKey: string): string;
110
104
  /**
111
- * @deprecated Use checkStealthAddress instead
105
+ * ERC-5564: Check if user can control a stealth address
106
+ * Verifies that the user's keys can derive the correct private key for a stealth address.
107
+ *
108
+ * @param viewingKey - Recipient's viewing private key
109
+ * @param spendingKey - Recipient's spending private key
110
+ * @param spendingPubKey - Recipient's spending public key (compressed)
111
+ * @param ephemeralPubKey - Ephemeral public key from announcement
112
+ * @param stealthAddress - The stealth address to verify control of
113
+ * @param viewTag - View tag from announcement (optional, for optimization)
114
+ * @returns True if the user can control the stealth address
112
115
  */
113
- declare function canControlStealthAddress(viewingKey: string, spendingKey: string, ephemeralPubkey: string, targetAddress: string): boolean;
116
+ declare function canControlStealthAddress(viewingKey: string, spendingKey: string, spendingPubKey: string, ephemeralPubKey: string, stealthAddress: string, viewTag?: string): boolean;
114
117
 
115
118
  /**
116
119
  * ERC-5564 Stealth Address Module for w3pk SDK
@@ -132,8 +135,6 @@ interface StealthAddressResult {
132
135
  ephemeralPublicKey: string;
133
136
  /** View tag (1 byte) for efficient scanning */
134
137
  viewTag: string;
135
- /** @deprecated Legacy field - sender doesn't get the private key in ERC-5564 */
136
- stealthPrivateKey?: string;
137
138
  }
138
139
  /**
139
140
  * ERC-5564 Announcement (what gets published on-chain)
@@ -552,10 +553,6 @@ declare class Web3Passkey {
552
553
  * @param hours - Session duration in hours
553
554
  */
554
555
  setSessionDuration(hours: number): void;
555
- /**
556
- * SDK version
557
- */
558
- get version(): string;
559
556
  }
560
557
 
561
558
  /**
@@ -852,10 +849,11 @@ declare class SocialRecoveryManager {
852
849
  generateGuardianInvite(guardian: Guardian): Promise<GuardianInvite>;
853
850
  /**
854
851
  * Generate QR code from share data
852
+ * Uses 'qrcode' library if available, falls back to canvas text
855
853
  */
856
854
  private generateQRCode;
857
855
  /**
858
- * Create placeholder QR code
856
+ * Create fallback QR representation
859
857
  */
860
858
  private createPlaceholderQR;
861
859
  /**
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var Rt=Object.create;var Z=Object.defineProperty;var xt=Object.getOwnPropertyDescriptor;var It=Object.getOwnPropertyNames;var Bt=Object.getPrototypeOf,Tt=Object.prototype.hasOwnProperty;var u=(s,e)=>()=>(s&&(e=s(s=0)),e);var S=(s,e)=>{for(var t in e)Z(s,t,{get:e[t],enumerable:!0})},Qe=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of It(e))!Tt.call(s,n)&&n!==t&&Z(s,n,{get:()=>e[n],enumerable:!(r=xt(e,n))||r.enumerable});return s};var B=(s,e,t)=>(t=s!=null?Rt(Bt(s)):{},Qe(e||!s||!s.__esModule?Z(t,"default",{value:s,enumerable:!0}):t,s)),Dt=s=>Qe(Z({},"__esModule",{value:!0}),s);var g,k,T,d,y,h,X,w=u(()=>{"use strict";g=class extends Error{constructor(t,r,n){super(t);this.code=r;this.originalError=n;this.name="Web3PasskeyError"}},k=class extends g{constructor(e,t){super(e,"AUTHENTICATION_ERROR",t),this.name="AuthenticationError"}},T=class extends g{constructor(e,t){super(e,"REGISTRATION_ERROR",t),this.name="RegistrationError"}},d=class extends g{constructor(e,t){super(e,"WALLET_ERROR",t),this.name="WalletError"}},y=class extends g{constructor(e,t){super(e,"CRYPTO_ERROR",t),this.name="CryptoError"}},h=class extends g{constructor(e,t){super(e,"STORAGE_ERROR",t),this.name="StorageError"}},X=class extends g{constructor(t,r,n){super(t,"API_ERROR",n);this.statusCode=r;this.name="ApiError"}}});var _={};S(_,{CredentialStorage:()=>C});var re,ne,C,R=u(()=>{"use strict";w();re="w3pk_credential_",ne="w3pk_credential_index",C=class{constructor(e){if(e)this.storage=e;else if(typeof window<"u"&&window.localStorage)this.storage=window.localStorage;else throw new h("localStorage is not available")}saveCredential(e){try{let t=`${re}${e.id}`;this.storage.setItem(t,JSON.stringify(e)),this.addToIndex(e.id)}catch(t){throw new h("Failed to save credential",t)}}getCredentialById(e){try{let t=`${re}${e}`,r=this.storage.getItem(t);return r?JSON.parse(r):null}catch(t){throw new h("Failed to retrieve credential",t)}}getCredentialByUsername(e){try{return this.getAllCredentials().find(r=>r.username===e)||null}catch(t){throw new h("Failed to retrieve credential",t)}}getCredentialByAddress(e){try{return this.getAllCredentials().find(r=>r.ethereumAddress.toLowerCase()===e.toLowerCase())||null}catch(t){throw new h("Failed to retrieve credential",t)}}getAllCredentials(){try{return this.getIndex().map(t=>this.getCredentialById(t)).filter(t=>t!==null)}catch(e){throw new h("Failed to retrieve credentials",e)}}userExists(e){return this.getCredentialByUsername(e)!==null}updateLastUsed(e){try{let t=this.getCredentialById(e);t&&(t.lastUsed=Date.now(),this.saveCredential(t))}catch(t){throw new h("Failed to update timestamp",t)}}deleteCredential(e){try{let t=`${re}${e}`;this.storage.removeItem(t),this.removeFromIndex(e)}catch(t){throw new h("Failed to delete credential",t)}}clearAll(){try{this.getIndex().forEach(t=>{let r=`${re}${t}`;this.storage.removeItem(r)}),this.storage.removeItem(ne)}catch(e){throw new h("Failed to clear credentials",e)}}getIndex(){try{let e=this.storage.getItem(ne);return e?JSON.parse(e):[]}catch{return[]}}addToIndex(e){let t=this.getIndex();t.includes(e)||(t.push(e),this.storage.setItem(ne,JSON.stringify(t)))}removeFromIndex(e){let r=this.getIndex().filter(n=>n!==e);this.storage.setItem(ne,JSON.stringify(r))}}});var xe={};S(xe,{decryptData:()=>le,deriveEncryptionKey:()=>Lt,deriveEncryptionKeyFromSignature:()=>qt,deriveEncryptionKeyFromWebAuthn:()=>x,encryptData:()=>de,generateChallenge:()=>Gt});async function x(s,e){try{let t=e?`w3pk-v4:${s}:${e}`:`w3pk-v4:${s}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t)),n=await crypto.subtle.importKey("raw",r,{name:"PBKDF2"},!1,["deriveKey"]),o=await crypto.subtle.digest("SHA-256",new TextEncoder().encode("w3pk-salt-v4"));return crypto.subtle.deriveKey({name:"PBKDF2",salt:new Uint8Array(o),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new y("Failed to derive encryption key from WebAuthn",t)}}async function Lt(s,e){try{let t=e?`w3pk-v2:${s}:${e}`:`w3pk-v2:${s}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t)),n=await crypto.subtle.importKey("raw",r,{name:"PBKDF2"},!1,["deriveKey"]),o=await crypto.subtle.digest("SHA-256",new TextEncoder().encode("w3pk-salt-v2"));return crypto.subtle.deriveKey({name:"PBKDF2",salt:new Uint8Array(o),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new y("Failed to derive encryption key",t)}}async function qt(s,e){try{if(typeof window<"u"&&window.PublicKeyCredential)return x(e);let t=await crypto.subtle.digest("SHA-256",s),r=await crypto.subtle.importKey("raw",t,{name:"PBKDF2"},!1,["deriveKey"]),n=await crypto.subtle.digest("SHA-256",new TextEncoder().encode("w3pk-salt-v3:"+e));return crypto.subtle.deriveKey({name:"PBKDF2",salt:new Uint8Array(n),iterations:21e4,hash:"SHA-256"},r,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new y("Failed to derive encryption key",t)}}function Gt(){let s=new Uint8Array(32);return crypto.getRandomValues(s),btoa(String.fromCharCode(...s)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function de(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 y("Failed to encrypt data",t)}}async function le(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 y(`Data decryption failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}var ue=u(()=>{"use strict";w()});var A,Te=u(()=>{"use strict";A=class{constructor(){this.dbName="Web3PasskeyBackup";this.version=1;this.db=null}async init(){return typeof indexedDB>"u"?Promise.resolve():new Promise((e,t)=>{let r=indexedDB.open(this.dbName,this.version);r.onerror=()=>t(r.error),r.onsuccess=()=>{this.db=r.result,e()},r.onupgradeneeded=n=>{let o=n.target.result;if(!o.objectStoreNames.contains("backups")){let i=o.createObjectStore("backups",{keyPath:"id"});i.createIndex("ethereumAddress","ethereumAddress",{unique:!1}),i.createIndex("method","method",{unique:!1}),i.createIndex("createdAt","createdAt",{unique:!1})}}})}async storeBackupMetadata(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let i=this.db.transaction(["backups"],"readwrite").objectStore("backups").put(e);i.onsuccess=()=>t(),i.onerror=()=>r(i.error)}):Promise.resolve()}async getBackupsByAddress(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let c=this.db.transaction(["backups"],"readonly").objectStore("backups").index("ethereumAddress").getAll(e);c.onsuccess=()=>t(c.result),c.onerror=()=>r(c.error)}):Promise.resolve([])}async getBackupById(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let i=this.db.transaction(["backups"],"readonly").objectStore("backups").get(e);i.onsuccess=()=>t(i.result||null),i.onerror=()=>r(i.error)}):Promise.resolve(null)}async deleteBackup(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let i=this.db.transaction(["backups"],"readwrite").objectStore("backups").delete(e);i.onsuccess=()=>t(),i.onerror=()=>r(i.error)}):Promise.resolve()}async getBackupCountByMethod(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let c=this.db.transaction(["backups"],"readonly").objectStore("backups").index("method").count(e);c.onsuccess=()=>t(c.result),c.onerror=()=>r(c.error)}):Promise.resolve(0)}}});var Fe={};S(Fe,{decryptWithPassword:()=>lt,deriveAddressChecksum:()=>b,deriveKeyFromPassword:()=>ge,encryptWithPassword:()=>M,getDeviceFingerprint:()=>f,validatePasswordStrength:()=>fe});async function ge(s,e,t=31e4){let n=new TextEncoder().encode(s),o=await crypto.subtle.importKey("raw",n,"PBKDF2",!1,["deriveBits","deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:e,iterations:t,hash:"SHA-256"},o,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function M(s,e,t){let n=await ge(e,t,31e4),i=new TextEncoder().encode(s),c=crypto.getRandomValues(new Uint8Array(12)),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:c},n,i);return{encrypted:j(a),iv:j(c),salt:j(t),iterations:31e4}}async function lt(s,e,t,r,n=31e4){let o=De(t),i=await ge(e,o,n),c=De(r),a=De(s),l=await crypto.subtle.decrypt({name:"AES-GCM",iv:c},i,a);return new TextDecoder().decode(l)}async function f(){let e=[navigator.userAgent,navigator.language,new Date().getTimezoneOffset().toString(),screen.width+"x"+screen.height,screen.colorDepth.toString()].join("|"),r=new TextEncoder().encode(e),n=await crypto.subtle.digest("SHA-256",r);return j(n)}async function b(s){let t=new TextEncoder().encode(s.toLowerCase()),r=await crypto.subtle.digest("SHA-256",t);return j(r).substring(0,16)}function fe(s){let e=[],t=0;return s.length<12?e.push("Password must be at least 12 characters"):t+=25,/[A-Z]/.test(s)?t+=15:e.push("Add at least one uppercase letter"),/[a-z]/.test(s)?t+=15:e.push("Add at least one lowercase letter"),/[0-9]/.test(s)?t+=15:e.push("Add at least one number"),/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(s)?t+=15:e.push("Add at least one special character"),s.length>=16&&(t+=10),s.length>=20&&(t+=5),["password","12345678","qwerty","abc123","password123","admin","letmein"].some(n=>s.toLowerCase().includes(n))&&(e.push("Password is too common"),t=Math.min(t,25)),{valid:t>=50&&e.length===0,score:Math.min(t,100),feedback:e}}function j(s){let e=s instanceof Uint8Array?s:new Uint8Array(s),t="";for(let r=0;r<e.byteLength;r++)t+=String.fromCharCode(e[r]);return btoa(t)}function De(s){let e=atob(s),t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}var E=u(()=>{"use strict"});var K,Me=u(()=>{"use strict";E();K=class{async createZipBackup(e,t,r){let n=fe(r.password);if(!n.valid)throw new Error(`Weak password: ${n.feedback.join(", ")}`);let o=crypto.getRandomValues(new Uint8Array(32)),i=await M(e,r.password,o),c=r.deviceBinding?await f():void 0,a={id:crypto.randomUUID(),ethereumAddress:t,method:"zip",createdAt:Date.now(),deviceFingerprint:c,addressChecksum:await b(t)},l={version:1,encrypted:i.encrypted,iv:i.iv,salt:i.salt,iterations:i.iterations,metadata:a,deviceFingerprint:c},p=new Map;return p.set("recovery-phrase.txt.enc",JSON.stringify(l,null,2)),p.set("metadata.json",JSON.stringify({address:t,createdAt:new Date(a.createdAt).toISOString(),backupId:a.id,addressChecksum:a.addressChecksum},null,2)),r.includeInstructions!==!1&&p.set("RECOVERY_INSTRUCTIONS.txt",this.getRecoveryInstructions()),{blob:await this.createSimpleZip(p),metadata:a}}async createSimpleZip(e){let t={};return e.forEach((r,n)=>{t[n]=r}),new Blob([JSON.stringify(t,null,2)],{type:"application/json"})}getRecoveryInstructions(){return`
1
+ "use strict";var Kt=Object.create;var ie=Object.defineProperty;var Ut=Object.getOwnPropertyDescriptor;var Ot=Object.getOwnPropertyNames;var Wt=Object.getPrototypeOf,Nt=Object.prototype.hasOwnProperty;var u=(s,e)=>()=>(s&&(e=s(s=0)),e);var S=(s,e)=>{for(var t in e)ie(s,t,{get:e[t],enumerable:!0})},tt=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Ot(e))!Nt.call(s,n)&&n!==t&&ie(s,n,{get:()=>e[n],enumerable:!(r=Ut(e,n))||r.enumerable});return s};var T=(s,e,t)=>(t=s!=null?Kt(Wt(s)):{},tt(e||!s||!s.__esModule?ie(t,"default",{value:s,enumerable:!0}):t,s)),Lt=s=>tt(ie({},"__esModule",{value:!0}),s);var m,k,D,d,h,y,ce,w=u(()=>{"use strict";m=class extends Error{constructor(t,r,n){super(t);this.code=r;this.originalError=n;this.name="Web3PasskeyError"}},k=class extends m{constructor(e,t){super(e,"AUTHENTICATION_ERROR",t),this.name="AuthenticationError"}},D=class extends m{constructor(e,t){super(e,"REGISTRATION_ERROR",t),this.name="RegistrationError"}},d=class extends m{constructor(e,t){super(e,"WALLET_ERROR",t),this.name="WalletError"}},h=class extends m{constructor(e,t){super(e,"CRYPTO_ERROR",t),this.name="CryptoError"}},y=class extends m{constructor(e,t){super(e,"STORAGE_ERROR",t),this.name="StorageError"}},ce=class extends m{constructor(t,r,n){super(t,"API_ERROR",n);this.statusCode=r;this.name="ApiError"}}});function R(s){try{let e=s.replace(/-/g,"+").replace(/_/g,"/"),t=(4-e.length%4)%4;e+="=".repeat(t);let r=atob(e),n=new Uint8Array(r.length);for(let o=0;o<r.length;o++)n[o]=r.charCodeAt(o);return n.buffer}catch(e){throw new Error(`Failed to decode base64url string: ${e instanceof Error?e.message:"Invalid format"}`)}}function A(s){let e=s instanceof Uint8Array?s:new Uint8Array(s),t="";for(let r=0;r<e.length;r++)t+=String.fromCharCode(e[r]);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function F(s){try{let e=s.replace(/-/g,"+").replace(/_/g,"/"),t=(4-e.length%4)%4;return e+="=".repeat(t),atob(e)}catch(e){throw new Error(`Failed to decode base64 string: ${e instanceof Error?e.message:"Invalid format"}`)}}var J=u(()=>{"use strict"});var Ke={};S(Ke,{decryptData:()=>Z,decryptMetadata:()=>pe,deriveEncryptionKey:()=>qt,deriveEncryptionKeyFromWebAuthn:()=>M,encryptData:()=>z,encryptMetadata:()=>ue,generateChallenge:()=>$t,hashCredentialId:()=>K,hashPublicKey:()=>Me});async function M(s,e){try{let t=e?`w3pk-v4:${s}:${e}`:`w3pk-v4:${s}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t)),n=await crypto.subtle.importKey("raw",r,{name:"PBKDF2"},!1,["deriveKey"]),o=await crypto.subtle.digest("SHA-256",new TextEncoder().encode("w3pk-salt-v4"));return crypto.subtle.deriveKey({name:"PBKDF2",salt:new Uint8Array(o),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new h("Failed to derive encryption key from WebAuthn",t)}}async function qt(s,e){try{let t=e?`w3pk-v2:${s}:${e}`:`w3pk-v2:${s}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t)),n=await crypto.subtle.importKey("raw",r,{name:"PBKDF2"},!1,["deriveKey"]),o=await crypto.subtle.digest("SHA-256",new TextEncoder().encode("w3pk-salt-v2"));return crypto.subtle.deriveKey({name:"PBKDF2",salt:new Uint8Array(o),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}catch(t){throw new h("Failed to derive encryption key",t)}}function $t(){let s=new Uint8Array(32);return crypto.getRandomValues(s),A(s)}async function z(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);o.set(t),o.set(new Uint8Array(n),t.length);let a="";for(let i=0;i<o.length;i++)a+=String.fromCharCode(o[i]);return btoa(a)}catch(t){throw new h("Failed to encrypt data",t)}}async function Z(s,e){try{if(!s||s.length<16)throw new Error("Invalid encrypted data: too small");let t=F(s),r=new Uint8Array(t.length);for(let i=0;i<t.length;i++)r[i]=t.charCodeAt(i);if(r.length<12)throw new Error("Invalid encrypted data: missing IV");let n=r.slice(0,12),o=r.slice(12);if(o.length===0)throw new Error("Invalid encrypted data: no content");let a=await crypto.subtle.decrypt({name:"AES-GCM",iv:n},e,o);return new TextDecoder().decode(a)}catch(t){throw new h(`Data decryption failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}async function K(s){try{let e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(`w3pk-cred-id:${s}`));return A(e)}catch(e){throw new h("Failed to hash credential ID",e)}}async function Me(s){try{let e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(s));return A(e)}catch(e){throw new h("Failed to hash public key",e)}}async function ue(s,e){return z(s,e)}async function pe(s,e){return Z(s,e)}var X=u(()=>{"use strict";w();J()});var ee={};S(ee,{CredentialStorage:()=>x});async function st(s){let e=new TextEncoder().encode(`w3pk-metadata-v1:${s}`),t=await crypto.subtle.digest("SHA-256",e),r=await crypto.subtle.importKey("raw",t,{name:"PBKDF2"},!1,["deriveKey"]);return await crypto.subtle.deriveKey({name:"PBKDF2",salt:new TextEncoder().encode("w3pk-metadata-salt-v1"),iterations:1e5,hash:"SHA-256"},r,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}var he,ye,x,I=u(()=>{"use strict";w();X();he="w3pk_credential_",ye="w3pk_credential_index";x=class{constructor(e){if(e)this.storage=e;else if(typeof window<"u"&&window.localStorage)this.storage=window.localStorage;else throw new y("localStorage is not available")}async saveCredential(e){try{let t=await st(e.id),r=await K(e.id),n={id:r,encryptedUsername:await ue(e.username,t),encryptedAddress:await ue(e.ethereumAddress,t),publicKeyFingerprint:await Me(e.publicKey),createdAt:e.createdAt,lastUsed:e.lastUsed},o=`${he}${r}`;this.storage.setItem(o,JSON.stringify(n)),await this.addToIndex(e.id)}catch(t){throw new y("Failed to save credential",t)}}async getCredentialById(e){try{let t=await K(e),r=`${he}${t}`,n=this.storage.getItem(r);if(!n)return null;let o=JSON.parse(n),a=await st(e);return{id:e,publicKey:"",username:await pe(o.encryptedUsername,a),ethereumAddress:await pe(o.encryptedAddress,a),createdAt:o.createdAt,lastUsed:o.lastUsed}}catch(t){throw new y("Failed to retrieve credential",t)}}async getCredentialByUsername(e){try{return(await this.getAllCredentials()).find(r=>r.username===e)||null}catch(t){throw new y("Failed to retrieve credential",t)}}async getCredentialByAddress(e){try{return(await this.getAllCredentials()).find(r=>r.ethereumAddress.toLowerCase()===e.toLowerCase())||null}catch(t){throw new y("Failed to retrieve credential",t)}}async getAllCredentials(){try{let e=await this.getIndex();return(await Promise.all(e.map(async r=>await this.getCredentialById(r)))).filter(r=>r!==null)}catch(e){throw new y("Failed to retrieve credentials",e)}}async userExists(e){return await this.getCredentialByUsername(e)!==null}async updateLastUsed(e){try{let t=await this.getCredentialById(e);t&&(t.lastUsed=Date.now(),await this.saveCredential(t))}catch(t){throw new y("Failed to update timestamp",t)}}async deleteCredential(e){try{let t=await K(e),r=`${he}${t}`;this.storage.removeItem(r),await this.removeFromIndex(e)}catch(t){throw new y("Failed to delete credential",t)}}async clearAll(){try{let e=await this.getIndex();(await Promise.all(e.map(async r=>await K(r)))).forEach(r=>{let n=`${he}${r}`;this.storage.removeItem(n)}),this.storage.removeItem(ye)}catch(e){throw new y("Failed to clear credentials",e)}}async getIndex(){try{let e=this.storage.getItem(ye);return e?JSON.parse(e):[]}catch{return[]}}async addToIndex(e){let t=await this.getIndex();t.includes(e)||(t.push(e),this.storage.setItem(ye,JSON.stringify(t)))}async removeFromIndex(e){let r=(await this.getIndex()).filter(n=>n!==e);this.storage.setItem(ye,JSON.stringify(r))}}});var E,We=u(()=>{"use strict";E=class{constructor(){this.dbName="Web3PasskeyBackup";this.version=1;this.db=null}async init(){return typeof indexedDB>"u"?Promise.resolve():new Promise((e,t)=>{let r=indexedDB.open(this.dbName,this.version);r.onerror=()=>t(r.error),r.onsuccess=()=>{this.db=r.result,e()},r.onupgradeneeded=n=>{let o=n.target.result;if(!o.objectStoreNames.contains("backups")){let a=o.createObjectStore("backups",{keyPath:"id"});a.createIndex("ethereumAddress","ethereumAddress",{unique:!1}),a.createIndex("method","method",{unique:!1}),a.createIndex("createdAt","createdAt",{unique:!1})}}})}async storeBackupMetadata(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let a=this.db.transaction(["backups"],"readwrite").objectStore("backups").put(e);a.onsuccess=()=>t(),a.onerror=()=>r(a.error)}):Promise.resolve()}async getBackupsByAddress(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let i=this.db.transaction(["backups"],"readonly").objectStore("backups").index("ethereumAddress").getAll(e);i.onsuccess=()=>t(i.result),i.onerror=()=>r(i.error)}):Promise.resolve([])}async getBackupById(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let a=this.db.transaction(["backups"],"readonly").objectStore("backups").get(e);a.onsuccess=()=>t(a.result||null),a.onerror=()=>r(a.error)}):Promise.resolve(null)}async deleteBackup(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let a=this.db.transaction(["backups"],"readwrite").objectStore("backups").delete(e);a.onsuccess=()=>t(),a.onerror=()=>r(a.error)}):Promise.resolve()}async getBackupCountByMethod(e){return this.db||await this.init(),this.db?new Promise((t,r)=>{let i=this.db.transaction(["backups"],"readonly").objectStore("backups").index("method").count(e);i.onsuccess=()=>t(i.result),i.onerror=()=>r(i.error)}):Promise.resolve(0)}}});var Le={};S(Le,{decryptWithPassword:()=>wt,deriveAddressChecksum:()=>b,deriveKeyFromPassword:()=>ke,encryptWithPassword:()=>W,getDeviceFingerprint:()=>f,validatePasswordStrength:()=>Ae});async function ke(s,e,t=31e4){let n=new TextEncoder().encode(s),o=await crypto.subtle.importKey("raw",n,"PBKDF2",!1,["deriveBits","deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:e,iterations:t,hash:"SHA-256"},o,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function W(s,e,t){let n=await ke(e,t,31e4),a=new TextEncoder().encode(s),i=crypto.getRandomValues(new Uint8Array(12)),c=await crypto.subtle.encrypt({name:"AES-GCM",iv:i},n,a);return{encrypted:se(c),iv:se(i),salt:se(t),iterations:31e4}}async function wt(s,e,t,r,n=31e4){let o=Ne(t),a=await ke(e,o,n),i=Ne(r),c=Ne(s),l=await crypto.subtle.decrypt({name:"AES-GCM",iv:i},a,c);return new TextDecoder().decode(l)}async function f(){let e=[navigator.userAgent,navigator.language,new Date().getTimezoneOffset().toString(),screen.width+"x"+screen.height,screen.colorDepth.toString()].join("|"),r=new TextEncoder().encode(e),n=await crypto.subtle.digest("SHA-256",r);return se(n)}async function b(s){let t=new TextEncoder().encode(s.toLowerCase()),r=await crypto.subtle.digest("SHA-256",t);return se(r).substring(0,16)}function Ae(s){let e=[],t=0;return s.length<12?e.push("Password must be at least 12 characters"):t+=25,/[A-Z]/.test(s)?t+=15:e.push("Add at least one uppercase letter"),/[a-z]/.test(s)?t+=15:e.push("Add at least one lowercase letter"),/[0-9]/.test(s)?t+=15:e.push("Add at least one number"),/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(s)?t+=15:e.push("Add at least one special character"),s.length>=16&&(t+=10),s.length>=20&&(t+=5),["password","12345678","qwerty","abc123","password123","admin","letmein"].some(n=>s.toLowerCase().includes(n))&&(e.push("Password is too common"),t=Math.min(t,25)),{valid:t>=50&&e.length===0,score:Math.min(t,100),feedback:e}}function se(s){let e=s instanceof Uint8Array?s:new Uint8Array(s),t="";for(let r=0;r<e.byteLength;r++)t+=String.fromCharCode(e[r]);return btoa(t)}function Ne(s){let e=F(s),t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}var P=u(()=>{"use strict";J()});var N,qe=u(()=>{"use strict";P();N=class{async createZipBackup(e,t,r){let n=Ae(r.password);if(!n.valid)throw new Error(`Weak password: ${n.feedback.join(", ")}`);let o=crypto.getRandomValues(new Uint8Array(32)),a=await W(e,r.password,o),i=r.deviceBinding?await f():void 0,c={id:crypto.randomUUID(),ethereumAddress:t,method:"zip",createdAt:Date.now(),deviceFingerprint:i,addressChecksum:await b(t)},l={version:1,encrypted:a.encrypted,iv:a.iv,salt:a.salt,iterations:a.iterations,metadata:c,deviceFingerprint:i},p=new Map;return p.set("recovery-phrase.txt.enc",JSON.stringify(l,null,2)),p.set("metadata.json",JSON.stringify({address:t,createdAt:new Date(c.createdAt).toISOString(),backupId:c.id,addressChecksum:c.addressChecksum},null,2)),r.includeInstructions!==!1&&p.set("RECOVERY_INSTRUCTIONS.txt",this.getRecoveryInstructions()),{blob:await this.createSimpleZip(p),metadata:c}}async createSimpleZip(e){let t={};return e.forEach((r,n)=>{t[n]=r}),new Blob([JSON.stringify(t,null,2)],{type:"application/json"})}getRecoveryInstructions(){return`
2
2
  W3PK WALLET RECOVERY INSTRUCTIONS
3
3
  =================================
4
4
 
@@ -64,7 +64,7 @@ Visit: https://docs.w3pk.org/recovery
64
64
  Email: support@w3pk.org
65
65
 
66
66
  Generated: ${new Date().toISOString()}
67
- `}async restoreFromZipBackup(e,t){let r=JSON.parse(e);if(r.version!==1)throw new Error("Unsupported backup version");let{decryptWithPassword:n}=await Promise.resolve().then(()=>(E(),Fe)),o=await n(r.encrypted,t,r.salt,r.iv,r.iterations),{Wallet:i}=await import("ethers"),c=i.fromPhrase(o);if(await b(c.address)!==r.metadata.addressChecksum)throw new Error("Address checksum mismatch - corrupted backup or wrong password");return{mnemonic:o,metadata:r.metadata}}}});var O,Ke=u(()=>{"use strict";E();O=class{async createQRBackup(e,t,r={}){let n=r.errorCorrection||"H",o;if(r.password){let l=crypto.getRandomValues(new Uint8Array(32)),p=await M(e,r.password,l);o={version:1,type:"encrypted",data:p.encrypted,iv:p.iv,salt:p.salt,iterations:p.iterations,checksum:await b(t)}}else o={version:1,type:"plain",data:e,checksum:await b(t)};let i=JSON.stringify(o),c=await this.generateQRCode(i,n),a=this.getInstructions(t,!!r.password);return{qrCodeDataURL:c,rawData:i,instructions:a}}async generateQRCode(e,t){try{return await(await import("qrcode")).default.toDataURL(e,{errorCorrectionLevel:t,width:512,margin:2})}catch{return this.createFallbackQRDataURL(e)}}createFallbackQRDataURL(e){if(typeof document>"u")return`data:text/plain;base64,${Buffer.from(e).toString("base64")}`;let t=document.createElement("canvas");t.width=512,t.height=512;let r=t.getContext("2d");if(!r)throw new Error("Canvas not supported");r.fillStyle="white",r.fillRect(0,0,512,512),r.fillStyle="black",r.font="12px monospace",r.textAlign="center",r.textBaseline="middle";let n=this.wrapText(e,50),o=14,i=256-n.length*o/2;return n.forEach((c,a)=>{r.fillText(c,256,i+a*o)}),r.font="bold 16px sans-serif",r.fillText('Install "qrcode" package for QR codes',256,480),t.toDataURL("image/png")}wrapText(e,t){let r=[];for(let n=0;n<e.length;n+=t)r.push(e.substring(n,n+t));return r}getInstructions(e,t){return`
67
+ `}async restoreFromZipBackup(e,t){let r=JSON.parse(e);if(r.version!==1)throw new Error("Unsupported backup version");let{decryptWithPassword:n}=await Promise.resolve().then(()=>(P(),Le)),o=await n(r.encrypted,t,r.salt,r.iv,r.iterations),{Wallet:a}=await import("ethers"),i=a.fromPhrase(o);if(await b(i.address)!==r.metadata.addressChecksum)throw new Error("Address checksum mismatch - corrupted backup or wrong password");return{mnemonic:o,metadata:r.metadata}}}});var L,$e=u(()=>{"use strict";P();L=class{async createQRBackup(e,t,r={}){let n=r.errorCorrection||"H",o;if(r.password){let l=crypto.getRandomValues(new Uint8Array(32)),p=await W(e,r.password,l);o={version:1,type:"encrypted",data:p.encrypted,iv:p.iv,salt:p.salt,iterations:p.iterations,checksum:await b(t)}}else o={version:1,type:"plain",data:e,checksum:await b(t)};let a=JSON.stringify(o),i=await this.generateQRCode(a,n),c=this.getInstructions(t,!!r.password);return{qrCodeDataURL:i,rawData:a,instructions:c}}async generateQRCode(e,t){try{return await(await import("qrcode")).default.toDataURL(e,{errorCorrectionLevel:t,width:512,margin:2})}catch{return this.createFallbackQRDataURL(e)}}createFallbackQRDataURL(e){if(typeof document>"u")return`data:text/plain;base64,${Buffer.from(e).toString("base64")}`;let t=document.createElement("canvas");t.width=512,t.height=512;let r=t.getContext("2d");if(!r)throw new Error("Canvas not supported");r.fillStyle="white",r.fillRect(0,0,512,512),r.fillStyle="black",r.font="12px monospace",r.textAlign="center",r.textBaseline="middle";let n=this.wrapText(e,50),o=14,a=256-n.length*o/2;return n.forEach((i,c)=>{r.fillText(i,256,a+c*o)}),r.font="bold 16px sans-serif",r.fillText('Install "qrcode" package for QR codes',256,480),t.toDataURL("image/png")}wrapText(e,t){let r=[];for(let n=0;n<e.length;n+=t)r.push(e.substring(n,n+t));return r}getInstructions(e,t){return`
68
68
  W3PK QR CODE BACKUP
69
69
  ==================
70
70
 
@@ -140,13 +140,13 @@ If QR code is lost/damaged, you can still recover using:
140
140
 
141
141
  Generated by w3pk Recovery System
142
142
  https://docs.w3pk.org/recovery
143
- `}async restoreFromQR(e,t){let r=JSON.parse(e);if(r.version!==1)throw new Error("Unsupported QR backup version");let n;if(r.type==="encrypted"){if(!t)throw new Error("Password required for encrypted QR backup");let{decryptWithPassword:a}=await Promise.resolve().then(()=>(E(),Fe));n=await a(r.data,t,r.salt,r.iv,r.iterations)}else if(r.type==="plain")n=r.data;else throw new Error("Unknown QR backup type");let{Wallet:o}=await import("ethers"),i=o.fromPhrase(n);if(await b(i.address)!==r.checksum)throw new Error("Address checksum mismatch - corrupted QR or wrong password");return{mnemonic:n,ethereumAddress:i.address}}}});var U,ut=u(()=>{"use strict";Te();Me();Ke();U=class{constructor(){this.storage=new A,this.zipCreator=new K,this.qrCreator=new O}async getBackupStatus(e){let t=await this.storage.getBackupsByAddress(e),r=await this.detectPasskeySync(),n=t.map(i=>({id:i.id,method:i.method,location:"local",createdAt:i.createdAt,deviceFingerprint:i.deviceFingerprint}));return{passkeySync:r,recoveryPhrase:{verified:!1,verificationCount:0,encryptedBackups:n},securityScore:this.calculateSecurityScore(r,n)}}async detectPasskeySync(){if(typeof navigator>"u")return{enabled:!1,deviceCount:0,lastSyncTime:void 0,platform:"unknown"};let e=navigator.userAgent.toLowerCase(),t="unknown";e.includes("mac")||e.includes("iphone")||e.includes("ipad")?t="apple":e.includes("android")?t="google":e.includes("windows")&&(t="microsoft");let r=await this.checkResidentKeySupport();return{enabled:r,deviceCount:1,lastSyncTime:r?Date.now():void 0,platform:t}}async checkResidentKeySupport(){if(typeof window>"u"||!window.PublicKeyCredential)return!1;try{return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return!1}}calculateSecurityScore(e,t){let r={passkeyActive:e.enabled?20:0,passkeyMultiDevice:e.deviceCount>1?10:0,phraseVerified:0,encryptedBackup:t.length>0?20:0,socialRecovery:0},n=Object.values(r).reduce((c,a)=>c+a,0),o,i;return n<=20?(o="vulnerable",i='Create encrypted backup to reach "protected" (40+ pts)'):n<=50?(o="protected",i='Set up social recovery to reach "secured" (70+ pts)'):n<=80?(o="secured",i='Enable all methods to reach "fort-knox" (100 pts)'):(o="fort-knox",i="Maximum security achieved! \u{1F3C6}"),{total:n,breakdown:r,level:o,nextMilestone:i}}async createZipBackup(e,t,r){let{blob:n,metadata:o}=await this.zipCreator.createZipBackup(e,t,r);return await this.storage.storeBackupMetadata(o),n}async createQRBackup(e,t,r){let{qrCodeDataURL:n,rawData:o,instructions:i}=await this.qrCreator.createQRBackup(e,t,r),c={id:crypto.randomUUID(),ethereumAddress:t,method:"qr",createdAt:Date.now(),addressChecksum:JSON.parse(o).checksum};return await this.storage.storeBackupMetadata(c),{qrCodeDataURL:n,instructions:i}}async restoreFromZipBackup(e,t){let{mnemonic:r,metadata:n}=await this.zipCreator.restoreFromZipBackup(e,t);return{mnemonic:r,ethereumAddress:n.ethereumAddress}}async restoreFromQR(e,t){return await this.qrCreator.restoreFromQR(e,t)}async simulateRecoveryScenario(e,t){let r=[];switch(e.type){case"lost-device":t.passkeySync.enabled&&t.passkeySync.deviceCount>1&&r.push({method:"Passkey Sync (iCloud/Google)",success:!0,time:"5 minutes",requirements:["Sign in to cloud account","Authenticate on new device"]}),t.recoveryPhrase.encryptedBackups.length>0&&r.push({method:"Encrypted ZIP Backup",success:!0,time:"2 minutes",requirements:["Backup file","Password"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break;case"lost-phrase":t.passkeySync.enabled&&r.push({method:"Passkey (current device)",success:!0,time:"instant",requirements:["Current device","Biometric/PIN"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break;case"lost-both":t.passkeySync.enabled&&t.passkeySync.deviceCount>1&&r.push({method:"Passkey Sync",success:!0,time:"5 minutes",requirements:["Cloud account access","New device"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break;case"switch-platform":t.recoveryPhrase.encryptedBackups.length>0&&r.push({method:"Encrypted Backup",success:!0,time:"2 minutes",requirements:["Backup file","Password"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break}let n=r.length>0&&r.some(i=>i.success),o="";return n?(o=`\u2705 You're safe! ${r.length} way${r.length>1?"s":""} to recover.
143
+ `}async restoreFromQR(e,t){let r=JSON.parse(e);if(r.version!==1)throw new Error("Unsupported QR backup version");let n;if(r.type==="encrypted"){if(!t)throw new Error("Password required for encrypted QR backup");let{decryptWithPassword:c}=await Promise.resolve().then(()=>(P(),Le));n=await c(r.data,t,r.salt,r.iv,r.iterations)}else if(r.type==="plain")n=r.data;else throw new Error("Unknown QR backup type");let{Wallet:o}=await import("ethers"),a=o.fromPhrase(n);if(await b(a.address)!==r.checksum)throw new Error("Address checksum mismatch - corrupted QR or wrong password");return{mnemonic:n,ethereumAddress:a.address}}}});var q,vt=u(()=>{"use strict";We();qe();$e();q=class{constructor(){this.storage=new E,this.zipCreator=new N,this.qrCreator=new L}async getBackupStatus(e){let t=await this.storage.getBackupsByAddress(e),r=await this.detectPasskeySync(),n=t.map(a=>({id:a.id,method:a.method,location:"local",createdAt:a.createdAt,deviceFingerprint:a.deviceFingerprint}));return{passkeySync:r,recoveryPhrase:{verified:!1,verificationCount:0,encryptedBackups:n},securityScore:this.calculateSecurityScore(r,n)}}async detectPasskeySync(){if(typeof navigator>"u")return{enabled:!1,deviceCount:0,lastSyncTime:void 0,platform:"unknown"};let e=navigator.userAgent.toLowerCase(),t="unknown";e.includes("mac")||e.includes("iphone")||e.includes("ipad")?t="apple":e.includes("android")?t="google":e.includes("windows")&&(t="microsoft");let r=await this.checkResidentKeySupport();return{enabled:r,deviceCount:1,lastSyncTime:r?Date.now():void 0,platform:t}}async checkResidentKeySupport(){if(typeof window>"u"||!window.PublicKeyCredential)return!1;try{return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return!1}}calculateSecurityScore(e,t){let r={passkeyActive:e.enabled?20:0,passkeyMultiDevice:e.deviceCount>1?10:0,phraseVerified:0,encryptedBackup:t.length>0?20:0,socialRecovery:0},n=Object.values(r).reduce((i,c)=>i+c,0),o,a;return n<=20?(o="vulnerable",a='Create encrypted backup to reach "protected" (40+ pts)'):n<=50?(o="protected",a='Set up social recovery to reach "secured" (70+ pts)'):n<=80?(o="secured",a='Enable all methods to reach "fort-knox" (100 pts)'):(o="fort-knox",a="Maximum security achieved! \u{1F3C6}"),{total:n,breakdown:r,level:o,nextMilestone:a}}async createZipBackup(e,t,r){let{blob:n,metadata:o}=await this.zipCreator.createZipBackup(e,t,r);return await this.storage.storeBackupMetadata(o),n}async createQRBackup(e,t,r){let{qrCodeDataURL:n,rawData:o,instructions:a}=await this.qrCreator.createQRBackup(e,t,r),i={id:crypto.randomUUID(),ethereumAddress:t,method:"qr",createdAt:Date.now(),addressChecksum:JSON.parse(o).checksum};return await this.storage.storeBackupMetadata(i),{qrCodeDataURL:n,instructions:a}}async restoreFromZipBackup(e,t){let{mnemonic:r,metadata:n}=await this.zipCreator.restoreFromZipBackup(e,t);return{mnemonic:r,ethereumAddress:n.ethereumAddress}}async restoreFromQR(e,t){return await this.qrCreator.restoreFromQR(e,t)}async simulateRecoveryScenario(e,t){let r=[];switch(e.type){case"lost-device":t.passkeySync.enabled&&t.passkeySync.deviceCount>1&&r.push({method:"Passkey Sync (iCloud/Google)",success:!0,time:"5 minutes",requirements:["Sign in to cloud account","Authenticate on new device"]}),t.recoveryPhrase.encryptedBackups.length>0&&r.push({method:"Encrypted ZIP Backup",success:!0,time:"2 minutes",requirements:["Backup file","Password"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break;case"lost-phrase":t.passkeySync.enabled&&r.push({method:"Passkey (current device)",success:!0,time:"instant",requirements:["Current device","Biometric/PIN"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break;case"lost-both":t.passkeySync.enabled&&t.passkeySync.deviceCount>1&&r.push({method:"Passkey Sync",success:!0,time:"5 minutes",requirements:["Cloud account access","New device"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break;case"switch-platform":t.recoveryPhrase.encryptedBackups.length>0&&r.push({method:"Encrypted Backup",success:!0,time:"2 minutes",requirements:["Backup file","Password"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break}let n=r.length>0&&r.some(a=>a.success),o="";return n?(o=`\u2705 You're safe! ${r.length} way${r.length>1?"s":""} to recover.
144
144
 
145
145
  `,o+=`Available recovery methods:
146
- `,r.forEach(i=>{o+=`- ${i.method} (~${i.time})
146
+ `,r.forEach(a=>{o+=`- ${a.method} (~${a.time})
147
147
  `})):(o=`\u274C Wallet cannot be recovered in this scenario.
148
148
 
149
- `,o+="Recommendation: Set up at least 2 backup methods to prevent total loss."),{scenario:e,success:n,availableMethods:r,timeEstimate:n?r[0].time:"N/A",educationalNote:o}}}});var pt=u(()=>{"use strict"});var W={};S(W,{BackupManager:()=>U,BackupStorage:()=>A,QRBackupCreator:()=>O,ZipBackupCreator:()=>K,decryptWithPassword:()=>lt,deriveAddressChecksum:()=>b,deriveKeyFromPassword:()=>ge,encryptWithPassword:()=>M,getDeviceFingerprint:()=>f,validatePasswordStrength:()=>fe});var I=u(()=>{"use strict";ut();Te();Me();Ke();pt();E()});function zt(){let s=new Uint8Array(1);return crypto.getRandomValues(s),s[0]}function Oe(s,e,t){if(e>t)throw new Error("Threshold cannot be greater than total shares");if(e<2)throw new Error("Threshold must be at least 2");if(t>255)throw new Error("Cannot create more than 255 shares");let r=[];for(let n=0;n<t;n++)r[n]=new Uint8Array(s.length+1),r[n][0]=n+1;for(let n=0;n<s.length;n++){let i=[s[n]];for(let c=1;c<e;c++)i.push(zt());for(let c=0;c<t;c++){let a=c+1,l=we.evaluatePolynomial(i,a);r[c][n+1]=l}}return r}function Ue(s,e){if(s.length<e)throw new Error(`Need at least ${e} shares to recover secret, got ${s.length}`);let t=s.slice(0,e),r=t[0].length;for(let i of t)if(i.length!==r)throw new Error("All shares must have the same length");let n=r-1,o=new Uint8Array(n);for(let i=0;i<n;i++){let c=[];for(let a of t)c.push({x:a[0],y:a[i+1]});o[i]=we.interpolate(c)}return o}function We(s){return new TextEncoder().encode(s)}function Ne(s){return new TextDecoder().decode(s)}function Le(s){return Array.from(s).map(e=>e.toString(16).padStart(2,"0")).join("")}function qe(s){let e=new Uint8Array(s.length/2);for(let t=0;t<s.length;t+=2)e[t/2]=parseInt(s.substring(t,t+2),16);return e}var P,we,Ge=u(()=>{"use strict";P=class P{static multiply(e,t){return e===0||t===0?0:this.EXP_TABLE[(this.LOG_TABLE[e]+this.LOG_TABLE[t])%255]}static divide(e,t){if(t===0)throw new Error("Division by zero in GF(256)");return e===0?0:this.EXP_TABLE[(this.LOG_TABLE[e]-this.LOG_TABLE[t]+255)%255]}static add(e,t){return e^t}static evaluatePolynomial(e,t){let r=0;for(let n=e.length-1;n>=0;n--)r=this.add(this.multiply(r,t),e[n]);return r}static interpolate(e){let t=0;for(let r=0;r<e.length;r++){let n=e[r].y,o=1;for(let i=0;i<e.length;i++)r!==i&&(n=this.multiply(n,e[i].x),o=this.multiply(o,this.add(e[r].x,e[i].x)));t=this.add(t,this.divide(n,o))}return t}};P.LOG_TABLE=[],P.EXP_TABLE=[],(()=>{let e=(r,n)=>{let o=0;for(let i=0;i<8;i++){n&1&&(o^=r);let c=r&128;r<<=1,c&&(r^=283),n>>=1}return o&255},t=1;for(let r=0;r<255;r++)P.EXP_TABLE[r]=t,P.LOG_TABLE[t]=r,t=e(t,3);P.EXP_TABLE[255]=P.EXP_TABLE[0]})();we=P});var ht,N,yt=u(()=>{"use strict";Ge();ht=new Map,N=class{constructor(){this.storageKey="w3pk_social_recovery"}getItem(e){return typeof localStorage<"u"?localStorage.getItem(e):ht.get(e)||null}setItem(e,t){typeof localStorage<"u"?localStorage.setItem(e,t):ht.set(e,t)}async setupSocialRecovery(e,t,r,n){if(n>r.length)throw new Error("Threshold cannot be greater than number of guardians");if(n<2)throw new Error("Threshold must be at least 2");if(r.length>255)throw new Error("Cannot have more than 255 guardians");let o=We(e),i=Oe(o,n,r.length),c=r.map((l,p)=>({id:crypto.randomUUID(),name:l.name,email:l.email,phone:l.phone,shareEncrypted:Le(i[p]),status:"pending",addedAt:Date.now()})),a={threshold:n,totalGuardians:r.length,guardians:c,createdAt:Date.now(),ethereumAddress:t};return this.setItem(this.storageKey,JSON.stringify(a)),c}getSocialRecoveryConfig(){let e=this.getItem(this.storageKey);if(!e)return null;try{return JSON.parse(e)}catch{return null}}async generateGuardianInvite(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");let r=t.guardians.findIndex(a=>a.id===e.id);if(r===-1)throw new Error("Guardian not found");let n={version:1,guardianId:e.id,guardianName:e.name,guardianIndex:r+1,totalGuardians:t.totalGuardians,threshold:t.threshold,share:e.shareEncrypted,ethereumAddress:t.ethereumAddress,createdAt:t.createdAt},o=JSON.stringify(n),i=await this.generateQRCode(o),c=this.getGuardianExplainer(e.name,r+1,t.totalGuardians,t.threshold);return{guardianId:e.id,qrCode:i,shareCode:o,explainer:c}}async generateQRCode(e){try{return await(await import("qrcode")).toDataURL(e,{errorCorrectionLevel:"H",width:512,margin:2})}catch{return this.createPlaceholderQR(e)}}createPlaceholderQR(e){if(typeof document>"u")return`data:text/plain;base64,${Buffer.from(e).toString("base64")}`;let t=document.createElement("canvas");t.width=512,t.height=512;let r=t.getContext("2d");return r?(r.fillStyle="white",r.fillRect(0,0,512,512),r.fillStyle="black",r.font="bold 20px sans-serif",r.textAlign="center",r.textBaseline="middle",r.fillText("Guardian Recovery Share",256,100),r.font="14px monospace",r.fillText('Install "qrcode" for QR codes',256,480),r.font="10px monospace",this.wrapText(e.substring(0,200)+"...",60).forEach((o,i)=>{r.fillText(o,256,150+i*12)}),t.toDataURL("image/png")):""}wrapText(e,t){let r=[];for(let n=0;n<e.length;n+=t)r.push(e.substring(n,n+t));return r}getGuardianExplainer(e,t,r,n){return`
149
+ `,o+="Recommendation: Set up at least 2 backup methods to prevent total loss."),{scenario:e,success:n,availableMethods:r,timeEstimate:n?r[0].time:"N/A",educationalNote:o}}}});var bt=u(()=>{"use strict"});var $={};S($,{BackupManager:()=>q,BackupStorage:()=>E,QRBackupCreator:()=>L,ZipBackupCreator:()=>N,decryptWithPassword:()=>wt,deriveAddressChecksum:()=>b,deriveKeyFromPassword:()=>ke,encryptWithPassword:()=>W,getDeviceFingerprint:()=>f,validatePasswordStrength:()=>Ae});var B=u(()=>{"use strict";vt();We();qe();$e();bt();P()});function rr(){let s=new Uint8Array(1);return crypto.getRandomValues(s),s[0]}function Ge(s,e,t){if(e>t)throw new Error("Threshold cannot be greater than total shares");if(e<2)throw new Error("Threshold must be at least 2");if(t>255)throw new Error("Cannot create more than 255 shares");let r=[];for(let n=0;n<t;n++)r[n]=new Uint8Array(s.length+1),r[n][0]=n+1;for(let n=0;n<s.length;n++){let a=[s[n]];for(let i=1;i<e;i++)a.push(rr());for(let i=0;i<t;i++){let c=i+1,l=Ee.evaluatePolynomial(a,c);r[i][n+1]=l}}return r}function Ye(s,e){if(s.length<e)throw new Error(`Need at least ${e} shares to recover secret, got ${s.length}`);let t=s.slice(0,e),r=t[0].length;for(let a of t)if(a.length!==r)throw new Error("All shares must have the same length");let n=r-1,o=new Uint8Array(n);for(let a=0;a<n;a++){let i=[];for(let c of t)i.push({x:c[0],y:c[a+1]});o[a]=Ee.interpolate(i)}return o}function He(s){return new TextEncoder().encode(s)}function _e(s){return new TextDecoder().decode(s)}function Ve(s){return Array.from(s).map(e=>e.toString(16).padStart(2,"0")).join("")}function Qe(s){let e=new Uint8Array(s.length/2);for(let t=0;t<s.length;t+=2)e[t/2]=parseInt(s.substring(t,t+2),16);return e}var C,Ee,je=u(()=>{"use strict";C=class C{static multiply(e,t){return e===0||t===0?0:this.EXP_TABLE[(this.LOG_TABLE[e]+this.LOG_TABLE[t])%255]}static divide(e,t){if(t===0)throw new Error("Division by zero in GF(256)");return e===0?0:this.EXP_TABLE[(this.LOG_TABLE[e]-this.LOG_TABLE[t]+255)%255]}static add(e,t){return e^t}static evaluatePolynomial(e,t){let r=0;for(let n=e.length-1;n>=0;n--)r=this.add(this.multiply(r,t),e[n]);return r}static interpolate(e){let t=0;for(let r=0;r<e.length;r++){let n=e[r].y,o=1;for(let a=0;a<e.length;a++)r!==a&&(n=this.multiply(n,e[a].x),o=this.multiply(o,this.add(e[r].x,e[a].x)));t=this.add(t,this.divide(n,o))}return t}};C.LOG_TABLE=[],C.EXP_TABLE=[],(()=>{let e=(r,n)=>{let o=0;for(let a=0;a<8;a++){n&1&&(o^=r);let i=r&128;r<<=1,i&&(r^=283),n>>=1}return o&255},t=1;for(let r=0;r<255;r++)C.EXP_TABLE[r]=t,C.LOG_TABLE[t]=r,t=e(t,3);C.EXP_TABLE[255]=C.EXP_TABLE[0]})();Ee=C});var St,G,kt=u(()=>{"use strict";je();St=new Map,G=class{constructor(){this.storageKey="w3pk_social_recovery"}getItem(e){return typeof localStorage<"u"?localStorage.getItem(e):St.get(e)||null}setItem(e,t){typeof localStorage<"u"?localStorage.setItem(e,t):St.set(e,t)}async setupSocialRecovery(e,t,r,n){if(n>r.length)throw new Error("Threshold cannot be greater than number of guardians");if(n<2)throw new Error("Threshold must be at least 2");if(r.length>255)throw new Error("Cannot have more than 255 guardians");let o=He(e),a=Ge(o,n,r.length),i=r.map((l,p)=>({id:crypto.randomUUID(),name:l.name,email:l.email,phone:l.phone,shareEncrypted:Ve(a[p]),status:"pending",addedAt:Date.now()})),c={threshold:n,totalGuardians:r.length,guardians:i,createdAt:Date.now(),ethereumAddress:t};return this.setItem(this.storageKey,JSON.stringify(c)),i}getSocialRecoveryConfig(){let e=this.getItem(this.storageKey);if(!e)return null;try{return JSON.parse(e)}catch{return null}}async generateGuardianInvite(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");let r=t.guardians.findIndex(c=>c.id===e.id);if(r===-1)throw new Error("Guardian not found");let n={version:1,guardianId:e.id,guardianName:e.name,guardianIndex:r+1,totalGuardians:t.totalGuardians,threshold:t.threshold,share:e.shareEncrypted,ethereumAddress:t.ethereumAddress,createdAt:t.createdAt},o=JSON.stringify(n),a=await this.generateQRCode(o),i=this.getGuardianExplainer(e.name,r+1,t.totalGuardians,t.threshold);return{guardianId:e.id,qrCode:a,shareCode:o,explainer:i}}async generateQRCode(e){try{return await(await import("qrcode")).toDataURL(e,{errorCorrectionLevel:"H",width:512,margin:2})}catch{return this.createPlaceholderQR(e)}}createPlaceholderQR(e){if(typeof document>"u")return`data:text/plain;base64,${Buffer.from(e).toString("base64")}`;let t=document.createElement("canvas");t.width=512,t.height=512;let r=t.getContext("2d");return r?(r.fillStyle="white",r.fillRect(0,0,512,512),r.fillStyle="black",r.font="bold 20px sans-serif",r.textAlign="center",r.textBaseline="middle",r.fillText("Guardian Recovery Share",256,100),r.font="14px monospace",r.fillText('Install "qrcode" for QR codes',256,480),r.font="10px monospace",this.wrapText(e.substring(0,200)+"...",60).forEach((o,a)=>{r.fillText(o,256,150+a*12)}),t.toDataURL("image/png")):""}wrapText(e,t){let r=[];for(let n=0;n<e.length;n+=t)r.push(e.substring(n,n+t));return r}getGuardianExplainer(e,t,r,n){return`
150
150
  \u{1F6E1}\uFE0F GUARDIAN RECOVERY SHARE
151
151
 
152
152
  Dear ${e},
@@ -234,7 +234,7 @@ Thank you for being a trusted guardian!
234
234
 
235
235
  NEED HELP?
236
236
  Visit: https://docs.w3pk.org/social-recovery
237
- `}async recoverFromGuardians(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");if(e.length<t.threshold)throw new Error(`Need at least ${t.threshold} shares, got ${e.length}`);let n=e.map(l=>{let p=JSON.parse(l);return{guardianId:p.guardianId,share:p.share,index:p.guardianIndex}}).map(l=>qe(l.share)),o=Ue(n,t.threshold),i=Ne(o),{Wallet:c}=await import("ethers"),a=c.fromPhrase(i);if(a.address.toLowerCase()!==t.ethereumAddress.toLowerCase())throw new Error("Recovered address does not match - invalid shares");return{mnemonic:i,ethereumAddress:a.address}}getRecoveryProgress(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");let r=new Set(e.map(n=>{try{return JSON.parse(n).guardianId}catch{return null}}).filter(Boolean));return{collected:r.size,required:t.threshold,guardians:t.guardians.map(n=>({id:n.id,name:n.name,hasProvided:r.has(n.id)})),canRecover:r.size>=t.threshold}}markGuardianVerified(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");let r=t.guardians.find(n=>n.id===e);if(!r)throw new Error("Guardian not found");r.status="active",r.lastVerified=Date.now(),this.setItem(this.storageKey,JSON.stringify(t))}revokeGuardian(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");let r=t.guardians.find(n=>n.id===e);if(!r)throw new Error("Guardian not found");r.status="revoked",this.setItem(this.storageKey,JSON.stringify(t))}async addGuardian(e,t){let r=this.getSocialRecoveryConfig();if(!r)throw new Error("Social recovery not configured");let n=[...r.guardians.filter(i=>i.status!=="revoked").map(i=>({name:i.name,email:i.email,phone:i.phone})),t],o=await this.setupSocialRecovery(e,r.ethereumAddress,n,r.threshold);return o[o.length-1]}}});var mt=u(()=>{"use strict"});var ve={};S(ve,{SocialRecoveryManager:()=>N,bytesToHex:()=>Le,bytesToString:()=>Ne,combineShares:()=>Ue,hexToBytes:()=>qe,splitSecret:()=>Oe,stringToBytes:()=>We});var J=u(()=>{"use strict";yt();Ge();mt()});var L,gt=u(()=>{"use strict";E();L=class{async createSyncPackage(e,t,r){let n=await f(),{deriveEncryptionKeyFromWebAuthn:o,encryptData:i}=await Promise.resolve().then(()=>(ue(),xe)),c=await o(t,r),a=await i(e,c),l=this.detectSyncMethod();return{id:crypto.randomUUID(),encryptedData:a,deviceFingerprints:[n],syncMethod:l,version:1,updatedAt:Date.now()}}detectSyncMethod(){let e=navigator.userAgent.toLowerCase();return e.includes("mac")||e.includes("iphone")||e.includes("ipad")?"icloud":e.includes("android")||e.includes("chrome")?"google":e.includes("windows")?"microsoft":"custom"}async restoreFromSync(e,t,r){let{deriveEncryptionKeyFromWebAuthn:n,decryptData:o}=await Promise.resolve().then(()=>(ue(),xe)),i=await n(t,r),c=await o(e.encryptedData,i),a=await f();return e.deviceFingerprints.includes(a)||(e.deviceFingerprints.push(a),e.updatedAt=Date.now()),c}async getSetupFlow(){return{success:!1,steps:[{title:"1. Authenticate on New Device",action:"Use Touch ID/Face ID",educational:"Your passkey is automatically synced via iCloud/Google",status:"waiting"},{title:"2. Decrypt Wallet Data",action:"System validates device",educational:"Only your trusted devices can decrypt the wallet",status:"waiting"},{title:"3. Verify Recovery",action:"Check partial address",educational:"Confirm address matches your wallet",status:"waiting"},{title:"4. Ready!",action:"Wallet synced",educational:"All devices now have access",status:"waiting"}]}}getSyncExplainer(){return`
237
+ `}async recoverFromGuardians(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");if(e.length<t.threshold)throw new Error(`Need at least ${t.threshold} shares, got ${e.length}`);let n=e.map(l=>{let p=JSON.parse(l);return{guardianId:p.guardianId,share:p.share,index:p.guardianIndex}}).map(l=>Qe(l.share)),o=Ye(n,t.threshold),a=_e(o),{Wallet:i}=await import("ethers"),c=i.fromPhrase(a);if(c.address.toLowerCase()!==t.ethereumAddress.toLowerCase())throw new Error("Recovered address does not match - invalid shares");return{mnemonic:a,ethereumAddress:c.address}}getRecoveryProgress(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");let r=new Set(e.map(n=>{try{return JSON.parse(n).guardianId}catch{return null}}).filter(Boolean));return{collected:r.size,required:t.threshold,guardians:t.guardians.map(n=>({id:n.id,name:n.name,hasProvided:r.has(n.id)})),canRecover:r.size>=t.threshold}}markGuardianVerified(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");let r=t.guardians.find(n=>n.id===e);if(!r)throw new Error("Guardian not found");r.status="active",r.lastVerified=Date.now(),this.setItem(this.storageKey,JSON.stringify(t))}revokeGuardian(e){let t=this.getSocialRecoveryConfig();if(!t)throw new Error("Social recovery not configured");let r=t.guardians.find(n=>n.id===e);if(!r)throw new Error("Guardian not found");r.status="revoked",this.setItem(this.storageKey,JSON.stringify(t))}async addGuardian(e,t){let r=this.getSocialRecoveryConfig();if(!r)throw new Error("Social recovery not configured");let n=[...r.guardians.filter(a=>a.status!=="revoked").map(a=>({name:a.name,email:a.email,phone:a.phone})),t],o=await this.setupSocialRecovery(e,r.ethereumAddress,n,r.threshold);return o[o.length-1]}}});var At=u(()=>{"use strict"});var Pe={};S(Pe,{SocialRecoveryManager:()=>G,bytesToHex:()=>Ve,bytesToString:()=>_e,combineShares:()=>Ye,hexToBytes:()=>Qe,splitSecret:()=>Ge,stringToBytes:()=>He});var oe=u(()=>{"use strict";kt();je();At()});var Y,Et=u(()=>{"use strict";P();Y=class{async createSyncPackage(e,t,r){let n=await f(),{deriveEncryptionKeyFromWebAuthn:o,encryptData:a}=await Promise.resolve().then(()=>(X(),Ke)),i=await o(t,r),c=await a(e,i),l=this.detectSyncMethod();return{id:crypto.randomUUID(),encryptedData:c,deviceFingerprints:[n],syncMethod:l,version:1,updatedAt:Date.now()}}detectSyncMethod(){let e=navigator.userAgent.toLowerCase();return e.includes("mac")||e.includes("iphone")||e.includes("ipad")?"icloud":e.includes("android")||e.includes("chrome")?"google":e.includes("windows")?"microsoft":"custom"}async restoreFromSync(e,t,r){let{deriveEncryptionKeyFromWebAuthn:n,decryptData:o}=await Promise.resolve().then(()=>(X(),Ke)),a=await n(t,r),i=await o(e.encryptedData,a),c=await f();return e.deviceFingerprints.includes(c)||(e.deviceFingerprints.push(c),e.updatedAt=Date.now()),i}async getSetupFlow(){return{success:!1,steps:[{title:"1. Authenticate on New Device",action:"Use Touch ID/Face ID",educational:"Your passkey is automatically synced via iCloud/Google",status:"waiting"},{title:"2. Decrypt Wallet Data",action:"System validates device",educational:"Only your trusted devices can decrypt the wallet",status:"waiting"},{title:"3. Verify Recovery",action:"Check partial address",educational:"Confirm address matches your wallet",status:"waiting"},{title:"4. Ready!",action:"Wallet synced",educational:"All devices now have access",status:"waiting"}]}}getSyncExplainer(){return`
238
238
  HOW CROSS-DEVICE SYNC WORKS
239
239
  ===========================
240
240
 
@@ -315,14 +315,14 @@ If passkey doesn't sync:
315
315
  Think of it like:
316
316
  \u{1F511} Passkey = Your car key (syncs via keychain)
317
317
  \u{1F697} Wallet = Your car (locked, needs key to start)
318
- `}}});var q,ft=u(()=>{"use strict";E();q=class{constructor(){this.storageKey="w3pk_devices"}async registerDevice(){let e={id:await f(),name:this.getDeviceName(),platform:this.detectPlatform(),lastActive:Date.now(),trusted:!0,canRevoke:!1},t=await this.getDevices(),r=t.find(n=>n.id===e.id);return r?(r.lastActive=Date.now(),localStorage.setItem(this.storageKey,JSON.stringify(t))):(t.push(e),localStorage.setItem(this.storageKey,JSON.stringify(t))),e}async getDevices(){let e=localStorage.getItem(this.storageKey);if(!e)return[];try{return JSON.parse(e)}catch{return[]}}async getSyncStatus(){let e=await this.getDevices(),t=await f();e.forEach(o=>{o.canRevoke=o.id!==t}),e.sort((o,i)=>i.lastActive-o.lastActive);let r=this.detectPlatform(),n=e.length>1?Math.max(...e.map(o=>o.lastActive)):void 0;return{enabled:e.length>1,devices:e,lastSyncTime:n,platform:this.getPlatformName(r)}}async revokeDevice(e){let t=await this.getDevices(),r=await f();if(e===r)throw new Error("Cannot revoke current device");let n=t.filter(o=>o.id!==e);localStorage.setItem(this.storageKey,JSON.stringify(n))}async updateLastActive(){let e=await this.getDevices(),t=await f(),r=e.find(n=>n.id===t);r&&(r.lastActive=Date.now(),localStorage.setItem(this.storageKey,JSON.stringify(e)))}getDeviceName(){let e=this.detectPlatform(),t=navigator.userAgent;if(e==="ios")return t.includes("iPhone")?"iPhone":t.includes("iPad")?"iPad":t.includes("iPod")?"iPod":"iOS Device";if(e==="android"){let r=t.match(/Android.*;\s([^)]+)\)/);return r?r[1]:"Android Device"}return e==="macos"?"Mac":e==="windows"?"Windows PC":e==="linux"?"Linux PC":"Unknown Device"}detectPlatform(){let e=navigator.userAgent.toLowerCase();return e.includes("iphone")||e.includes("ipad")||e.includes("ipod")?"ios":e.includes("android")?"android":e.includes("mac")?"macos":e.includes("windows")?"windows":e.includes("linux")?"linux":"unknown"}getPlatformName(e){switch(e){case"ios":return"iOS (iCloud Keychain)";case"android":return"Android (Google)";case"macos":return"macOS (iCloud Keychain)";case"windows":return"Windows (Microsoft)";case"linux":return"Linux";default:return"Unknown"}}async getDeviceListFormatted(){let e=await this.getSyncStatus();if(e.devices.length===0)return"No devices registered";let t=`Your Devices (${e.devices.length}):
318
+ `}}});var H,Pt=u(()=>{"use strict";P();H=class{constructor(){this.storageKey="w3pk_devices"}async registerDevice(){let e={id:await f(),name:this.getDeviceName(),platform:this.detectPlatform(),lastActive:Date.now(),trusted:!0,canRevoke:!1},t=await this.getDevices(),r=t.find(n=>n.id===e.id);return r?(r.lastActive=Date.now(),localStorage.setItem(this.storageKey,JSON.stringify(t))):(t.push(e),localStorage.setItem(this.storageKey,JSON.stringify(t))),e}async getDevices(){let e=localStorage.getItem(this.storageKey);if(!e)return[];try{return JSON.parse(e)}catch{return[]}}async getSyncStatus(){let e=await this.getDevices(),t=await f();e.forEach(o=>{o.canRevoke=o.id!==t}),e.sort((o,a)=>a.lastActive-o.lastActive);let r=this.detectPlatform(),n=e.length>1?Math.max(...e.map(o=>o.lastActive)):void 0;return{enabled:e.length>1,devices:e,lastSyncTime:n,platform:this.getPlatformName(r)}}async revokeDevice(e){let t=await this.getDevices(),r=await f();if(e===r)throw new Error("Cannot revoke current device");let n=t.filter(o=>o.id!==e);localStorage.setItem(this.storageKey,JSON.stringify(n))}async updateLastActive(){let e=await this.getDevices(),t=await f(),r=e.find(n=>n.id===t);r&&(r.lastActive=Date.now(),localStorage.setItem(this.storageKey,JSON.stringify(e)))}getDeviceName(){let e=this.detectPlatform(),t=navigator.userAgent;if(e==="ios")return t.includes("iPhone")?"iPhone":t.includes("iPad")?"iPad":t.includes("iPod")?"iPod":"iOS Device";if(e==="android"){let r=t.match(/Android.*;\s([^)]+)\)/);return r?r[1]:"Android Device"}return e==="macos"?"Mac":e==="windows"?"Windows PC":e==="linux"?"Linux PC":"Unknown Device"}detectPlatform(){let e=navigator.userAgent.toLowerCase();return e.includes("iphone")||e.includes("ipad")||e.includes("ipod")?"ios":e.includes("android")?"android":e.includes("mac")?"macos":e.includes("windows")?"windows":e.includes("linux")?"linux":"unknown"}getPlatformName(e){switch(e){case"ios":return"iOS (iCloud Keychain)";case"android":return"Android (Google)";case"macos":return"macOS (iCloud Keychain)";case"windows":return"Windows (Microsoft)";case"linux":return"Linux";default:return"Unknown"}}async getDeviceListFormatted(){let e=await this.getSyncStatus();if(e.devices.length===0)return"No devices registered";let t=`Your Devices (${e.devices.length}):
319
319
 
320
- `;return e.devices.forEach((r,n)=>{let o=Date.now()-r.lastActive,i=this.formatTimeDiff(o);t+=`${n+1}. ${r.name}
320
+ `;return e.devices.forEach((r,n)=>{let o=Date.now()-r.lastActive,a=this.formatTimeDiff(o);t+=`${n+1}. ${r.name}
321
321
  `,t+=` Platform: ${this.getPlatformName(r.platform)}
322
- `,t+=` Last active: ${i}
322
+ `,t+=` Last active: ${a}
323
323
  `,t+=` ${r.canRevoke?"":"(Current device)"}
324
324
 
325
- `}),t}formatTimeDiff(e){let t=Math.floor(e/1e3),r=Math.floor(t/60),n=Math.floor(r/60),o=Math.floor(n/24);return o>0?`${o} day${o>1?"s":""} ago`:n>0?`${n} hour${n>1?"s":""} ago`:r>0?`${r} minute${r>1?"s":""} ago`:"just now"}}});var G,wt=u(()=>{"use strict";G=class{async detectSyncCapabilities(){let e=this.detectPlatform(),t=await this.checkPasskeySync(),r=this.estimateDeviceCount();return{passkeysSync:t,platform:e,estimatedDevices:r,syncEnabled:t&&e!=="none"}}detectPlatform(){let e=navigator.userAgent.toLowerCase();return e.includes("mac")||e.includes("iphone")||e.includes("ipad")||e.includes("ipod")?"apple":e.includes("android")?"google":e.includes("windows")?"microsoft":"none"}async checkPasskeySync(){if(!window.PublicKeyCredential)return!1;try{return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return!1}}estimateDeviceCount(){return 1}getPlatformEducation(e){switch(e){case"apple":return`
325
+ `}),t}formatTimeDiff(e){let t=Math.floor(e/1e3),r=Math.floor(t/60),n=Math.floor(r/60),o=Math.floor(n/24);return o>0?`${o} day${o>1?"s":""} ago`:n>0?`${n} hour${n>1?"s":""} ago`:r>0?`${r} minute${r>1?"s":""} ago`:"just now"}}});var _,Ct=u(()=>{"use strict";_=class{async detectSyncCapabilities(){let e=this.detectPlatform(),t=await this.checkPasskeySync(),r=this.estimateDeviceCount();return{passkeysSync:t,platform:e,estimatedDevices:r,syncEnabled:t&&e!=="none"}}detectPlatform(){let e=navigator.userAgent.toLowerCase();return e.includes("mac")||e.includes("iphone")||e.includes("ipad")||e.includes("ipod")?"apple":e.includes("android")?"google":e.includes("windows")?"microsoft":"none"}async checkPasskeySync(){if(!window.PublicKeyCredential)return!1;try{return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return!1}}estimateDeviceCount(){return 1}getPlatformEducation(e){switch(e){case"apple":return`
326
326
  \u{1F34E} Apple iCloud Keychain
327
327
 
328
328
  Your passkey automatically syncs across:
@@ -401,7 +401,7 @@ This ensures you can recover if:
401
401
  - Device is lost/stolen
402
402
  - Device is damaged
403
403
  - You switch devices
404
- `}}getSyncInstructions(e){switch(e){case"apple":return["Open Settings on your iPhone/iPad/Mac","Tap your name at the top",'Tap "iCloud"','Enable "Keychain"','Enable "iCloud Backup" (recommended)'];case"google":return["Open Chrome Settings",'Click "You and Google"','Enable "Sync"','Ensure "Passwords" is checked',"Sign in on other devices with same Google account"];case"microsoft":return["Windows Hello sync is limited","Consider using:","- Encrypted ZIP backup","- Social recovery","- Cloud backup (password-protected)"];case"none":return["Platform sync not available","Use alternative backup methods:","- Create encrypted ZIP backup","- Set up social recovery","- Save recovery phrase securely"]}}}});var vt=u(()=>{"use strict"});var $e={};S($e,{DeviceManager:()=>q,PlatformDetector:()=>G,VaultSync:()=>L});var be=u(()=>{"use strict";gt();ft();wt();vt()});var $,bt=u(()=>{"use strict";$=class{getScenarios(){return[{type:"lost-device",description:"Your phone fell in the ocean"},{type:"lost-phrase",description:"Your paper backup burned in a fire"},{type:"lost-both",description:"Phone stolen AND forgot recovery phrase"},{type:"switch-platform",description:"Switching from iPhone to Android"}]}async simulateScenario(e,t){let r=[];switch(e.type){case"lost-device":t.passkeySync.enabled&&t.passkeySync.deviceCount>1&&r.push({method:`Passkey Sync (${t.passkeySync.platform})`,success:!0,time:"5 minutes",requirements:["Sign in to cloud account on new device","Authenticate with biometric/PIN"]}),t.recoveryPhrase.encryptedBackups.length>0&&t.recoveryPhrase.encryptedBackups.forEach(i=>{r.push({method:`Encrypted ${i.method.toUpperCase()} Backup`,success:!0,time:"2 minutes",requirements:["Backup file/QR code","Backup password"]})}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`Contact ${t.socialRecovery.threshold} guardians`,"Collect shares from guardians","Verify identity with each guardian"]});break;case"lost-phrase":t.passkeySync.enabled&&r.push({method:"Passkey (current device)",success:!0,time:"Instant",requirements:["Access to current device","Biometric/PIN authentication"]}),t.passkeySync.deviceCount>1&&r.push({method:"Passkey Sync",success:!0,time:"5 minutes",requirements:["Any synced device","Biometric authentication"]}),t.recoveryPhrase.encryptedBackups.length>0&&r.push({method:"Encrypted Backup",success:!0,time:"2 minutes",requirements:["Backup file","Password"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break;case"lost-both":t.passkeySync.deviceCount>1&&r.push({method:"Passkey Sync",success:!0,time:"5 minutes",requirements:["Cloud account access","New device","Biometric setup"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`,"Identity verification with guardians"]});break;case"switch-platform":t.recoveryPhrase.encryptedBackups.length>0&&r.push({method:"Encrypted Backup",success:!0,time:"2 minutes",requirements:["Backup file","Password"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break}let n=r.length>0,o=this.getEducationalNote(e,r,t);return{scenario:e,success:n,availableMethods:r,timeEstimate:n?this.estimateFastestRecovery(r):"Cannot recover",educationalNote:o}}estimateFastestRecovery(e){let t=e.map(r=>r.time.toLowerCase());if(t.some(r=>r.includes("instant")))return"Instant";if(t.some(r=>r.includes("minute"))){let r=t.filter(n=>n.includes("minute")).map(n=>parseInt(n));return`${Math.min(...r)} minutes`}return t.some(r=>r.includes("hour"))?"24 hours":"Unknown"}getEducationalNote(e,t,r){if(t.length===0)return`
404
+ `}}getSyncInstructions(e){switch(e){case"apple":return["Open Settings on your iPhone/iPad/Mac","Tap your name at the top",'Tap "iCloud"','Enable "Keychain"','Enable "iCloud Backup" (recommended)'];case"google":return["Open Chrome Settings",'Click "You and Google"','Enable "Sync"','Ensure "Passwords" is checked',"Sign in on other devices with same Google account"];case"microsoft":return["Windows Hello sync is limited","Consider using:","- Encrypted ZIP backup","- Social recovery","- Cloud backup (password-protected)"];case"none":return["Platform sync not available","Use alternative backup methods:","- Create encrypted ZIP backup","- Set up social recovery","- Save recovery phrase securely"]}}}});var Rt=u(()=>{"use strict"});var Je={};S(Je,{DeviceManager:()=>H,PlatformDetector:()=>_,VaultSync:()=>Y});var Ce=u(()=>{"use strict";Et();Pt();Ct();Rt()});var V,xt=u(()=>{"use strict";V=class{getScenarios(){return[{type:"lost-device",description:"Your phone fell in the ocean"},{type:"lost-phrase",description:"Your paper backup burned in a fire"},{type:"lost-both",description:"Phone stolen AND forgot recovery phrase"},{type:"switch-platform",description:"Switching from iPhone to Android"}]}async simulateScenario(e,t){let r=[];switch(e.type){case"lost-device":t.passkeySync.enabled&&t.passkeySync.deviceCount>1&&r.push({method:`Passkey Sync (${t.passkeySync.platform})`,success:!0,time:"5 minutes",requirements:["Sign in to cloud account on new device","Authenticate with biometric/PIN"]}),t.recoveryPhrase.encryptedBackups.length>0&&t.recoveryPhrase.encryptedBackups.forEach(a=>{r.push({method:`Encrypted ${a.method.toUpperCase()} Backup`,success:!0,time:"2 minutes",requirements:["Backup file/QR code","Backup password"]})}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`Contact ${t.socialRecovery.threshold} guardians`,"Collect shares from guardians","Verify identity with each guardian"]});break;case"lost-phrase":t.passkeySync.enabled&&r.push({method:"Passkey (current device)",success:!0,time:"Instant",requirements:["Access to current device","Biometric/PIN authentication"]}),t.passkeySync.deviceCount>1&&r.push({method:"Passkey Sync",success:!0,time:"5 minutes",requirements:["Any synced device","Biometric authentication"]}),t.recoveryPhrase.encryptedBackups.length>0&&r.push({method:"Encrypted Backup",success:!0,time:"2 minutes",requirements:["Backup file","Password"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break;case"lost-both":t.passkeySync.deviceCount>1&&r.push({method:"Passkey Sync",success:!0,time:"5 minutes",requirements:["Cloud account access","New device","Biometric setup"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`,"Identity verification with guardians"]});break;case"switch-platform":t.recoveryPhrase.encryptedBackups.length>0&&r.push({method:"Encrypted Backup",success:!0,time:"2 minutes",requirements:["Backup file","Password"]}),t.socialRecovery?.enabled&&r.push({method:"Social Recovery",success:!0,time:"24 hours",requirements:[`${t.socialRecovery.threshold} guardian shares`]});break}let n=r.length>0,o=this.getEducationalNote(e,r,t);return{scenario:e,success:n,availableMethods:r,timeEstimate:n?this.estimateFastestRecovery(r):"Cannot recover",educationalNote:o}}estimateFastestRecovery(e){let t=e.map(r=>r.time.toLowerCase());if(t.some(r=>r.includes("instant")))return"Instant";if(t.some(r=>r.includes("minute"))){let r=t.filter(n=>n.includes("minute")).map(n=>parseInt(n));return`${Math.min(...r)} minutes`}return t.some(r=>r.includes("hour"))?"24 hours":"Unknown"}getEducationalNote(e,t,r){if(t.length===0)return`
405
405
  \u274C WALLET CANNOT BE RECOVERED
406
406
 
407
407
  Scenario: ${e.description}
@@ -442,10 +442,10 @@ Scenario: ${e.description}
442
442
 
443
443
  `;return n+=`Available recovery methods (${t.length}):
444
444
 
445
- `,t.forEach((o,i)=>{n+=`${i+1}. ${o.method}
445
+ `,t.forEach((o,a)=>{n+=`${a+1}. ${o.method}
446
446
  `,n+=` \u23F1 Time: ~${o.time}
447
447
  `,n+=` Requirements:
448
- `,o.requirements.forEach(c=>{n+=` - ${c}
448
+ `,o.requirements.forEach(i=>{n+=` - ${i}
449
449
  `}),n+=`
450
450
  `}),n+=`
451
451
  RECOMMENDATIONS:
@@ -457,19 +457,19 @@ RECOMMENDATIONS:
457
457
  `,r.socialRecovery?.enabled||(n+=` Consider adding social recovery for maximum security.
458
458
  `)):(n+=`\u{1F7E2} Excellent! You have ${t.length} recovery methods.
459
459
  `,n+=` Your wallet is well-protected!
460
- `),n}async runInteractiveTest(e){let t=this.getScenarios(),r=[];for(let c of t){let a=await this.simulateScenario(c,e);r.push(a)}let n=r.filter(c=>c.success).length,o=n/t.length*100,i="";return o===100?i=`\u{1F3C6} PERFECT SCORE!
460
+ `),n}async runInteractiveTest(e){let t=this.getScenarios(),r=[];for(let i of t){let c=await this.simulateScenario(i,e);r.push(c)}let n=r.filter(i=>i.success).length,o=n/t.length*100,a="";return o===100?a=`\u{1F3C6} PERFECT SCORE!
461
461
 
462
462
  You can recover in ALL scenarios.
463
- Your wallet is extremely well-protected!`:o>=75?i=`\u{1F7E2} GREAT JOB!
463
+ Your wallet is extremely well-protected!`:o>=75?a=`\u{1F7E2} GREAT JOB!
464
464
 
465
465
  You can recover in ${n}/${t.length} scenarios.
466
- Consider adding more backup methods for complete coverage.`:o>=50?i=`\u{1F7E1} GOOD START!
466
+ Consider adding more backup methods for complete coverage.`:o>=50?a=`\u{1F7E1} GOOD START!
467
467
 
468
468
  You can recover in ${n}/${t.length} scenarios.
469
- Add more backup methods to improve security.`:i=`\u26A0\uFE0F AT RISK!
469
+ Add more backup methods to improve security.`:a=`\u26A0\uFE0F AT RISK!
470
470
 
471
471
  You can only recover in ${n}/${t.length} scenarios.
472
- Urgently add backup methods to protect your wallet!`,{scenarios:r,overallScore:o,feedback:i}}}});function Ye(s){return Se[s]||null}function He(){return Object.keys(Se)}function _e(s){let e=s.toLowerCase();return Object.values(Se).filter(t=>t.title.toLowerCase().includes(e)||t.content.toLowerCase().includes(e))}var Se,St=u(()=>{"use strict";Se={whatIsPasskey:{title:"What is a Passkey?",content:`
472
+ Urgently add backup methods to protect your wallet!`,{scenarios:r,overallScore:o,feedback:a}}}});function ze(s){return Re[s]||null}function Ze(){return Object.keys(Re)}function Xe(s){let e=s.toLowerCase();return Object.values(Re).filter(t=>t.title.toLowerCase().includes(e)||t.content.toLowerCase().includes(e))}var Re,It=u(()=>{"use strict";Re={whatIsPasskey:{title:"What is a Passkey?",content:`
473
473
  Think of a passkey like your house smart lock:
474
474
 
475
475
  \u{1F511} Traditional Key (Password):
@@ -773,5 +773,5 @@ STORAGE OPTIONS:
773
773
  - Email to yourself
774
774
 
775
775
  The encryption makes it safe even in cloud!
776
- `}}});var ke={};S(ke,{RecoverySimulator:()=>$,educationalModules:()=>Se,getAllTopics:()=>He,getExplainer:()=>Ye,searchExplainers:()=>_e});var z=u(()=>{"use strict";bt();St()});var Xt={};S(Xt,{ApiError:()=>X,AuthenticationError:()=>k,BackupManager:()=>U,BackupStorage:()=>A,CryptoError:()=>y,DeviceManager:()=>q,PlatformDetector:()=>G,RecoverySimulator:()=>$,RegistrationError:()=>T,SocialRecoveryManager:()=>N,StealthAddressModule:()=>F,StorageError:()=>h,VaultSync:()=>L,WalletError:()=>d,Web3Passkey:()=>Y,Web3PasskeyError:()=>g,assertEthereumAddress:()=>ee,assertMnemonic:()=>je,assertUsername:()=>te,canControlStealthAddress:()=>it,checkStealthAddress:()=>Q,computeStealthPrivateKey:()=>he,createWalletFromMnemonic:()=>et,createWeb3Passkey:()=>kt,default:()=>Zt,deriveStealthKeys:()=>D,deriveWalletFromMnemonic:()=>ce,generateBIP39Wallet:()=>ae,generateStealthAddress:()=>pe,getAllTopics:()=>He,getExplainer:()=>Ye,isStrongPassword:()=>Je,searchExplainers:()=>_e,validateEthereumAddress:()=>Pe,validateMnemonic:()=>Re,validateUsername:()=>Ce});module.exports=Dt(Xt);var ze=require("@simplewebauthn/browser");w();function Pe(s){return/^0x[a-fA-F0-9]{40}$/.test(s)}function Ce(s){return s.length>=3&&s.length<=50}function Re(s){let e=s.trim().split(/\s+/);return e.length===12||e.length===24}function ee(s){if(!Pe(s))throw new Error("Invalid Ethereum address format")}function te(s){if(!Ce(s))throw new Error("Username must be between 3 and 50 characters")}function je(s){if(!Re(s))throw new Error("Invalid mnemonic: must be 12 or 24 words")}function Je(s){if(s.length<12)return!1;let e=/[A-Z]/.test(s),t=/[a-z]/.test(s),r=/[0-9]/.test(s),n=/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(s);return!(!e||!t||!r||!n||["password","12345678","qwerty","abc123","password123","admin","letmein"].some(i=>s.toLowerCase().includes(i)))}R();function Ft(){let s=new Uint8Array(32);return crypto.getRandomValues(s),btoa(String.fromCharCode(...s)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function Ze(s){try{let{username:e,ethereumAddress:t}=s;te(e),ee(t);let r=new C;if(r.userExists(e))throw new Error("Username already registered");let o={challenge:Ft(),rp:{name:"w3pk",id:window.location.hostname},user:{id:e,name:e,displayName:e},pubKeyCredParams:[{type:"public-key",alg:-7},{type:"public-key",alg:-257}],authenticatorSelection:{authenticatorAttachment:"platform",userVerification:"required",residentKey:"required",requireResidentKey:!0},timeout:6e4,attestation:"none"},i=await(0,ze.startRegistration)({optionsJSON:o}),c=i.response.publicKey;if(!c)throw new Error("Public key not returned from authenticator");r.saveCredential({id:i.id,publicKey:c,username:e,ethereumAddress:t,createdAt:Date.now(),lastUsed:Date.now()}),console.log("[register] Credential response:",i.response);let a=i.response.attestationObject;if(console.log("[register] Attestation object:",a),!a)throw new Error("Attestation object not returned from authenticator");let l=Mt(a);return console.log("[register] Attestation buffer length:",l.byteLength),{signature:l}}catch(e){throw new T(e instanceof Error?e.message:"Registration failed",e)}}function Mt(s){let e=s.replace(/-/g,"+").replace(/_/g,"/"),t=atob(e),r=new Uint8Array(t.length);for(let n=0;n<t.length;n++)r[n]=t.charCodeAt(n);return r.buffer}var Xe=require("@simplewebauthn/browser");w();R();function Kt(){let s=new Uint8Array(32);return crypto.getRandomValues(s),btoa(String.fromCharCode(...s)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function oe(){try{let s=new C,t={challenge:Kt(),rpId:window.location.hostname,userVerification:"required",timeout:6e4},r=await(0,Xe.startAuthentication)({optionsJSON:t}),n=s.getCredentialById(r.id);if(!n)throw new Error("Credential not found");if(!await Ot(r,n))throw new Error("Signature verification failed");s.updateLastUsed(n.id);let i=se(r.response.signature);return{verified:!0,user:{username:n.username,ethereumAddress:n.ethereumAddress,credentialId:n.id},signature:i}}catch(s){throw new k(s instanceof Error?s.message:"Authentication failed",s)}}async function Ot(s,e){try{let t=se(e.publicKey),r=await crypto.subtle.importKey("spki",t,{name:"ECDSA",namedCurve:"P-256"},!1,["verify"]),n=se(s.response.authenticatorData),o=s.response.clientDataJSON,i;o.startsWith("eyJ")?i=atob(o.replace(/-/g,"+").replace(/_/g,"/")):i=o;let c=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(i)),a=new Uint8Array(n.byteLength+c.byteLength);a.set(new Uint8Array(n),0),a.set(new Uint8Array(c),n.byteLength);let l=se(s.response.signature),p=Ut(new Uint8Array(l));return await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},r,p,a)}catch(t){return console.error("Signature verification error:",t),!1}}function se(s){let e=s.replace(/-/g,"+").replace(/_/g,"/"),t=atob(e),r=new Uint8Array(t.length);for(let n=0;n<t.length;n++)r[n]=t.charCodeAt(n);return r.buffer}function Ut(s){let e=2;e++;let t=s[e++];t>32&&(e++,t--);let r=s.slice(e,e+t);e+=t,e++;let n=s[e++];n>32&&(e++,n--);let o=s.slice(e,e+n),i=new Uint8Array(64);return i.set(r,32-r.length),i.set(o,64-o.length),i.buffer}w();var Wt="Web3PasskeyWallet",Nt=1,v="wallets",ie=class{constructor(){this.db=null}async init(){return new Promise((e,t)=>{let r=indexedDB.open(Wt,Nt);r.onerror=()=>t(new h("Failed to open database",r.error)),r.onsuccess=()=>{this.db=r.result,e()},r.onupgradeneeded=()=>{let n=r.result;n.objectStoreNames.contains(v)||n.createObjectStore(v,{keyPath:"ethereumAddress"})}})}async store(e){return this.db||await this.init(),new Promise((t,r)=>{let i=this.db.transaction([v],"readwrite").objectStore(v).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([v],"readonly").objectStore(v).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([v],"readwrite").objectStore(v).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([v],"readwrite").objectStore(v).clear();o.onerror=()=>t(new h("Failed to clear wallet data",o.error)),o.onsuccess=()=>e()})}};var V=require("ethers");w();function ae(){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 d("Wallet generation failed",s)}}function et(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 d(`Wallet creation failed: ${e instanceof Error?e.message:"Invalid mnemonic"}`,e)}}function ce(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 d(`HD wallet derivation failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}ue();w();var m=require("ethers");w();function D(s){try{let e=m.ethers.HDNodeWallet.fromPhrase(s,void 0,"m/44'/60'/1'/0/0"),t=m.ethers.HDNodeWallet.fromPhrase(s,void 0,"m/44'/60'/1'/0/1"),r=t.signingKey.compressedPublicKey,n=e.signingKey.compressedPublicKey,o=r+n.slice(2),i=Yt(e.signingKey.publicKey,t.signingKey.publicKey);return{stealthMetaAddress:o,spendingPubKey:r,viewingPubKey:n,viewingKey:e.privateKey,spendingKey:t.privateKey,metaAddress:i}}catch(e){throw new y("Failed to derive stealth keys",e)}}function pe(s){try{let e="0x"+s.slice(2,68),t="0x"+s.slice(68),r=m.ethers.Wallet.createRandom(),n=r.signingKey.compressedPublicKey,o=Ie(r.privateKey,t),i=m.ethers.keccak256(o),c="0x"+i.slice(2,4),a=st(e,nt(i));return{stealthAddress:ot(a),ephemeralPubKey:n,viewTag:c,ephemeralPubkey:n}}catch(e){throw new y("Failed to generate stealth address",e)}}function Q(s,e,t,r,n){try{let o=Ie(s,t),i=m.ethers.keccak256(o);if(n&&("0x"+i.slice(2,4)).toLowerCase()!==n.toLowerCase())return{isForUser:!1};let c=st(e,nt(i)),a=ot(c);return a.toLowerCase()!==r.toLowerCase()?{isForUser:!1}:{isForUser:!0,stealthAddress:a}}catch{return{isForUser:!1}}}function he(s,e,t){try{let r=Ie(s,t),n=m.ethers.keccak256(r);return $t(e,n)}catch(r){throw new y("Failed to compute stealth private key",r)}}function Ie(s,e){try{return new m.ethers.Wallet(s).signingKey.computeSharedSecret(e)}catch(t){throw new y("Failed to compute shared secret",t)}}function nt(s){try{return new m.ethers.Wallet(s).signingKey.compressedPublicKey}catch(e){throw new y("Failed to multiply generator by scalar",e)}}function st(s,e){try{let t=m.ethers.SigningKey.computePublicKey(s,!1),r=m.ethers.SigningKey.computePublicKey(e,!1),n=BigInt("0x"+t.slice(4,68)),o=BigInt("0x"+t.slice(68)),i=BigInt("0x"+r.slice(4,68)),c=BigInt("0x"+r.slice(68)),a=BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");if(n===i&&o===c){let Et=3n*n*n%a,Pt=2n*o%a,Ee=Et*rt(Pt,a)%a,Ve=(Ee*Ee-2n*n)%a,Ct=(Ee*(n-Ve)-o)%a;return tt((Ve+a)%a,(Ct+a)%a)}let l=((c-o)%a+a)%a,p=((i-n)%a+a)%a,H=l*rt(p,a)%a,Ae=(H*H-n-i)%a,At=(H*(n-Ae)-o)%a;return tt((Ae+a)%a,(At+a)%a)}catch(t){throw new y("Failed to add public keys",t)}}function $t(s,e){try{let t=BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"),r=BigInt(s),n=BigInt(e);return"0x"+((r+n)%t).toString(16).padStart(64,"0")}catch(t){throw new y("Failed to add private keys",t)}}function tt(s,e){return"0x"+(e%2n===0n?"02":"03")+s.toString(16).padStart(64,"0")}function rt(s,e){s=(s%e+e)%e;let[t,r]=[s,e],[n,o]=[1n,0n];for(;r!==0n;){let i=t/r;[t,r]=[r,t-i*r],[n,o]=[o,n-i*o]}return(n%e+e)%e}function ot(s){try{let e=m.ethers.SigningKey.computePublicKey(s,!1),t=m.ethers.keccak256("0x"+e.slice(4));return m.ethers.getAddress("0x"+t.slice(-40))}catch(e){throw new y("Failed to derive address from public key",e)}}function Yt(s,e){let t=m.ethers.solidityPackedKeccak256(["bytes","bytes"],[s,e]);return m.ethers.getAddress("0x"+t.slice(26))}function it(s,e,t,r){let n=new m.ethers.Wallet(e);return Q(s,n.signingKey.compressedPublicKey,t,r).isForUser}var F=class{constructor(e,t){this.getMnemonic=t}async generateStealthAddress(e){try{let t=await this.getMnemonic(e?.requireAuth),r=D(t),n=pe(r.stealthMetaAddress);return{stealthAddress:n.stealthAddress,ephemeralPublicKey:n.ephemeralPubKey,viewTag:n.viewTag}}catch(t){throw new g("Failed to generate stealth address","STEALTH_GENERATION_ERROR",t)}}async parseAnnouncement(e,t){try{let r=await this.getMnemonic(t?.requireAuth),n=D(r),o=Q(n.viewingKey,n.spendingPubKey,e.ephemeralPublicKey,e.stealthAddress,e.viewTag);if(!o.isForUser)return{isForUser:!1};let i=he(n.viewingKey,n.spendingKey,e.ephemeralPublicKey);return{isForUser:!0,stealthAddress:o.stealthAddress,stealthPrivateKey:i}}catch(r){throw new g("Failed to parse announcement","ANNOUNCEMENT_PARSE_ERROR",r)}}async scanAnnouncements(e,t){let r=[];for(let n of e){let o=await this.parseAnnouncement(n,t);o.isForUser&&r.push(o)}return r}async getKeys(e){try{let t=await this.getMnemonic(e?.requireAuth);return D(t)}catch(t){throw new g("Failed to get stealth keys","STEALTH_KEYS_ERROR",t)}}async getStealthMetaAddress(e){try{return(await this.getKeys(e)).stealthMetaAddress}catch(t){throw new g("Failed to get stealth meta-address","STEALTH_META_ADDRESS_ERROR",t)}}get isAvailable(){return!0}};var ye=class{constructor(e=1){this.session=null;this.sessionDuration=e*60*60*1e3}startSession(e,t){let r=Date.now()+this.sessionDuration;this.session={mnemonic:e,expiresAt:r,credentialId:t}}getMnemonic(){return this.session?Date.now()>this.session.expiresAt?(this.clearSession(),null):this.session.mnemonic:null}getCredentialId(){return this.session?Date.now()>this.session.expiresAt?(this.clearSession(),null):this.session.credentialId:null}isActive(){return this.getMnemonic()!==null}getRemainingTime(){return this.session?Date.now()>this.session.expiresAt?(this.clearSession(),0):Math.floor((this.session.expiresAt-Date.now())/1e3):0}extendSession(){if(!this.session)throw new Error("No active session to extend");if(Date.now()>this.session.expiresAt)throw this.clearSession(),new Error("Session expired, cannot extend");this.session.expiresAt=Date.now()+this.sessionDuration}clearSession(){this.session&&(this.session.mnemonic="0".repeat(this.session.mnemonic.length)),this.session=null}setSessionDuration(e){this.sessionDuration=e*60*60*1e3}};var Be={debug:!1,sessionDuration:1,onError:s=>{Be.debug&&console.error("[w3pk]",s)}};w();var at="https://chainid.network/chains.json";var me=null,Ht=[/\$\{[\w_]+\}/i,/\{[\w_]+\}/i,/<[\w_]+>/i,/YOUR[-_]?API[-_]?KEY/i,/INSERT[-_]?API[-_]?KEY/i,/API[-_]?KEY[-_]?HERE/i];function _t(s){return Ht.some(e=>e.test(s))}async function Vt(s=at){let e=await fetch(s);if(!e.ok)throw new Error(`Failed to fetch chains data: ${e.status} ${e.statusText}`);return await e.json()}async function Qt(s){let e=s?.chainsJsonUrl??at,t=s?.cacheDuration??36e5,r=Date.now();if(me&&r-me.timestamp<t)return me.data;let n=await Vt(e);return me={data:n,timestamp:r},n}async function ct(s,e){let r=(await Qt(e)).find(n=>n.chainId===s);return r?r.rpc.filter(n=>!_t(n)&&!n.startsWith("wss://")&&!n.startsWith("ws://")):[]}var jt=new Set([1,10,8453,42161,57073,100,42220,137,42,15,40,41,44,46,47,50,51,56,61,71,82,83,95,97,112,123,130,146,151,153,171,180,183,185,195,215,228,247,248,252,261,267,291,293,311,332,336,395,401,416,466,480,488,510,545,634,647,648,747,831,919,938,945,957,964,970,980,995,997,1001,1003,1024,1030,1114,1125,1135,1149,1188,1284,1285,1287,1300,1301,1315,1337,1338,1339,1424,1514,1687,1727,1729,1740,1750,1829,1868,1946,1961,1962,1969,1989,1995,2017,2020,2031,2043,2109,2241,2340,2345,2440,2522,2559,2649,3068,3109,3338,3502,3799,3888,3889,4e3,4048,4078,4162,4201,4202,4460,4488,4661,4689,4690,4888,5e3,5003,5124,5234,5330,5424,5522,6283,6342,6398,6678,6806,6934,6942,6969,7117,7171,7200,7208,7368,7518,7668,7672,7744,7771,7869,7897,8008,8118,8217,8408,8700,8726,8727,8844,8880,8881,8882,8889,9372,9496,9700,9745,9746,9899,9990,9996,10011,10085,10143,10200,11221,11501,11504,11891,13370,14853,16602,16661,17e3,18880,18881,19991,21e3,21816,21912,25327,32323,33401,34443,41923,42170,43111,44787,47805,48898,48900,49049,49088,5e4,50312,53302,53456,53457,55244,56288,59141,60808,60850,62320,62850,64002,71402,72080,73114,73115,75338,78281,80002,80008,80069,80094,80451,80931,84532,88899,91342,92278,94524,96970,97476,97477,98985,100021,100501,101010,102030,102031,102032,112358,120893,121212,121213,121214,121215,129399,161803,175188,192940,193939,198989,212013,222222,240241,325e3,355110,355113,421614,555777,560048,656476,713715,743111,747474,763373,763375,777777,806582,808813,810180,839999,888991,2019775,2222222,4278608,5734951,6666689,6985385,7080969,7777777,9999999,11142220,11155111,11155420,11155931,16969696,19850818,20180427,20250825,28122024,34949059,37084624,52164803,61022448,79479957,96969696,420420421,420420422,888888888,974399131,999999999,1020352220,1273227453,1313161560,1350216234,1380996178,1417429182,1444673419,1482601649,1564830818,2046399126,11297108099,11297108109,88153591557,123420000220,123420001114]);async function Jt(s,e=1e4){try{let t=new AbortController,r=setTimeout(()=>t.abort(),e),n=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},signal:t.signal,body:JSON.stringify({jsonrpc:"2.0",method:"eth_estimateGas",params:[{from:"0xdeadbeef00000000000000000000000000000000",to:"0xdeadbeef00000000000000000000000000000000",data:"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",value:"0x0"},"latest",{"0xdeadbeef00000000000000000000000000000000":{code:"0xef01000000000000000000000000000000000000000001"}}],id:1})});if(clearTimeout(r),!n.ok)return!1;let o=await n.json();if(o.error){let i=(o.error.message||"").toLowerCase();return!["unsupported","not supported","unknown","invalid","unrecognized","does not support","not implemented"].some(a=>i.includes(a))}return o.result!==void 0}catch{return!1}}async function dt(s,e,t){if(jt.has(s))return!0;let r=t?.maxEndpoints||3,n=t?.timeout||1e4;try{let o=await e(s);if(o.length===0)return!1;let i=o.slice(0,r);for(let c of i)if(await Jt(c,n))return!0;return!1}catch{return!1}}var Y=class{constructor(e={}){this.currentUser=null;this.currentWallet=null;this.config={...Be,...e},this.walletStorage=new ie,this.sessionManager=new ye(e.sessionDuration||1),e.stealthAddresses!==void 0&&(this.stealth=new F(e.stealthAddresses,t=>this.getMnemonicFromSession(t)))}async loadZKModule(){if(this.zkModule)return this.zkModule;try{let e=new Function("path","return import(path)"),{ZKProofModule:t}=await e("w3pk/zk"),r=this.config.zkProofs||{};return this.zkModule=new t(r),this.zkModule}catch{throw new Error("ZK module not available. Install dependencies: npm install snarkjs circomlibjs")}}async getMnemonicFromSession(e=!1){if(!e){let l=this.sessionManager.getMnemonic();if(l)return l}if(!this.currentUser)throw new d("Must be authenticated. Call login() first.");let t=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!t)throw new d("No wallet found. Generate a wallet first.");if(!(await oe()).user)throw new d("Authentication failed");let i=new(await Promise.resolve().then(()=>(R(),_))).CredentialStorage().getCredentialById(t.credentialId)?.publicKey,c=await x(t.credentialId,i),a=await le(t.encryptedMnemonic,c);return this.sessionManager.startSession(a,t.credentialId),a}async register(e){try{this.currentWallet?.address||await this.generateWallet();let t=this.currentWallet.address,r=this.currentWallet.mnemonic;await Ze({username:e.username,ethereumAddress:t}),this.currentUser={id:t,username:e.username,displayName:e.username,ethereumAddress:t};let o=new(await Promise.resolve().then(()=>(R(),_))).CredentialStorage().getCredentialByAddress(t);if(!o)throw new d("Credential not found after registration");let i=o.id,c=o.publicKey,a=await x(i,c),l=await de(r,a);return await this.walletStorage.store({ethereumAddress:this.currentUser.ethereumAddress,encryptedMnemonic:l,credentialId:i,createdAt:Date.now()}),this.sessionManager.startSession(r,i),this.currentWallet={address:t,mnemonic:r},this.config.onAuthStateChanged?.(!0,this.currentUser),{address:t,username:e.username}}catch(t){throw this.config.onError?.(t),t}}async login(){try{let e=await oe();if(!e.verified||!e.user)throw new k("Login failed");this.currentUser={id:e.user.ethereumAddress,username:e.user.username,displayName:e.user.username,ethereumAddress:e.user.ethereumAddress};let t=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!t)throw new d("No wallet found for this user. You may need to register first.");let o=new(await Promise.resolve().then(()=>(R(),_))).CredentialStorage().getCredentialById(t.credentialId)?.publicKey,i=await x(t.credentialId,o),c=await le(t.encryptedMnemonic,i);return this.sessionManager.startSession(c,t.credentialId),this.config.onAuthStateChanged?.(!0,this.currentUser),this.currentUser}catch(e){throw this.config.onError?.(e),e}}async logout(){this.currentUser=null,this.currentWallet=null,this.sessionManager.clearSession(),this.config.onAuthStateChanged?.(!1,void 0)}get isAuthenticated(){return this.currentUser!==null}get user(){return this.currentUser}async generateWallet(){try{let e=ae();return this.currentWallet={address:e.address,mnemonic:e.mnemonic},{mnemonic:e.mnemonic}}catch(e){throw this.config.onError?.(e),new d("Failed to generate wallet",e)}}async deriveWallet(e,t){try{if(!this.currentUser)throw new d("Must be authenticated to derive wallet");let r=await this.getMnemonicFromSession(t?.requireAuth),n=ce(r,e);return{address:n.address,privateKey:n.privateKey}}catch(r){throw this.config.onError?.(r),new d("Failed to derive wallet",r)}}async exportMnemonic(e){try{if(!this.currentUser)throw new d("Must be authenticated to export mnemonic");return await this.getMnemonicFromSession(e?.requireAuth)}catch(t){throw this.config.onError?.(t),new d("Failed to export mnemonic",t)}}async importMnemonic(e){try{if(!this.currentUser)throw new d("Must be authenticated to import mnemonic");if(!e||e.trim().split(/\s+/).length<12)throw new d("Invalid mnemonic: must be at least 12 words");let t=await oe();if(!t.user)throw new d("Authentication failed");let r=t.user.credentialId,i=new(await Promise.resolve().then(()=>(R(),_))).CredentialStorage().getCredentialById(r)?.publicKey,c=await x(r,i),a=await de(e.trim(),c);await this.walletStorage.store({ethereumAddress:this.currentUser.ethereumAddress,encryptedMnemonic:a,credentialId:r,createdAt:Date.now()}),this.currentWallet={address:this.currentUser.ethereumAddress,mnemonic:e.trim()},this.sessionManager.startSession(e.trim(),r)}catch(t){throw this.config.onError?.(t),new d("Failed to import mnemonic",t)}}async signMessage(e,t){try{if(!this.currentUser)throw new d("Must be authenticated to sign message");let r=await this.getMnemonicFromSession(t?.requireAuth),{Wallet:n}=await import("ethers");return await n.fromPhrase(r).signMessage(e)}catch(r){throw this.config.onError?.(r),new d("Failed to sign message",r)}}async getEndpoints(e){return ct(e)}async supportsEIP7702(e,t){return dt(e,this.getEndpoints.bind(this),t)}get zk(){return new Proxy({},{get:(e,t)=>async(...r)=>(await this.loadZKModule())[t](...r)})}async getBackupStatus(){if(!this.currentUser)throw new d("Must be authenticated to check backup status");let{BackupManager:e}=await Promise.resolve().then(()=>(I(),W));return new e().getBackupStatus(this.currentUser.ethereumAddress)}async createZipBackup(e,t){if(!this.currentUser)throw new d("Must be authenticated to create backup");let r=await this.getMnemonicFromSession(!0),{BackupManager:n}=await Promise.resolve().then(()=>(I(),W));return new n().createZipBackup(r,this.currentUser.ethereumAddress,{password:e,...t})}async createQRBackup(e,t){if(!this.currentUser)throw new d("Must be authenticated to create backup");let r=await this.getMnemonicFromSession(!0),{BackupManager:n}=await Promise.resolve().then(()=>(I(),W));return new n().createQRBackup(r,this.currentUser.ethereumAddress,{password:e,...t})}async setupSocialRecovery(e,t){if(!this.currentUser)throw new d("Must be authenticated to set up social recovery");let r=await this.getMnemonicFromSession(!0),{SocialRecoveryManager:n}=await Promise.resolve().then(()=>(J(),ve));return new n().setupSocialRecovery(r,this.currentUser.ethereumAddress,e,t)}async generateGuardianInvite(e){let{SocialRecoveryManager:t}=await Promise.resolve().then(()=>(J(),ve)),r=new t,n=r.getSocialRecoveryConfig();if(!n)throw new d("Social recovery not configured");let o=n.guardians.find(i=>i.id===e);if(!o)throw new d("Guardian not found");return r.generateGuardianInvite(o)}async recoverFromGuardians(e){let{SocialRecoveryManager:t}=await Promise.resolve().then(()=>(J(),ve));return new t().recoverFromGuardians(e)}async restoreFromBackup(e,t){let{BackupManager:r}=await Promise.resolve().then(()=>(I(),W));return new r().restoreFromZipBackup(e,t)}async restoreFromQR(e,t){let{BackupManager:r}=await Promise.resolve().then(()=>(I(),W));return new r().restoreFromQR(e,t)}async getSyncStatus(){let{DeviceManager:e}=await Promise.resolve().then(()=>(be(),$e));return new e().getSyncStatus()}async detectSyncCapabilities(){let{PlatformDetector:e}=await Promise.resolve().then(()=>(be(),$e));return new e().detectSyncCapabilities()}async simulateRecoveryScenario(e){if(!this.currentUser)throw new d("Must be authenticated to run recovery simulation");let t=await this.getBackupStatus(),{RecoverySimulator:r}=await Promise.resolve().then(()=>(z(),ke));return new r().simulateScenario(e,t)}async runRecoveryTest(){if(!this.currentUser)throw new d("Must be authenticated to run recovery test");let e=await this.getBackupStatus(),{RecoverySimulator:t}=await Promise.resolve().then(()=>(z(),ke));return new t().runInteractiveTest(e)}async getEducation(e){let{getExplainer:t}=await Promise.resolve().then(()=>(z(),ke)),r=t(e);if(!r)throw new d(`Unknown education topic: ${e}`);return r}hasActiveSession(){return this.sessionManager.isActive()}getSessionRemainingTime(){return this.sessionManager.getRemainingTime()}extendSession(){try{this.sessionManager.extendSession()}catch(e){throw new d("Cannot extend session",e)}}clearSession(){this.sessionManager.clearSession()}setSessionDuration(e){this.sessionManager.setSessionDuration(e)}get version(){return"0.7.2"}};w();I();J();be();z();function kt(s={}){return new Y(s)}var Zt=kt;
776
+ `}}});var xe={};S(xe,{RecoverySimulator:()=>V,educationalModules:()=>Re,getAllTopics:()=>Ze,getExplainer:()=>ze,searchExplainers:()=>Xe});var ae=u(()=>{"use strict";xt();It()});var sr={};S(sr,{ApiError:()=>ce,AuthenticationError:()=>k,BackupManager:()=>q,BackupStorage:()=>E,CryptoError:()=>h,DeviceManager:()=>H,PlatformDetector:()=>_,RecoverySimulator:()=>V,RegistrationError:()=>D,SocialRecoveryManager:()=>G,StealthAddressModule:()=>O,StorageError:()=>y,VaultSync:()=>Y,WalletError:()=>d,Web3Passkey:()=>Q,Web3PasskeyError:()=>m,assertEthereumAddress:()=>de,assertMnemonic:()=>rt,assertUsername:()=>le,canControlStealthAddress:()=>ut,checkStealthAddress:()=>re,computeStealthPrivateKey:()=>ne,createWalletFromMnemonic:()=>ct,createWeb3Passkey:()=>Bt,default:()=>nr,deriveStealthKeys:()=>U,deriveWalletFromMnemonic:()=>we,generateBIP39Wallet:()=>fe,generateStealthAddress:()=>ve,getAllTopics:()=>Ze,getExplainer:()=>ze,isStrongPassword:()=>nt,searchExplainers:()=>Xe,validateEthereumAddress:()=>Te,validateMnemonic:()=>Fe,validateUsername:()=>De});module.exports=Lt(sr);var ot=require("@simplewebauthn/browser");w();function Te(s){return/^0x[a-fA-F0-9]{40}$/.test(s)}function De(s){return s.length>=3&&s.length<=50}function Fe(s){let e=s.trim().split(/\s+/);return e.length===12||e.length===24}function de(s){if(!Te(s))throw new Error("Invalid Ethereum address format")}function le(s){if(!De(s))throw new Error("Username must be between 3 and 50 characters")}function rt(s){if(!Fe(s))throw new Error("Invalid mnemonic: must be 12 or 24 words")}function nt(s){if(s.length<12)return!1;let e=/[A-Z]/.test(s),t=/[a-z]/.test(s),r=/[0-9]/.test(s),n=/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(s);return!(!e||!t||!r||!n||["password","12345678","qwerty","abc123","password123","admin","letmein"].some(a=>s.toLowerCase().includes(a)))}I();J();function Gt(){let s=new Uint8Array(32);return crypto.getRandomValues(s),A(s)}async function at(s){try{let{username:e,ethereumAddress:t}=s;le(e),de(t);let r=new x;if(await r.userExists(e))throw new Error("Username already registered");let o={challenge:Gt(),rp:{name:"w3pk",id:window.location.hostname},user:{id:e,name:e,displayName:e},pubKeyCredParams:[{type:"public-key",alg:-7},{type:"public-key",alg:-257}],authenticatorSelection:{authenticatorAttachment:"platform",userVerification:"required",residentKey:"required",requireResidentKey:!0},timeout:6e4,attestation:"none"},a=await(0,ot.startRegistration)({optionsJSON:o}),i=a.response.publicKey;if(!i)throw new Error("Public key not returned from authenticator");await r.saveCredential({id:a.id,publicKey:i,username:e,ethereumAddress:t,createdAt:Date.now(),lastUsed:Date.now()}),console.log("[register] Credential response:",a.response);let c=a.response.attestationObject;if(console.log("[register] Attestation object:",c),!c)throw new Error("Attestation object not returned from authenticator");let l=R(c);return console.log("[register] Attestation buffer length:",l.byteLength),{signature:l}}catch(e){throw new D(e instanceof Error?e.message:"Registration failed",e)}}var it=require("@simplewebauthn/browser");w();I();J();function Yt(){let s=new Uint8Array(32);return crypto.getRandomValues(s),A(s)}async function me(){try{let s=new x,t={challenge:Yt(),rpId:window.location.hostname,userVerification:"required",timeout:6e4},r=await(0,it.startAuthentication)({optionsJSON:t}),n=await s.getCredentialById(r.id);if(!n)throw new Error("Credential not found");if(!await Ht(r,n))throw new Error("Signature verification failed");await s.updateLastUsed(n.id);let a=R(r.response.signature);return{verified:!0,user:{username:n.username,ethereumAddress:n.ethereumAddress,credentialId:n.id},signature:a}}catch(s){throw new k(s instanceof Error?s.message:"Authentication failed",s)}}async function Ht(s,e){try{let t=R(e.publicKey),r=await crypto.subtle.importKey("spki",t,{name:"ECDSA",namedCurve:"P-256"},!1,["verify"]),n=R(s.response.authenticatorData),o=s.response.clientDataJSON,a;o.startsWith("eyJ")?a=F(o):a=o;let i=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(a)),c=new Uint8Array(n.byteLength+i.byteLength);c.set(new Uint8Array(n),0),c.set(new Uint8Array(i),n.byteLength);let l=R(s.response.signature),p=_t(new Uint8Array(l));return await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},r,p,c)}catch(t){return console.error("Signature verification error:",t),!1}}function _t(s){let e=2;e++;let t=s[e++];t>32&&(e++,t--);let r=s.slice(e,e+t);e+=t,e++;let n=s[e++];n>32&&(e++,n--);let o=s.slice(e,e+n),a=new Uint8Array(64);return a.set(r,32-r.length),a.set(o,64-o.length),a.buffer}w();var Vt="Web3PasskeyWallet",Qt=1,v="wallets",ge=class{constructor(){this.db=null}async init(){return new Promise((e,t)=>{let r=indexedDB.open(Vt,Qt);r.onerror=()=>t(new y("Failed to open database",r.error)),r.onsuccess=()=>{this.db=r.result,e()},r.onupgradeneeded=()=>{let n=r.result;n.objectStoreNames.contains(v)||n.createObjectStore(v,{keyPath:"ethereumAddress"})}})}async store(e){return this.db||await this.init(),new Promise((t,r)=>{let a=this.db.transaction([v],"readwrite").objectStore(v).put(e);a.onerror=()=>r(new y("Failed to store wallet data",a.error)),a.onsuccess=()=>t()})}async retrieve(e){return this.db||await this.init(),new Promise((t,r)=>{let a=this.db.transaction([v],"readonly").objectStore(v).get(e);a.onerror=()=>r(new y("Failed to retrieve wallet data",a.error)),a.onsuccess=()=>t(a.result||null)})}async delete(e){return this.db||await this.init(),new Promise((t,r)=>{let a=this.db.transaction([v],"readwrite").objectStore(v).delete(e);a.onerror=()=>r(new y("Failed to delete wallet data",a.error)),a.onsuccess=()=>t()})}async clear(){return this.db||await this.init(),new Promise((e,t)=>{let o=this.db.transaction([v],"readwrite").objectStore(v).clear();o.onerror=()=>t(new y("Failed to clear wallet data",o.error)),o.onsuccess=()=>e()})}};var te=require("ethers");w();function fe(){try{let s=te.ethers.Wallet.createRandom().mnemonic;if(!s)throw new Error("Failed to generate mnemonic");let e=s.phrase;return{address:te.ethers.HDNodeWallet.fromPhrase(e,void 0,"m/44'/60'/0'/0/0").address,mnemonic:e}}catch(s){throw new d("Wallet generation failed",s)}}function ct(s){try{if(!s||s.trim().split(/\s+/).length<12)throw new Error("Invalid mnemonic: must be at least 12 words");return te.ethers.HDNodeWallet.fromPhrase(s.trim(),void 0,"m/44'/60'/0'/0/0")}catch(e){throw new d(`Wallet creation failed: ${e instanceof Error?e.message:"Invalid mnemonic"}`,e)}}function we(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=te.ethers.HDNodeWallet.fromPhrase(s.trim(),void 0,t);return{address:r.address,privateKey:r.privateKey}}catch(t){throw new d(`HD wallet derivation failed: ${t instanceof Error?t.message:"Unknown error"}`,t)}}X();w();var g=require("ethers");w();function U(s){try{let e=g.ethers.HDNodeWallet.fromPhrase(s,void 0,"m/44'/60'/1'/0/0"),t=g.ethers.HDNodeWallet.fromPhrase(s,void 0,"m/44'/60'/1'/0/1"),r=t.signingKey.compressedPublicKey,n=e.signingKey.compressedPublicKey;return{stealthMetaAddress:r+n.slice(2),spendingPubKey:r,viewingPubKey:n,viewingKey:e.privateKey,spendingKey:t.privateKey}}catch(e){throw new h("Failed to derive stealth keys",e)}}function ve(s){try{let e="0x"+s.slice(2,68),t="0x"+s.slice(68),r=g.ethers.Wallet.createRandom(),n=r.signingKey.compressedPublicKey,o=Ue(r.privateKey,t),a=g.ethers.keccak256(o),i="0x"+a.slice(2,4),c=ht(e,pt(a));return{stealthAddress:yt(c),ephemeralPubKey:n,viewTag:i}}catch(e){throw new h("Failed to generate stealth address",e)}}function re(s,e,t,r,n){try{let o=Ue(s,t),a=g.ethers.keccak256(o);if(n&&("0x"+a.slice(2,4)).toLowerCase()!==n.toLowerCase())return{isForUser:!1};let i=ht(e,pt(a)),c=yt(i);return c.toLowerCase()!==r.toLowerCase()?{isForUser:!1}:{isForUser:!0,stealthAddress:c}}catch{return{isForUser:!1}}}function ne(s,e,t){try{let r=Ue(s,t),n=g.ethers.keccak256(r);return jt(e,n)}catch(r){throw new h("Failed to compute stealth private key",r)}}function ut(s,e,t,r,n,o){try{if(!re(s,t,r,n,o).isForUser)return!1;let i=ne(s,e,r);return new g.ethers.Wallet(i).address.toLowerCase()===n.toLowerCase()}catch{return!1}}function Ue(s,e){try{return new g.ethers.Wallet(s).signingKey.computeSharedSecret(e)}catch(t){throw new h("Failed to compute shared secret",t)}}function pt(s){try{return new g.ethers.Wallet(s).signingKey.compressedPublicKey}catch(e){throw new h("Failed to multiply generator by scalar",e)}}function ht(s,e){try{let t=g.ethers.SigningKey.computePublicKey(s,!1),r=g.ethers.SigningKey.computePublicKey(e,!1),n=BigInt("0x"+t.slice(4,68)),o=BigInt("0x"+t.slice(68)),a=BigInt("0x"+r.slice(4,68)),i=BigInt("0x"+r.slice(68)),c=BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");if(n===a&&o===i){let Dt=3n*n*n%c,Ft=2n*o%c,Be=Dt*lt(Ft,c)%c,et=(Be*Be-2n*n)%c,Mt=(Be*(n-et)-o)%c;return dt((et+c)%c,(Mt+c)%c)}let l=((i-o)%c+c)%c,p=((a-n)%c+c)%c,j=l*lt(p,c)%c,Ie=(j*j-n-a)%c,Tt=(j*(n-Ie)-o)%c;return dt((Ie+c)%c,(Tt+c)%c)}catch(t){throw new h("Failed to add public keys",t)}}function jt(s,e){try{let t=BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"),r=BigInt(s),n=BigInt(e);return"0x"+((r+n)%t).toString(16).padStart(64,"0")}catch(t){throw new h("Failed to add private keys",t)}}function dt(s,e){return"0x"+(e%2n===0n?"02":"03")+s.toString(16).padStart(64,"0")}function lt(s,e){s=(s%e+e)%e;let[t,r]=[s,e],[n,o]=[1n,0n];for(;r!==0n;){let a=t/r;[t,r]=[r,t-a*r],[n,o]=[o,n-a*o]}return(n%e+e)%e}function yt(s){try{let e=g.ethers.SigningKey.computePublicKey(s,!1),t=g.ethers.keccak256("0x"+e.slice(4));return g.ethers.getAddress("0x"+t.slice(-40))}catch(e){throw new h("Failed to derive address from public key",e)}}var O=class{constructor(e,t){this.getMnemonic=t}async generateStealthAddress(e){try{let t=await this.getMnemonic(e?.requireAuth),r=U(t),n=ve(r.stealthMetaAddress);return{stealthAddress:n.stealthAddress,ephemeralPublicKey:n.ephemeralPubKey,viewTag:n.viewTag}}catch(t){throw new m("Failed to generate stealth address","STEALTH_GENERATION_ERROR",t)}}async parseAnnouncement(e,t){try{let r=await this.getMnemonic(t?.requireAuth),n=U(r),o=re(n.viewingKey,n.spendingPubKey,e.ephemeralPublicKey,e.stealthAddress,e.viewTag);if(!o.isForUser)return{isForUser:!1};let a=ne(n.viewingKey,n.spendingKey,e.ephemeralPublicKey);return{isForUser:!0,stealthAddress:o.stealthAddress,stealthPrivateKey:a}}catch(r){throw new m("Failed to parse announcement","ANNOUNCEMENT_PARSE_ERROR",r)}}async scanAnnouncements(e,t){let r=[];for(let n of e){let o=await this.parseAnnouncement(n,t);o.isForUser&&r.push(o)}return r}async getKeys(e){try{let t=await this.getMnemonic(e?.requireAuth);return U(t)}catch(t){throw new m("Failed to get stealth keys","STEALTH_KEYS_ERROR",t)}}async getStealthMetaAddress(e){try{return(await this.getKeys(e)).stealthMetaAddress}catch(t){throw new m("Failed to get stealth meta-address","STEALTH_META_ADDRESS_ERROR",t)}}get isAvailable(){return!0}};var be=class{constructor(e=1){this.session=null;this.sessionDuration=e*60*60*1e3}startSession(e,t){let r=Date.now()+this.sessionDuration;this.session={mnemonic:e,expiresAt:r,credentialId:t}}getMnemonic(){return this.session?Date.now()>this.session.expiresAt?(this.clearSession(),null):this.session.mnemonic:null}getCredentialId(){return this.session?Date.now()>this.session.expiresAt?(this.clearSession(),null):this.session.credentialId:null}isActive(){return this.getMnemonic()!==null}getRemainingTime(){return this.session?Date.now()>this.session.expiresAt?(this.clearSession(),0):Math.floor((this.session.expiresAt-Date.now())/1e3):0}extendSession(){if(!this.session)throw new Error("No active session to extend");if(Date.now()>this.session.expiresAt)throw this.clearSession(),new Error("Session expired, cannot extend");this.session.expiresAt=Date.now()+this.sessionDuration}clearSession(){this.session&&(this.session.mnemonic="0".repeat(this.session.mnemonic.length)),this.session=null}setSessionDuration(e){this.sessionDuration=e*60*60*1e3}};var Oe={debug:!1,sessionDuration:1,onError:s=>{Oe.debug&&console.error("[w3pk]",s)}};w();var mt="https://chainid.network/chains.json";var Se=null,Jt=[/\$\{[\w_]+\}/i,/\{[\w_]+\}/i,/<[\w_]+>/i,/YOUR[-_]?API[-_]?KEY/i,/INSERT[-_]?API[-_]?KEY/i,/API[-_]?KEY[-_]?HERE/i];function zt(s){return Jt.some(e=>e.test(s))}async function Zt(s=mt){let e=await fetch(s);if(!e.ok)throw new Error(`Failed to fetch chains data: ${e.status} ${e.statusText}`);return await e.json()}async function Xt(s){let e=s?.chainsJsonUrl??mt,t=s?.cacheDuration??36e5,r=Date.now();if(Se&&r-Se.timestamp<t)return Se.data;let n=await Zt(e);return Se={data:n,timestamp:r},n}async function gt(s,e){let r=(await Xt(e)).find(n=>n.chainId===s);return r?r.rpc.filter(n=>!zt(n)&&!n.startsWith("wss://")&&!n.startsWith("ws://")):[]}var er=new Set([1,10,8453,42161,57073,100,42220,137,42,15,40,41,44,46,47,50,51,56,61,71,82,83,95,97,112,123,130,146,151,153,171,180,183,185,195,215,228,247,248,252,261,267,291,293,311,332,336,395,401,416,466,480,488,510,545,634,647,648,747,831,919,938,945,957,964,970,980,995,997,1001,1003,1024,1030,1114,1125,1135,1149,1188,1284,1285,1287,1300,1301,1315,1337,1338,1339,1424,1514,1687,1727,1729,1740,1750,1829,1868,1946,1961,1962,1969,1989,1995,2017,2020,2031,2043,2109,2241,2340,2345,2440,2522,2559,2649,3068,3109,3338,3502,3799,3888,3889,4e3,4048,4078,4162,4201,4202,4460,4488,4661,4689,4690,4888,5e3,5003,5124,5234,5330,5424,5522,6283,6342,6398,6678,6806,6934,6942,6969,7117,7171,7200,7208,7368,7518,7668,7672,7744,7771,7869,7897,8008,8118,8217,8408,8700,8726,8727,8844,8880,8881,8882,8889,9372,9496,9700,9745,9746,9899,9990,9996,10011,10085,10143,10200,11221,11501,11504,11891,13370,14853,16602,16661,17e3,18880,18881,19991,21e3,21816,21912,25327,32323,33401,34443,41923,42170,43111,44787,47805,48898,48900,49049,49088,5e4,50312,53302,53456,53457,55244,56288,59141,60808,60850,62320,62850,64002,71402,72080,73114,73115,75338,78281,80002,80008,80069,80094,80451,80931,84532,88899,91342,92278,94524,96970,97476,97477,98985,100021,100501,101010,102030,102031,102032,112358,120893,121212,121213,121214,121215,129399,161803,175188,192940,193939,198989,212013,222222,240241,325e3,355110,355113,421614,555777,560048,656476,713715,743111,747474,763373,763375,777777,806582,808813,810180,839999,888991,2019775,2222222,4278608,5734951,6666689,6985385,7080969,7777777,9999999,11142220,11155111,11155420,11155931,16969696,19850818,20180427,20250825,28122024,34949059,37084624,52164803,61022448,79479957,96969696,420420421,420420422,888888888,974399131,999999999,1020352220,1273227453,1313161560,1350216234,1380996178,1417429182,1444673419,1482601649,1564830818,2046399126,11297108099,11297108109,88153591557,123420000220,123420001114]);async function tr(s,e=1e4){try{let t=new AbortController,r=setTimeout(()=>t.abort(),e),n=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},signal:t.signal,body:JSON.stringify({jsonrpc:"2.0",method:"eth_estimateGas",params:[{from:"0xdeadbeef00000000000000000000000000000000",to:"0xdeadbeef00000000000000000000000000000000",data:"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",value:"0x0"},"latest",{"0xdeadbeef00000000000000000000000000000000":{code:"0xef01000000000000000000000000000000000000000001"}}],id:1})});if(clearTimeout(r),!n.ok)return!1;let o=await n.json();if(o.error){let a=(o.error.message||"").toLowerCase();return!["unsupported","not supported","unknown","invalid","unrecognized","does not support","not implemented"].some(c=>a.includes(c))}return o.result!==void 0}catch{return!1}}async function ft(s,e,t){if(er.has(s))return!0;let r=t?.maxEndpoints||3,n=t?.timeout||1e4;try{let o=await e(s);if(o.length===0)return!1;let a=o.slice(0,r);for(let i of a)if(await tr(i,n))return!0;return!1}catch{return!1}}var Q=class{constructor(e={}){this.currentUser=null;this.currentWallet=null;this.config={...Oe,...e},this.walletStorage=new ge,this.sessionManager=new be(e.sessionDuration||1),e.stealthAddresses!==void 0&&(this.stealth=new O(e.stealthAddresses,t=>this.getMnemonicFromSession(t)))}async loadZKModule(){if(this.zkModule)return this.zkModule;try{let e=new Function("path","return import(path)"),{ZKProofModule:t}=await e("w3pk/zk"),r=this.config.zkProofs||{};return this.zkModule=new t(r),this.zkModule}catch{throw new Error("ZK module not available. Install dependencies: npm install snarkjs circomlibjs")}}async getMnemonicFromSession(e=!1){if(!e){let l=this.sessionManager.getMnemonic();if(l)return l}if(!this.currentUser)throw new d("Must be authenticated. Call login() first.");let t=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!t)throw new d("No wallet found. Generate a wallet first.");if(!(await me()).user)throw new d("Authentication failed");let a=(await new(await Promise.resolve().then(()=>(I(),ee))).CredentialStorage().getCredentialById(t.credentialId))?.publicKey,i=await M(t.credentialId,a),c=await Z(t.encryptedMnemonic,i);return this.sessionManager.startSession(c,t.credentialId),c}async register(e){try{this.currentWallet?.address||await this.generateWallet();let t=this.currentWallet.address,r=this.currentWallet.mnemonic;await at({username:e.username,ethereumAddress:t}),this.currentUser={id:t,username:e.username,displayName:e.username,ethereumAddress:t};let o=await new(await Promise.resolve().then(()=>(I(),ee))).CredentialStorage().getCredentialByAddress(t);if(!o)throw new d("Credential not found after registration");let a=o.id,i=o.publicKey,c=await M(a,i),l=await z(r,c);return await this.walletStorage.store({ethereumAddress:this.currentUser.ethereumAddress,encryptedMnemonic:l,credentialId:a,createdAt:Date.now()}),this.sessionManager.startSession(r,a),this.currentWallet={address:t,mnemonic:r},this.config.onAuthStateChanged?.(!0,this.currentUser),{address:t,username:e.username}}catch(t){throw this.config.onError?.(t),t}}async login(){try{let e=await me();if(!e.verified||!e.user)throw new k("Login failed");this.currentUser={id:e.user.ethereumAddress,username:e.user.username,displayName:e.user.username,ethereumAddress:e.user.ethereumAddress};let t=await this.walletStorage.retrieve(this.currentUser.ethereumAddress);if(!t)throw new d("No wallet found for this user. You may need to register first.");let o=(await new(await Promise.resolve().then(()=>(I(),ee))).CredentialStorage().getCredentialById(t.credentialId))?.publicKey,a=await M(t.credentialId,o),i=await Z(t.encryptedMnemonic,a);return this.sessionManager.startSession(i,t.credentialId),this.config.onAuthStateChanged?.(!0,this.currentUser),this.currentUser}catch(e){throw this.config.onError?.(e),e}}async logout(){this.currentUser=null,this.currentWallet=null,this.sessionManager.clearSession(),this.config.onAuthStateChanged?.(!1,void 0)}get isAuthenticated(){return this.currentUser!==null}get user(){return this.currentUser}async generateWallet(){try{let e=fe();return this.currentWallet={address:e.address,mnemonic:e.mnemonic},{mnemonic:e.mnemonic}}catch(e){throw this.config.onError?.(e),new d("Failed to generate wallet",e)}}async deriveWallet(e,t){try{if(!this.currentUser)throw new d("Must be authenticated to derive wallet");let r=await this.getMnemonicFromSession(t?.requireAuth),n=we(r,e);return{address:n.address,privateKey:n.privateKey}}catch(r){throw this.config.onError?.(r),new d("Failed to derive wallet",r)}}async exportMnemonic(e){try{if(!this.currentUser)throw new d("Must be authenticated to export mnemonic");return await this.getMnemonicFromSession(e?.requireAuth)}catch(t){throw this.config.onError?.(t),new d("Failed to export mnemonic",t)}}async importMnemonic(e){try{if(!this.currentUser)throw new d("Must be authenticated to import mnemonic");if(!e||e.trim().split(/\s+/).length<12)throw new d("Invalid mnemonic: must be at least 12 words");let t=await me();if(!t.user)throw new d("Authentication failed");let r=t.user.credentialId,a=(await new(await Promise.resolve().then(()=>(I(),ee))).CredentialStorage().getCredentialById(r))?.publicKey,i=await M(r,a),c=await z(e.trim(),i);await this.walletStorage.store({ethereumAddress:this.currentUser.ethereumAddress,encryptedMnemonic:c,credentialId:r,createdAt:Date.now()}),this.currentWallet={address:this.currentUser.ethereumAddress,mnemonic:e.trim()},this.sessionManager.startSession(e.trim(),r)}catch(t){throw this.config.onError?.(t),new d("Failed to import mnemonic",t)}}async signMessage(e,t){try{if(!this.currentUser)throw new d("Must be authenticated to sign message");let r=await this.getMnemonicFromSession(t?.requireAuth),{Wallet:n}=await import("ethers");return await n.fromPhrase(r).signMessage(e)}catch(r){throw this.config.onError?.(r),new d("Failed to sign message",r)}}async getEndpoints(e){return gt(e)}async supportsEIP7702(e,t){return ft(e,this.getEndpoints.bind(this),t)}get zk(){return new Proxy({},{get:(e,t)=>async(...r)=>(await this.loadZKModule())[t](...r)})}async getBackupStatus(){if(!this.currentUser)throw new d("Must be authenticated to check backup status");let{BackupManager:e}=await Promise.resolve().then(()=>(B(),$));return new e().getBackupStatus(this.currentUser.ethereumAddress)}async createZipBackup(e,t){if(!this.currentUser)throw new d("Must be authenticated to create backup");let r=await this.getMnemonicFromSession(!0),{BackupManager:n}=await Promise.resolve().then(()=>(B(),$));return new n().createZipBackup(r,this.currentUser.ethereumAddress,{password:e,...t})}async createQRBackup(e,t){if(!this.currentUser)throw new d("Must be authenticated to create backup");let r=await this.getMnemonicFromSession(!0),{BackupManager:n}=await Promise.resolve().then(()=>(B(),$));return new n().createQRBackup(r,this.currentUser.ethereumAddress,{password:e,...t})}async setupSocialRecovery(e,t){if(!this.currentUser)throw new d("Must be authenticated to set up social recovery");let r=await this.getMnemonicFromSession(!0),{SocialRecoveryManager:n}=await Promise.resolve().then(()=>(oe(),Pe));return new n().setupSocialRecovery(r,this.currentUser.ethereumAddress,e,t)}async generateGuardianInvite(e){let{SocialRecoveryManager:t}=await Promise.resolve().then(()=>(oe(),Pe)),r=new t,n=r.getSocialRecoveryConfig();if(!n)throw new d("Social recovery not configured");let o=n.guardians.find(a=>a.id===e);if(!o)throw new d("Guardian not found");return r.generateGuardianInvite(o)}async recoverFromGuardians(e){let{SocialRecoveryManager:t}=await Promise.resolve().then(()=>(oe(),Pe));return new t().recoverFromGuardians(e)}async restoreFromBackup(e,t){let{BackupManager:r}=await Promise.resolve().then(()=>(B(),$));return new r().restoreFromZipBackup(e,t)}async restoreFromQR(e,t){let{BackupManager:r}=await Promise.resolve().then(()=>(B(),$));return new r().restoreFromQR(e,t)}async getSyncStatus(){let{DeviceManager:e}=await Promise.resolve().then(()=>(Ce(),Je));return new e().getSyncStatus()}async detectSyncCapabilities(){let{PlatformDetector:e}=await Promise.resolve().then(()=>(Ce(),Je));return new e().detectSyncCapabilities()}async simulateRecoveryScenario(e){if(!this.currentUser)throw new d("Must be authenticated to run recovery simulation");let t=await this.getBackupStatus(),{RecoverySimulator:r}=await Promise.resolve().then(()=>(ae(),xe));return new r().simulateScenario(e,t)}async runRecoveryTest(){if(!this.currentUser)throw new d("Must be authenticated to run recovery test");let e=await this.getBackupStatus(),{RecoverySimulator:t}=await Promise.resolve().then(()=>(ae(),xe));return new t().runInteractiveTest(e)}async getEducation(e){let{getExplainer:t}=await Promise.resolve().then(()=>(ae(),xe)),r=t(e);if(!r)throw new d(`Unknown education topic: ${e}`);return r}hasActiveSession(){return this.sessionManager.isActive()}getSessionRemainingTime(){return this.sessionManager.getRemainingTime()}extendSession(){try{this.sessionManager.extendSession()}catch(e){throw new d("Cannot extend session",e)}}clearSession(){this.sessionManager.clearSession()}setSessionDuration(e){this.sessionManager.setSessionDuration(e)}};w();B();oe();Ce();ae();function Bt(s={}){return new Q(s)}var nr=Bt;
777
777
  //# sourceMappingURL=index.js.map