{"version":3,"file":"wallet-manage-commands.mjs","names":[],"sources":["../../../src/commands/wallet-manage-commands.ts"],"sourcesContent":["/**\n * Wallet management commands — recover, export, and backup encrypted wallets.\n *\n * These commands work with the keychain-wallet service for local wallet\n * management (BIP-39 mnemonic + scrypt/AES-256-GCM encryption).\n */\n\nimport {\n  hasKeychainWallet,\n  loadAndDecrypt,\n  encryptAndStore,\n  exportBackupFile,\n  deleteKeychainWallet,\n  getStorageInfo,\n} from '../services/keychain-wallet.js';\n\n// ── /recover — Restore wallet from mnemonic ─────────────────────────────────\n\n/**\n * Two-phase command:\n * Phase 1: /recover (no args) — prompts for mnemonic\n * Phase 2: /recover <mnemonic> <password> — executes recovery\n *\n * In practice, the LLM agent will collect the mnemonic and password\n * from the user in conversation, then call this with args.\n */\nexport const recoverCommand = {\n  name: 'recover',\n  description: 'Restore wallet from a 12/24-word seed phrase. Usage: /recover <mnemonic words> | <password>',\n  acceptsArgs: true,\n  requireAuth: true,\n  handler: async (_ctx: any, args?: string) => {\n    if (!args || args.trim().length === 0) {\n      return {\n        text: 'To recover a wallet, provide your seed phrase and a new password separated by |.\\n\\n' +\n          'Usage: `/recover word1 word2 ... word12 | yourpassword`\\n\\n' +\n          '⚠️ **Security note**: Your seed phrase and password will appear in chat history. ' +\n          'For maximum security, use the onboarding flow (/create_wallet or /import_wallet) instead, ' +\n          'which handles sensitive input more carefully.\\n\\n' +\n          'The mnemonic will be encrypted and stored locally. ' +\n          (hasKeychainWallet() ? '⚠️ This will replace your existing local wallet.' : ''),\n      };\n    }\n\n    // Parse: mnemonic | password\n    const parts = args.split('|').map(s => s.trim());\n    if (parts.length < 2 || !parts[0] || !parts[1]) {\n      return {\n        text: 'Invalid format. Usage: `/recover word1 word2 ... word12 | yourpassword`',\n      };\n    }\n\n    const mnemonic = parts[0];\n    const password = parts[1];\n    const words = mnemonic.split(/\\s+/);\n\n    if (words.length !== 12 && words.length !== 24) {\n      return {\n        text: `Expected 12 or 24 words, got ${words.length}. Please provide a valid BIP-39 mnemonic.`,\n      };\n    }\n\n    if (password.length < 8) {\n      return { text: 'Password must be at least 8 characters.' };\n    }\n\n    try {\n      // Validate mnemonic by deriving account\n      const { mnemonicToAccount } = await import('viem/accounts');\n      const account = mnemonicToAccount(mnemonic);\n\n      // Delete existing wallet if present\n      if (hasKeychainWallet()) {\n        deleteKeychainWallet();\n      }\n\n      await encryptAndStore(mnemonic, password);\n      const storage = getStorageInfo();\n      const storageDesc = storage.backend === 'keychain'\n        ? 'macOS Keychain'\n        : `encrypted file (${storage.path})`;\n\n      return {\n        text: `Wallet recovered.\\n\\n` +\n          `Address: \\`${account.address}\\`\\n` +\n          `Storage: ${storageDesc}\\n\\n` +\n          `Restart the session or set \\`CLAWNCHER_WALLET_PASSWORD\\` to unlock automatically.`,\n      };\n    } catch (err) {\n      return {\n        text: `Recovery failed: ${err instanceof Error ? err.message : String(err)}`,\n      };\n    }\n  },\n};\n\n// ── /export_wallet — Display mnemonic (requires password) ───────────────────\n\nexport const exportWalletCommand = {\n  name: 'export_wallet',\n  description: 'Display your wallet mnemonic (requires password). Usage: /export_wallet <password>',\n  acceptsArgs: true,\n  requireAuth: true,\n  handler: async (_ctx: any, args?: string) => {\n    if (!hasKeychainWallet()) {\n      return {\n        text: 'No local wallet found. Use /create_wallet to create one or /recover to import.',\n      };\n    }\n\n    if (!args || args.trim().length === 0) {\n      return {\n        text: 'Usage: `/export_wallet <password>`\\n\\n' +\n          '⚠️ This will display your seed phrase. Make sure no one can see your screen.\\n' +\n          '⚠️ Your password will appear in chat history.',\n      };\n    }\n\n    const password = args.trim();\n\n    try {\n      const result = await loadAndDecrypt(password);\n\n      return {\n        text: `⚠️ **YOUR SEED PHRASE — DO NOT SHARE**\\n\\n` +\n          `\\`${result.mnemonic}\\`\\n\\n` +\n          `Address: \\`${result.address}\\`\\n\\n` +\n          `Write this down and store it safely. Anyone with these words can access your funds.`,\n      };\n    } catch (err) {\n      return {\n        text: `Export failed: ${err instanceof Error ? err.message : String(err)}`,\n      };\n    }\n  },\n};\n\n// ── /wallet_backup — Export encrypted backup file ───────────────────────────\n\nexport const walletBackupCommand = {\n  name: 'wallet_backup',\n  description: 'Export encrypted wallet backup file to ~/.openclawnch/',\n  acceptsArgs: true,\n  requireAuth: true,\n  handler: async (_ctx: any, args?: string) => {\n    if (!hasKeychainWallet()) {\n      return {\n        text: 'No local wallet found. Use /create_wallet to create one or /recover to import.',\n      };\n    }\n\n    try {\n      const outputDir = args?.trim() || undefined;\n      const backupPath = exportBackupFile(outputDir);\n\n      return {\n        text: `Encrypted backup saved to: \\`${backupPath}\\`\\n\\n` +\n          `This file is encrypted with your wallet password. ` +\n          `You can restore from it using /recover.`,\n      };\n    } catch (err) {\n      return {\n        text: `Backup failed: ${err instanceof Error ? err.message : String(err)}`,\n      };\n    }\n  },\n};\n"],"mappings":";;;;;;;;;;;;;;;;AA0BA,MAAa,iBAAiB;CAC5B,MAAM;CACN,aAAa;CACb,aAAa;CACb,aAAa;CACb,SAAS,OAAO,MAAW,SAAkB;AAC3C,MAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,WAAW,EAClC,QAAO,EACL,MAAM,oaAMH,mBAAmB,GAAG,qDAAqD,KAC/E;EAIH,MAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,KAAI,MAAK,EAAE,MAAM,CAAC;AAChD,MAAI,MAAM,SAAS,KAAK,CAAC,MAAM,MAAM,CAAC,MAAM,GAC1C,QAAO,EACL,MAAM,2EACP;EAGH,MAAM,WAAW,MAAM;EACvB,MAAM,WAAW,MAAM;EACvB,MAAM,QAAQ,SAAS,MAAM,MAAM;AAEnC,MAAI,MAAM,WAAW,MAAM,MAAM,WAAW,GAC1C,QAAO,EACL,MAAM,gCAAgC,MAAM,OAAO,4CACpD;AAGH,MAAI,SAAS,SAAS,EACpB,QAAO,EAAE,MAAM,2CAA2C;AAG5D,MAAI;GAEF,MAAM,EAAE,sBAAsB,MAAM,OAAO;GAC3C,MAAM,UAAU,kBAAkB,SAAS;AAG3C,OAAI,mBAAmB,CACrB,uBAAsB;AAGxB,SAAM,gBAAgB,UAAU,SAAS;GACzC,MAAM,UAAU,gBAAgB;GAChC,MAAM,cAAc,QAAQ,YAAY,aACpC,mBACA,mBAAmB,QAAQ,KAAK;AAEpC,UAAO,EACL,MAAM,mCACU,QAAQ,QAAQ,eAClB,YAAY,wFAE3B;WACM,KAAK;AACZ,UAAO,EACL,MAAM,oBAAoB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IAC3E;;;CAGN;AAID,MAAa,sBAAsB;CACjC,MAAM;CACN,aAAa;CACb,aAAa;CACb,aAAa;CACb,SAAS,OAAO,MAAW,SAAkB;AAC3C,MAAI,CAAC,mBAAmB,CACtB,QAAO,EACL,MAAM,kFACP;AAGH,MAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,WAAW,EAClC,QAAO,EACL,MAAM,qKAGP;EAGH,MAAM,WAAW,KAAK,MAAM;AAE5B,MAAI;GACF,MAAM,SAAS,MAAM,eAAe,SAAS;AAE7C,UAAO,EACL,MAAM,+CACC,OAAO,SAAS,mBACP,OAAO,QAAQ,4FAEhC;WACM,KAAK;AACZ,UAAO,EACL,MAAM,kBAAkB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACzE;;;CAGN;AAID,MAAa,sBAAsB;CACjC,MAAM;CACN,aAAa;CACb,aAAa;CACb,aAAa;CACb,SAAS,OAAO,MAAW,SAAkB;AAC3C,MAAI,CAAC,mBAAmB,CACtB,QAAO,EACL,MAAM,kFACP;AAGH,MAAI;AAIF,UAAO,EACL,MAAM,gCAHW,iBADD,MAAM,MAAM,IAAI,KAAA,EACY,CAGK,kGAGlD;WACM,KAAK;AACZ,UAAO,EACL,MAAM,kBAAkB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACzE;;;CAGN"}