{"version":3,"file":"yield-service.mjs","names":[],"sources":["../../../src/services/yield-service.ts"],"sourcesContent":["/**\n * Yield Aggregation Service — find and execute yield opportunities across DeFi.\n *\n * Data source: DeFiLlama yields API (yields.llama.fi/pools).\n * Execution: Yearn V3 vaults on Base (direct contract calls, no SDK).\n *\n * Supported protocols for deposits:\n *   - Yearn V3 vaults on Base (ERC-4626 standard)\n *   - Aave V3 on Base (via defi_lend tool — this service only searches)\n *\n * No new dependencies. Uses guardedFetch for HTTP, viem for contract calls.\n */\n\nimport { formatUnits, parseUnits } from 'viem';\nimport type { Address } from 'viem';\nimport { guardedFetch } from './endpoint-allowlist.js';\nimport { YEARN, TOKENS } from '../lib/contract-registry.js';\n\n// ── DeFiLlama Pool Types ─────────────────────────────────────────────────\n\nexport interface YieldPool {\n  pool: string;           // DeFiLlama pool ID\n  chain: string;          // \"Base\", \"Ethereum\", etc.\n  project: string;        // \"aave-v3\", \"yearn-finance\", \"moonwell\", etc.\n  symbol: string;         // \"USDC\", \"WETH-USDC\", etc.\n  tvlUsd: number;\n  apyBase: number | null;\n  apyReward: number | null;\n  apy: number;            // total APY (base + reward)\n  rewardTokens: string[] | null;\n  underlyingTokens: string[] | null;\n  ilRisk: string | null;  // \"yes\" | \"no\" | null\n  stablecoin: boolean;\n  exposure: string | null; // \"single\" | \"multi\"\n  poolMeta: string | null;\n  /** Vault address — from DeFiLlama or resolved locally */\n  vaultAddress?: string;\n}\n\nexport interface YieldSearchParams {\n  chain?: string;\n  asset?: string;\n  minTvl?: number;\n  minApy?: number;\n  stableOnly?: boolean;\n  singleExposure?: boolean;\n  limit?: number;\n  project?: string;\n}\n\nexport interface VaultPosition {\n  vault: string;\n  vaultAddress: string;\n  asset: string;\n  shares: string;\n  assetsValue: string;\n  chain: string;\n  apy?: number;\n}\n\n// ── Yearn V3 Vault Addresses (Base) ──────────────────────────────────────\n\nexport const YEARN_VAULTS_BASE: Record<string, { address: Address; asset: string; decimals: number }> = {\n  'yvUSDC': {\n    address: YEARN.base.yvUSDC,\n    asset: 'USDC',\n    decimals: 6,\n  },\n  'yvWETH': {\n    address: YEARN.base.yvWETH,\n    asset: 'WETH',\n    decimals: 18,\n  },\n  'yvDAI': {\n    address: YEARN.base.yvDAI,\n    asset: 'DAI',\n    decimals: 18,\n  },\n};\n\n// ── Underlying Token Addresses (Base) ────────────────────────────────────\n\nconst BASE_TOKENS: Record<string, Address> = {\n  USDC: TOKENS.base.USDC,\n  WETH: TOKENS.base.WETH,\n  DAI: TOKENS.base.DAI,\n};\n\n// ── ERC-4626 Vault ABI (minimal — standard interface) ────────────────────\n\nexport const ERC4626_ABI = [\n  {\n    name: 'deposit',\n    type: 'function',\n    stateMutability: 'nonpayable',\n    inputs: [\n      { name: 'assets', type: 'uint256' },\n      { name: 'receiver', type: 'address' },\n    ],\n    outputs: [{ name: 'shares', type: 'uint256' }],\n  },\n  {\n    name: 'withdraw',\n    type: 'function',\n    stateMutability: 'nonpayable',\n    inputs: [\n      { name: 'assets', type: 'uint256' },\n      { name: 'receiver', type: 'address' },\n      { name: 'owner', type: 'address' },\n    ],\n    outputs: [{ name: 'shares', type: 'uint256' }],\n  },\n  {\n    name: 'redeem',\n    type: 'function',\n    stateMutability: 'nonpayable',\n    inputs: [\n      { name: 'shares', type: 'uint256' },\n      { name: 'receiver', type: 'address' },\n      { name: 'owner', type: 'address' },\n    ],\n    outputs: [{ name: 'assets', type: 'uint256' }],\n  },\n  {\n    name: 'balanceOf',\n    type: 'function',\n    stateMutability: 'view',\n    inputs: [{ name: 'owner', type: 'address' }],\n    outputs: [{ name: '', type: 'uint256' }],\n  },\n  {\n    name: 'convertToAssets',\n    type: 'function',\n    stateMutability: 'view',\n    inputs: [{ name: 'shares', type: 'uint256' }],\n    outputs: [{ name: '', type: 'uint256' }],\n  },\n  {\n    name: 'convertToShares',\n    type: 'function',\n    stateMutability: 'view',\n    inputs: [{ name: 'assets', type: 'uint256' }],\n    outputs: [{ name: '', type: 'uint256' }],\n  },\n  {\n    name: 'maxDeposit',\n    type: 'function',\n    stateMutability: 'view',\n    inputs: [{ name: 'receiver', type: 'address' }],\n    outputs: [{ name: '', type: 'uint256' }],\n  },\n  {\n    name: 'totalAssets',\n    type: 'function',\n    stateMutability: 'view',\n    inputs: [],\n    outputs: [{ name: '', type: 'uint256' }],\n  },\n  {\n    name: 'asset',\n    type: 'function',\n    stateMutability: 'view',\n    inputs: [],\n    outputs: [{ name: '', type: 'address' }],\n  },\n] as const;\n\nconst ERC20_APPROVE_ABI = [\n  {\n    name: 'approve',\n    type: 'function',\n    stateMutability: 'nonpayable',\n    inputs: [\n      { name: 'spender', type: 'address' },\n      { name: 'amount', type: 'uint256' },\n    ],\n    outputs: [{ name: '', type: 'bool' }],\n  },\n  {\n    name: 'allowance',\n    type: 'function',\n    stateMutability: 'view',\n    inputs: [\n      { name: 'owner', type: 'address' },\n      { name: 'spender', type: 'address' },\n    ],\n    outputs: [{ name: '', type: 'uint256' }],\n  },\n] as const;\n\n// ── Chain Name Normalization ─────────────────────────────────────────────\n\nfunction normalizeChain(input: string): string {\n  const lower = input.toLowerCase();\n  const map: Record<string, string> = {\n    base: 'Base',\n    ethereum: 'Ethereum',\n    eth: 'Ethereum',\n    mainnet: 'Ethereum',\n    arbitrum: 'Arbitrum',\n    arb: 'Arbitrum',\n    optimism: 'Optimism',\n    op: 'Optimism',\n    polygon: 'Polygon',\n    matic: 'Polygon',\n  };\n  return map[lower] ?? input;\n}\n\n// ── Service ──────────────────────────────────────────────────────────────\n\nexport class YieldService {\n  private poolsCache: YieldPool[] = [];\n  private poolsCacheTimestamp = 0;\n  private readonly POOLS_CACHE_TTL = 300_000; // 5 minutes\n\n  // ── Search / Discovery ─────────────────────────────────────────────\n\n  /**\n   * Search DeFiLlama yield pools with optional filters.\n   * Returns top results sorted by APY descending.\n   */\n  async searchPools(params: YieldSearchParams = {}): Promise<YieldPool[]> {\n    const pools = await this.fetchPools();\n\n    let filtered = pools;\n\n    // Chain filter\n    if (params.chain) {\n      const normalizedChain = normalizeChain(params.chain);\n      filtered = filtered.filter(p => p.chain === normalizedChain);\n    }\n\n    // Asset filter (match in symbol)\n    if (params.asset) {\n      const upper = params.asset.toUpperCase();\n      filtered = filtered.filter(p => p.symbol.toUpperCase().includes(upper));\n    }\n\n    // Project filter\n    if (params.project) {\n      const lower = params.project.toLowerCase();\n      filtered = filtered.filter(p => p.project.toLowerCase().includes(lower));\n    }\n\n    // Min TVL filter (default: $100K to exclude dust pools)\n    const minTvl = params.minTvl ?? 100_000;\n    filtered = filtered.filter(p => p.tvlUsd >= minTvl);\n\n    // Min APY filter\n    if (params.minApy !== undefined) {\n      filtered = filtered.filter(p => p.apy >= params.minApy!);\n    }\n\n    // Stablecoin filter\n    if (params.stableOnly) {\n      filtered = filtered.filter(p => p.stablecoin);\n    }\n\n    // Single exposure filter (no IL risk)\n    if (params.singleExposure) {\n      filtered = filtered.filter(p => p.exposure === 'single' || p.ilRisk === 'no');\n    }\n\n    // Sort by APY descending\n    filtered.sort((a, b) => b.apy - a.apy);\n\n    // Limit results\n    const limit = params.limit ?? 20;\n    return filtered.slice(0, limit);\n  }\n\n  /**\n   * Get top yields for a specific asset on a specific chain.\n   */\n  async topYieldsForAsset(\n    asset: string,\n    chain = 'Base',\n    limit = 10,\n  ): Promise<YieldPool[]> {\n    return this.searchPools({\n      chain,\n      asset,\n      limit,\n      minTvl: 50_000,\n    });\n  }\n\n  // ── Vault Operations (Yearn V3 on Base) ────────────────────────────\n\n  /**\n   * Resolve a vault name or address to a known Yearn V3 vault.\n   */\n  resolveVault(input: string): { name: string; address: Address; asset: string; decimals: number } | null {\n    // Try by vault name\n    const upper = input.toUpperCase();\n    for (const [name, vault] of Object.entries(YEARN_VAULTS_BASE)) {\n      if (name.toUpperCase() === upper || vault.asset.toUpperCase() === upper) {\n        return { name, ...vault };\n      }\n    }\n\n    // Try by address\n    const lower = input.toLowerCase();\n    for (const [name, vault] of Object.entries(YEARN_VAULTS_BASE)) {\n      if (vault.address.toLowerCase() === lower) {\n        return { name, ...vault };\n      }\n    }\n\n    return null;\n  }\n\n  /**\n   * Get all known Yearn V3 vaults.\n   */\n  getAvailableVaults() {\n    return Object.entries(YEARN_VAULTS_BASE).map(([name, v]) => ({\n      name,\n      address: v.address,\n      asset: v.asset,\n      decimals: v.decimals,\n    }));\n  }\n\n  /**\n   * Deposit into a Yearn V3 vault (ERC-4626).\n   */\n  async deposit(\n    vaultAddress: Address,\n    assetAddress: Address,\n    amount: bigint,\n    userAddress: Address,\n    walletClient: any,\n    publicClient: any,\n  ): Promise<{ hash: string; shares: string }> {\n    // Ensure approval for vault to spend tokens\n    await this.ensureApproval(assetAddress, vaultAddress, amount, userAddress, walletClient, publicClient);\n\n    const hash = await walletClient.writeContract({\n      address: vaultAddress,\n      abi: ERC4626_ABI,\n      functionName: 'deposit',\n      args: [amount, userAddress],\n    });\n\n    const receipt = await publicClient.waitForTransactionReceipt({ hash });\n\n    // Try to read shares from receipt logs or vault balance\n    let shares = '0';\n    try {\n      const sharesBalance = await publicClient.readContract({\n        address: vaultAddress,\n        abi: ERC4626_ABI,\n        functionName: 'balanceOf',\n        args: [userAddress],\n      }) as bigint;\n      shares = sharesBalance.toString();\n    } catch {\n      // Non-critical — just can't report shares\n    }\n\n    return { hash, shares };\n  }\n\n  /**\n   * Withdraw from a Yearn V3 vault (ERC-4626).\n   * If isMax, redeems all shares. Otherwise withdraws specific asset amount.\n   */\n  async withdraw(\n    vaultAddress: Address,\n    amount: bigint,\n    userAddress: Address,\n    walletClient: any,\n    publicClient: any,\n    isMax: boolean,\n    decimals: number,\n  ): Promise<{ hash: string; assetsReturned: string }> {\n    let hash: string;\n\n    if (isMax) {\n      // Redeem all shares\n      const sharesBalance = await publicClient.readContract({\n        address: vaultAddress,\n        abi: ERC4626_ABI,\n        functionName: 'balanceOf',\n        args: [userAddress],\n      }) as bigint;\n\n      if (sharesBalance === 0n) {\n        throw new Error('No shares to redeem in this vault.');\n      }\n\n      hash = await walletClient.writeContract({\n        address: vaultAddress,\n        abi: ERC4626_ABI,\n        functionName: 'redeem',\n        args: [sharesBalance, userAddress, userAddress],\n      });\n    } else {\n      // Withdraw specific amount of underlying assets\n      hash = await walletClient.writeContract({\n        address: vaultAddress,\n        abi: ERC4626_ABI,\n        functionName: 'withdraw',\n        args: [amount, userAddress, userAddress],\n      });\n    }\n\n    await publicClient.waitForTransactionReceipt({ hash });\n\n    return { hash, assetsReturned: isMax ? 'all' : formatUnits(amount, decimals) };\n  }\n\n  /**\n   * Get vault positions for a user across all known vaults.\n   */\n  async getPositions(\n    userAddress: Address,\n    publicClient: any,\n  ): Promise<VaultPosition[]> {\n    const positions: VaultPosition[] = [];\n\n    for (const [name, vault] of Object.entries(YEARN_VAULTS_BASE)) {\n      try {\n        const sharesBalance = await publicClient.readContract({\n          address: vault.address,\n          abi: ERC4626_ABI,\n          functionName: 'balanceOf',\n          args: [userAddress],\n        }) as bigint;\n\n        if (sharesBalance === 0n) continue;\n\n        // Convert shares to underlying asset value\n        let assetsValue: bigint;\n        try {\n          assetsValue = await publicClient.readContract({\n            address: vault.address,\n            abi: ERC4626_ABI,\n            functionName: 'convertToAssets',\n            args: [sharesBalance],\n          }) as bigint;\n        } catch {\n          assetsValue = sharesBalance; // fallback: 1:1\n        }\n\n        positions.push({\n          vault: name,\n          vaultAddress: vault.address,\n          asset: vault.asset,\n          shares: formatUnits(sharesBalance, vault.decimals),\n          assetsValue: formatUnits(assetsValue, vault.decimals),\n          chain: 'base',\n        });\n      } catch {\n        // Skip vault if contract call fails\n      }\n    }\n\n    // Enrich with APY from DeFiLlama\n    await this.enrichPositionsWithApy(positions);\n\n    return positions;\n  }\n\n  /**\n   * Get the underlying token address for a vault's asset.\n   */\n  getTokenAddress(asset: string): Address | null {\n    return BASE_TOKENS[asset.toUpperCase()] ?? null;\n  }\n\n  // ── Internal ───────────────────────────────────────────────────────\n\n  private async fetchPools(): Promise<YieldPool[]> {\n    if (this.poolsCache.length > 0 && Date.now() - this.poolsCacheTimestamp < this.POOLS_CACHE_TTL) {\n      return this.poolsCache;\n    }\n\n    try {\n      const response = await guardedFetch('https://yields.llama.fi/pools', {\n        headers: { Accept: 'application/json' },\n        signal: AbortSignal.timeout(15_000),\n      });\n\n      if (!response.ok) {\n        return this.poolsCache;\n      }\n\n      const data: any = await response.json();\n      const rawPools: any[] = data.data ?? [];\n\n      this.poolsCache = rawPools.map((p: any) => ({\n        pool: p.pool ?? '',\n        chain: p.chain ?? '',\n        project: p.project ?? '',\n        symbol: p.symbol ?? '',\n        tvlUsd: p.tvlUsd ?? 0,\n        apyBase: p.apyBase ?? null,\n        apyReward: p.apyReward ?? null,\n        apy: p.apy ?? p.apyBase ?? 0,\n        rewardTokens: p.rewardTokens ?? null,\n        underlyingTokens: p.underlyingTokens ?? null,\n        ilRisk: p.ilRisk ?? null,\n        stablecoin: p.stablecoin ?? false,\n        exposure: p.exposure ?? null,\n        poolMeta: p.poolMeta ?? null,\n      }));\n\n      this.poolsCacheTimestamp = Date.now();\n      return this.poolsCache;\n    } catch {\n      return this.poolsCache;\n    }\n  }\n\n  private async enrichPositionsWithApy(positions: VaultPosition[]): Promise<void> {\n    if (positions.length === 0) return;\n\n    const pools = await this.fetchPools();\n\n    for (const pos of positions) {\n      // Find matching DeFiLlama pool for this vault\n      const match = pools.find(\n        p =>\n          p.chain === 'Base' &&\n          p.project.includes('yearn') &&\n          p.symbol.toUpperCase().includes(pos.asset.toUpperCase()),\n      );\n      if (match) {\n        pos.apy = match.apy;\n      }\n    }\n  }\n\n  private async ensureApproval(\n    tokenAddress: Address,\n    spender: Address,\n    amount: bigint,\n    owner: Address,\n    walletClient: any,\n    publicClient: any,\n  ): Promise<void> {\n    const currentAllowance = await publicClient.readContract({\n      address: tokenAddress,\n      abi: ERC20_APPROVE_ABI,\n      functionName: 'allowance',\n      args: [owner, spender],\n    }) as bigint;\n\n    if (currentAllowance < amount) {\n      const approveHash = await walletClient.writeContract({\n        address: tokenAddress,\n        abi: ERC20_APPROVE_ABI,\n        functionName: 'approve',\n        args: [spender, amount],\n      });\n      await publicClient.waitForTransactionReceipt({ hash: approveHash });\n    }\n  }\n}\n\n// ── Singleton ────────────────────────────────────────────────────────────\n\nlet _instance: YieldService | null = null;\n\nexport function getYieldService(): YieldService {\n  if (!_instance) {\n    _instance = new YieldService();\n  }\n  return _instance;\n}\n\nexport function resetYieldService(): void {\n  _instance = null;\n}\n"],"mappings":"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"}