{"version":3,"file":"defi-lend.mjs","names":[],"sources":["../../../src/tools/defi-lend.ts"],"sourcesContent":["/**\n * DeFi Lending Tool — supply, borrow, repay, withdraw on Aave V3 (Base).\n *\n * Actions:\n * - supply: Deposit assets as collateral to earn interest\n * - borrow: Borrow assets against your collateral\n * - repay: Repay borrowed assets\n * - withdraw: Withdraw supplied assets\n * - health_factor: Check your health factor and liquidation risk\n * - positions: View all active supply/borrow positions\n * - rates: View current supply/borrow APYs\n */\n\nimport { Type } from '@sinclair/typebox';\nimport { stringEnum, jsonResult, errorResult, readStringParam, readNumberParam } from '../lib/tool-helpers.js';\nimport {\n  getWalletState,\n  requireWalletClient,\n  requirePublicClient,\n} from '../services/walletconnect-service.js';\nimport { getLendingService } from '../services/lending-service.js';\nimport { resolveAddressOrEns, isEnsName } from '../lib/ens-resolver.js';\n\nconst ACTIONS = ['supply', 'borrow', 'repay', 'withdraw', 'health_factor', 'positions', 'rates'] as const;\n\nconst DefiLendSchema = Type.Object({\n  action: stringEnum(ACTIONS, {\n    description:\n      'supply: deposit assets as collateral. borrow: borrow against collateral. ' +\n      'repay: repay borrowed assets. withdraw: withdraw supplied assets. ' +\n      'health_factor: check liquidation risk. positions: view active positions. ' +\n      'rates: view current APYs.',\n  }),\n  asset: Type.Optional(Type.String({\n    description: 'Asset symbol (ETH, USDC, cbETH, USDbC) or contract address. Required for supply/borrow/repay/withdraw.',\n  })),\n  amount: Type.Optional(Type.String({\n    description: 'Amount in human-readable units (e.g. \"100\" for 100 USDC, \"0.5\" for 0.5 ETH). Use \"max\" to repay/withdraw entire balance.',\n  })),\n  protocol: Type.Optional(Type.String({\n    description: 'Lending protocol. Currently only \"aave\" (Aave V3 on Base) is supported.',\n  })),\n  address: Type.Optional(Type.String({\n    description: 'Wallet address or ENS name to check positions/health for. Defaults to connected wallet.',\n  })),\n});\n\nexport function createDefiLendTool() {\n  return {\n    name: 'defi_lend',\n    label: 'DeFi Lending',\n    ownerOnly: true,\n    description:\n      'Supply, borrow, repay, and withdraw on Aave V3 on Base. ' +\n      'Check health factor to monitor liquidation risk. View positions and current APYs. ' +\n      'All write operations go through ClawnchConnect for approval.',\n    parameters: DefiLendSchema,\n    execute: async (_toolCallId: string, args: unknown) => {\n      const params = args as Record<string, unknown>;\n      const action = readStringParam(params, 'action', { required: true })!;\n\n      // Protocol validation — only Aave V3 is currently supported\n      const protocol = readStringParam(params, 'protocol');\n      if (protocol && protocol.toLowerCase() !== 'aave') {\n        return errorResult(`Protocol \"${protocol}\" is not yet supported. Currently only Aave V3 on Base is available.`);\n      }\n\n      switch (action) {\n        case 'supply':\n          return handleSupply(params);\n        case 'borrow':\n          return handleBorrow(params);\n        case 'repay':\n          return handleRepay(params);\n        case 'withdraw':\n          return handleWithdraw(params);\n        case 'health_factor':\n          return handleHealthFactor(params);\n        case 'positions':\n          return handlePositions(params);\n        case 'rates':\n          return handleRates();\n        default:\n          return errorResult(`Unknown action: ${action}. Use: supply, borrow, repay, withdraw, health_factor, positions, rates`);\n      }\n    },\n  };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction parseAmount(amount: string, decimals: number): bigint {\n  // Input validation\n  const trimmed = amount.trim();\n  if (!trimmed) {\n    throw new Error('Amount cannot be empty.');\n  }\n  if (!/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n    throw new Error(`Invalid amount \"${trimmed}\". Must be a positive number (e.g. \"100\", \"0.5\").`);\n  }\n\n  const parts = trimmed.split('.');\n  const whole = parts[0] ?? '0';\n  let fraction = parts[1] ?? '';\n  if (fraction.length > decimals) {\n    fraction = fraction.slice(0, decimals);\n  } else {\n    fraction = fraction.padEnd(decimals, '0');\n  }\n  const result = BigInt(whole + fraction);\n  if (result === 0n) {\n    throw new Error('Amount must be greater than zero.');\n  }\n  return result;\n}\n\nasync function resolveAddress(params: Record<string, unknown>): Promise<string> {\n  const addressInput = readStringParam(params, 'address');\n  if (!addressInput) {\n    const state = getWalletState();\n    if (!state.connected || !state.address) {\n      throw new Error('No wallet connected and no address provided.');\n    }\n    return state.address;\n  }\n  if (isEnsName(addressInput)) {\n    const publicClient = requirePublicClient();\n    const resolved = await resolveAddressOrEns(addressInput, publicClient);\n    return resolved.address;\n  }\n  return addressInput;\n}\n\n/**\n * Check if the user is trying to use native ETH where WETH is needed.\n * Aave works with WETH (ERC-20), not native ETH. Return a clear error message.\n */\nfunction checkNativeEthWarning(assetInput: string, asset: { symbol: string }): string | null {\n  if (asset.symbol === 'ETH' && assetInput.toUpperCase() === 'ETH') {\n    return (\n      'Note: Aave uses WETH (wrapped ETH), not native ETH. ' +\n      'If you have native ETH, wrap it first using a swap (swap 0 ETH for WETH) ' +\n      'or use the \"Wrap ETH\" option. If you already have WETH, this will work as expected.'\n    );\n  }\n  return null;\n}\n\n// ── Action Handlers ──────────────────────────────────────────────────────\n\nasync function handleSupply(params: Record<string, unknown>) {\n  const assetInput = readStringParam(params, 'asset', { required: true });\n  const amountInput = readStringParam(params, 'amount', { required: true });\n  if (!assetInput || !amountInput) {\n    return errorResult('Both asset and amount are required for supply.');\n  }\n\n  const state = getWalletState();\n  if (!state.connected || !state.address) {\n    return errorResult('No wallet connected. Connect a wallet first.');\n  }\n\n  const service = getLendingService();\n  const asset = service.resolveAsset(assetInput);\n  if (!asset) {\n    const supported = service.getSupportedAssets().map(a => a.symbol).join(', ');\n    return errorResult(`Unknown asset: \"${assetInput}\". Supported: ${supported}`);\n  }\n\n  try {\n    const amount = parseAmount(amountInput, asset.decimals);\n    const wallet = requireWalletClient();\n    const publicClient = requirePublicClient();\n\n    const result = await service.supply(\n      asset, amount, state.address as `0x${string}`, wallet, publicClient,\n    );\n\n    // Get updated health factor\n    const accountData = await service.getUserAccountData(\n      state.address as `0x${string}`, publicClient,\n    );\n\n    const { formatUnits } = await import('viem');\n\n    return jsonResult({\n      status: 'success',\n      action: 'supply',\n      protocol: 'aave',\n      asset: asset.symbol,\n      amount: formatUnits(amount, asset.decimals),\n      txHash: result.hash,\n      healthFactor: accountData.healthFactor === Infinity ? 'safe (no debt)' : accountData.healthFactor.toFixed(4),\n      totalCollateralUsd: accountData.totalCollateralUsd.toFixed(2),\n    });\n  } catch (err) {\n    const ethNote = checkNativeEthWarning(assetInput, asset);\n    const errMsg = `Supply failed: ${err instanceof Error ? err.message : String(err)}`;\n    return errorResult(ethNote ? `${errMsg}\\n\\n${ethNote}` : errMsg);\n  }\n}\n\nasync function handleBorrow(params: Record<string, unknown>) {\n  const assetInput = readStringParam(params, 'asset', { required: true });\n  const amountInput = readStringParam(params, 'amount', { required: true });\n  if (!assetInput || !amountInput) {\n    return errorResult('Both asset and amount are required for borrow.');\n  }\n\n  const state = getWalletState();\n  if (!state.connected || !state.address) {\n    return errorResult('No wallet connected. Connect a wallet first.');\n  }\n\n  const service = getLendingService();\n  const asset = service.resolveAsset(assetInput);\n  if (!asset) {\n    const supported = service.getSupportedAssets().map(a => a.symbol).join(', ');\n    return errorResult(`Unknown asset: \"${assetInput}\". Supported: ${supported}`);\n  }\n\n  try {\n    // Pre-flight: check health factor\n    const publicClient = requirePublicClient();\n    const preCheck = await service.getUserAccountData(\n      state.address as `0x${string}`, publicClient,\n    );\n\n    if (preCheck.totalCollateralUsd === 0) {\n      return errorResult('No collateral supplied. Supply assets first before borrowing.');\n    }\n\n    const amount = parseAmount(amountInput, asset.decimals);\n        const wallet = requireWalletClient();\n\n        const result = await service.borrow(\n          asset, amount, state.address as `0x${string}`, wallet, publicClient,\n        );\n\n    // Get updated health factor\n    const postCheck = await service.getUserAccountData(\n      state.address as `0x${string}`, publicClient,\n    );\n\n    const { formatUnits } = await import('viem');\n    const healthWarning = postCheck.healthFactor < 1.5\n      ? ' ⚠️ Health factor is low — risk of liquidation!'\n      : '';\n\n    return jsonResult({\n      status: 'success',\n      action: 'borrow',\n      protocol: 'aave',\n      asset: asset.symbol,\n      amount: formatUnits(amount, asset.decimals),\n      txHash: result.hash,\n      healthFactor: postCheck.healthFactor.toFixed(4),\n      healthWarning: healthWarning || undefined,\n      totalDebtUsd: postCheck.totalDebtUsd.toFixed(2),\n    });\n  } catch (err) {\n    return errorResult(`Borrow failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handleRepay(params: Record<string, unknown>) {\n  const assetInput = readStringParam(params, 'asset', { required: true });\n  const amountInput = readStringParam(params, 'amount', { required: true });\n  if (!assetInput || !amountInput) {\n    return errorResult('Both asset and amount are required for repay.');\n  }\n\n  const state = getWalletState();\n  if (!state.connected || !state.address) {\n    return errorResult('No wallet connected. Connect a wallet first.');\n  }\n\n  const service = getLendingService();\n  const asset = service.resolveAsset(assetInput);\n  if (!asset) {\n    const supported = service.getSupportedAssets().map(a => a.symbol).join(', ');\n    return errorResult(`Unknown asset: \"${assetInput}\". Supported: ${supported}`);\n  }\n\n  try {\n    const isMax = amountInput.toLowerCase() === 'max';\n    const wallet = requireWalletClient();\n    const publicClient = requirePublicClient();\n\n    let amount: bigint;\n    if (isMax) {\n      // Query actual debt balance instead of using MaxUint256 for approval.\n      // Aave's repay() accepts MaxUint256 to mean \"repay all\", but we only\n      // approve the actual debt + 0.5% buffer (for interest accruing between\n      // the approval and repay txs). This avoids granting unlimited approval.\n      const debtBalance = await service.getDebtBalance(\n        asset, state.address as `0x${string}`, publicClient,\n      );\n      if (debtBalance === 0n) {\n        return errorResult(`No outstanding ${asset.symbol} debt to repay.`);\n      }\n      // Approve debt + 0.5% buffer; pass MaxUint256 to Aave's repay() itself\n      // (Aave contract interprets MaxUint256 as \"repay full balance\")\n      const approvalAmount = debtBalance + (debtBalance / 200n); // +0.5%\n      await service.ensureApprovalPublic(\n        asset.address, approvalAmount, state.address as `0x${string}`, wallet, publicClient,\n      );\n      amount = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');\n    } else {\n      amount = parseAmount(amountInput, asset.decimals);\n    }\n\n    const result = await service.repay(\n      asset, amount, state.address as `0x${string}`, wallet, publicClient, isMax,\n    );\n\n    const postCheck = await service.getUserAccountData(\n      state.address as `0x${string}`, publicClient,\n    );\n\n    return jsonResult({\n      status: 'success',\n      action: 'repay',\n      protocol: 'aave',\n      asset: asset.symbol,\n      amount: isMax ? 'max (entire debt)' : amountInput,\n      txHash: result.hash,\n      healthFactor: postCheck.healthFactor === Infinity ? 'safe (no debt)' : postCheck.healthFactor.toFixed(4),\n      remainingDebtUsd: postCheck.totalDebtUsd.toFixed(2),\n    });\n  } catch (err) {\n    const ethNote = checkNativeEthWarning(assetInput, asset);\n    const errMsg = `Repay failed: ${err instanceof Error ? err.message : String(err)}`;\n    return errorResult(ethNote ? `${errMsg}\\n\\n${ethNote}` : errMsg);\n  }\n}\n\nasync function handleWithdraw(params: Record<string, unknown>) {\n  const assetInput = readStringParam(params, 'asset', { required: true });\n  const amountInput = readStringParam(params, 'amount', { required: true });\n  if (!assetInput || !amountInput) {\n    return errorResult('Both asset and amount are required for withdraw.');\n  }\n\n  const state = getWalletState();\n  if (!state.connected || !state.address) {\n    return errorResult('No wallet connected. Connect a wallet first.');\n  }\n\n  const service = getLendingService();\n  const asset = service.resolveAsset(assetInput);\n  if (!asset) {\n    const supported = service.getSupportedAssets().map(a => a.symbol).join(', ');\n    return errorResult(`Unknown asset: \"${assetInput}\". Supported: ${supported}`);\n  }\n\n  try {\n    const isMax = amountInput.toLowerCase() === 'max';\n    const amount = isMax\n      ? BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')\n      : parseAmount(amountInput, asset.decimals);\n\n    const wallet = requireWalletClient();\n    const publicClient = requirePublicClient();\n\n    const result = await service.withdraw(\n      asset, amount, state.address as `0x${string}`, wallet, publicClient,\n    );\n    const postCheck = await service.getUserAccountData(\n      state.address as `0x${string}`, publicClient,\n    );\n\n    const healthWarning = postCheck.healthFactor !== Infinity && postCheck.healthFactor < 1.5\n      ? ' ⚠️ Health factor dropped — monitor closely!'\n      : '';\n\n    return jsonResult({\n      status: 'success',\n      action: 'withdraw',\n      protocol: 'aave',\n      asset: asset.symbol,\n      amount: isMax ? 'max (entire balance)' : amountInput,\n      txHash: result.hash,\n      healthFactor: postCheck.healthFactor === Infinity ? 'safe (no debt)' : postCheck.healthFactor.toFixed(4),\n      healthWarning: healthWarning || undefined,\n    });\n  } catch (err) {\n    return errorResult(`Withdraw failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handleHealthFactor(params: Record<string, unknown>) {\n  try {\n    const address = await resolveAddress(params);\n    const publicClient = requirePublicClient();\n    const service = getLendingService();\n\n    const data = await service.getUserAccountData(address as `0x${string}`, publicClient);\n\n    let status: string;\n    if (data.healthFactor === Infinity) {\n      status = 'safe — no outstanding debt';\n    } else if (data.healthFactor > 2.0) {\n      status = 'healthy';\n    } else if (data.healthFactor > 1.5) {\n      status = 'moderate — consider adding collateral or repaying debt';\n    } else if (data.healthFactor > 1.1) {\n      status = 'WARNING — approaching liquidation zone';\n    } else {\n      status = 'DANGER — immediate liquidation risk!';\n    }\n\n    return jsonResult({\n      protocol: 'aave',\n      address,\n      healthFactor: data.healthFactor === Infinity ? 'Infinity (no debt)' : data.healthFactor.toFixed(4),\n      status,\n      totalCollateralUsd: data.totalCollateralUsd.toFixed(2),\n      totalDebtUsd: data.totalDebtUsd.toFixed(2),\n      availableBorrowsUsd: data.availableBorrowsUsd.toFixed(2),\n      ltvPercent: data.ltv.toFixed(1),\n      liquidationThresholdPercent: data.liquidationThreshold.toFixed(1),\n    });\n  } catch (err) {\n    return errorResult(`Health factor check failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handlePositions(params: Record<string, unknown>) {\n  try {\n    const address = await resolveAddress(params);\n    const publicClient = requirePublicClient();\n    const service = getLendingService();\n    const { formatUnits, erc20Abi } = await import('viem');\n\n    const accountData = await service.getUserAccountData(address as `0x${string}`, publicClient);\n    const assets = service.getSupportedAssets();\n\n    // Check aToken balances (supply positions) and debt token balances (borrow positions)\n    const positions: Array<{\n      asset: string;\n      type: 'supply' | 'borrow';\n      balance: string;\n    }> = [];\n\n    for (const asset of assets) {\n      // Check supply (aToken balance)\n      if (asset.aToken) {\n        try {\n          const balance = await publicClient.readContract({\n            address: asset.aToken,\n            abi: erc20Abi,\n            functionName: 'balanceOf',\n            args: [address as `0x${string}`],\n          }) as bigint;\n          if (balance > 0n) {\n            positions.push({\n              asset: asset.symbol,\n              type: 'supply',\n              balance: formatUnits(balance, asset.decimals),\n            });\n          }\n        } catch { /* skip if contract call fails */ }\n      }\n\n      // Check borrow (variable debt token balance)\n      if (asset.variableDebtToken) {\n        try {\n          const balance = await publicClient.readContract({\n            address: asset.variableDebtToken,\n            abi: erc20Abi,\n            functionName: 'balanceOf',\n            args: [address as `0x${string}`],\n          }) as bigint;\n          if (balance > 0n) {\n            positions.push({\n              asset: asset.symbol,\n              type: 'borrow',\n              balance: formatUnits(balance, asset.decimals),\n            });\n          }\n        } catch { /* skip if contract call fails */ }\n      }\n    }\n\n    return jsonResult({\n      protocol: 'aave',\n      address,\n      positions,\n      summary: {\n        totalCollateralUsd: accountData.totalCollateralUsd.toFixed(2),\n        totalDebtUsd: accountData.totalDebtUsd.toFixed(2),\n        healthFactor: accountData.healthFactor === Infinity ? 'safe (no debt)' : accountData.healthFactor.toFixed(4),\n        netPositionUsd: (accountData.totalCollateralUsd - accountData.totalDebtUsd).toFixed(2),\n      },\n    });\n  } catch (err) {\n    return errorResult(`Positions check failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handleRates() {\n  const service = getLendingService();\n  const assets = service.getSupportedAssets();\n  const protocols = service.getSupportedProtocols();\n\n  // Try to fetch live APY data from DeFiLlama\n  let liveRates: Array<{ symbol: string; supplyApy: number; borrowApy: number; tvl: number }> = [];\n  try {\n    const res = await fetch('https://yields.llama.fi/pools');\n    if (res.ok) {\n      const data = (await res.json()) as { data: Array<{ project: string; chain: string; symbol: string; apy: number; apyBorrow: number; tvlUsd: number }> };\n      liveRates = data.data\n        .filter(p => p.project === 'aave-v3' && p.chain === 'Base')\n        .map(p => ({\n          symbol: p.symbol,\n          supplyApy: Math.round(p.apy * 100) / 100,\n          borrowApy: Math.round((p.apyBorrow ?? 0) * 100) / 100,\n          tvl: Math.round(p.tvlUsd),\n        }));\n    }\n  } catch {\n    // Fall back to static list\n  }\n\n  if (liveRates.length > 0) {\n    return jsonResult({\n      source: 'DeFiLlama (live)',\n      protocol: 'Aave V3',\n      chain: 'Base',\n      rates: liveRates,\n    });\n  }\n\n  return jsonResult({\n    notice: 'Could not fetch live APY data. Showing supported assets and protocols.',\n    protocols: protocols.map(p => ({ id: p.id, name: p.name, chain: p.chain })),\n    supportedAssets: assets.map(a => ({\n      symbol: a.symbol,\n      address: a.address,\n    })),\n    tip: 'Try again later for live rates, or ask me to check DeFiLlama yields for Aave V3 on Base.',\n  });\n}\n"],"mappings":"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"}