{"version":3,"file":"nft.mjs","names":[],"sources":["../../../src/tools/nft.ts"],"sourcesContent":["/**\n * NFT Tool — view, transfer, buy, list, and manage NFTs.\n *\n * Actions:\n *   view             — View NFT metadata, image, attributes\n *   transfer         — Transfer an NFT to another address\n *   buy              — Buy an NFT listed on marketplaces\n *   list             — List an NFT for sale\n *   collection_floor — Get collection floor price and stats\n *   portfolio        — View all NFTs owned by an address\n *\n * Uses Reservoir API (covers OpenSea, Blur, LooksRare).\n * Requires RESERVOIR_API_KEY env var.\n */\n\nimport { Type } from '@sinclair/typebox';\nimport { parseEther } from 'viem';\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 { getNftService, ERC721_TRANSFER_ABI } from '../services/nft-service.js';\nimport { resolveAddressOrEns, isEnsName } from '../lib/ens-resolver.js';\n\nconst ACTIONS = ['view', 'transfer', 'buy', 'list', 'collection_floor', 'portfolio'] as const;\n\nconst NftSchema = Type.Object({\n  action: stringEnum(ACTIONS, {\n    description:\n      'view: NFT metadata and attributes. transfer: send NFT to address. ' +\n      'buy: purchase listed NFT. list: list NFT for sale. ' +\n      'collection_floor: floor price and stats. portfolio: all owned NFTs.',\n  }),\n  contract: Type.Optional(Type.String({\n    description: 'NFT contract address (0x...). Required for view, transfer, buy, list.',\n  })),\n  token_id: Type.Optional(Type.String({\n    description: 'Token ID within the collection. Required for view, transfer, buy, list.',\n  })),\n  to: Type.Optional(Type.String({\n    description: 'Recipient address or ENS name. Required for transfer.',\n  })),\n  price: Type.Optional(Type.String({\n    description: 'Listing price in ETH (e.g. \"0.5\"). Required for list.',\n  })),\n  collection: Type.Optional(Type.String({\n    description: 'Collection contract address or slug. Required for collection_floor.',\n  })),\n  chain: Type.Optional(Type.String({\n    description: 'Chain: \"base\" (default), \"ethereum\", \"arbitrum\", \"optimism\", \"polygon\".',\n  })),\n  address: Type.Optional(Type.String({\n    description: 'Wallet address for portfolio. Defaults to connected wallet.',\n  })),\n  limit: Type.Optional(Type.Number({\n    description: 'Max results for portfolio. Default: 50.',\n  })),\n});\n\nexport function createNftTool() {\n  return {\n    name: 'nft',\n    label: 'NFT',\n    ownerOnly: true,\n    description:\n      'View, transfer, buy, list, and manage NFTs. Supports collections on Base, Ethereum, ' +\n      'Arbitrum, Optimism, and Polygon. Uses Reservoir API for marketplace data ' +\n      '(covers OpenSea, Blur, LooksRare). Requires RESERVOIR_API_KEY.',\n    parameters: NftSchema,\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      switch (action) {\n        case 'view':\n          return handleView(params);\n        case 'transfer':\n          return handleTransfer(params);\n        case 'buy':\n          return handleBuy(params);\n        case 'list':\n          return handleList(params);\n        case 'collection_floor':\n          return handleCollectionFloor(params);\n        case 'portfolio':\n          return handlePortfolio(params);\n        default:\n          return errorResult(`Unknown action: ${action}. Use: view, transfer, buy, list, collection_floor, portfolio`);\n      }\n    },\n  };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction resolveChainId(chain?: string): number {\n  if (!chain) return 8453;\n  switch (chain.toLowerCase()) {\n    case 'ethereum': case 'eth': case 'mainnet': return 1;\n    case 'arbitrum': case 'arb': return 42161;\n    case 'optimism': case 'op': return 10;\n    case 'polygon': case 'matic': return 137;\n    case 'base': default: return 8453;\n  }\n}\n\nfunction chainName(chainId: number): string {\n  const names: Record<number, string> = {\n    1: 'ethereum', 8453: 'base', 42161: 'arbitrum', 10: 'optimism', 137: 'polygon',\n  };\n  return names[chainId] ?? String(chainId);\n}\n\n/** Validate token ID is a non-negative integer string. */\nfunction validateTokenId(tokenId: string): bigint {\n  const trimmed = tokenId.trim();\n  if (!trimmed || !/^\\d+$/.test(trimmed)) {\n    throw new Error(`Invalid token ID \"${trimmed}\". Must be a non-negative integer.`);\n  }\n  return BigInt(trimmed);\n}\n\n/** Validate and parse an ETH price string. */\nfunction validatePrice(price: string): bigint {\n  const trimmed = price.trim();\n  if (!trimmed) throw new Error('Price cannot be empty.');\n  if (!/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n    throw new Error(`Invalid price \"${trimmed}\". Must be a positive number (e.g. \"0.5\", \"1.0\").`);\n  }\n  const parsed = parseFloat(trimmed);\n  if (parsed === 0) throw new Error('Price must be greater than zero.');\n  return parseEther(trimmed);\n}\n\n// ── Action Handlers ─────────────────────────────────────────────────────────\n\nasync function handleView(params: Record<string, unknown>) {\n  const contract = readStringParam(params, 'contract', { required: true });\n  const tokenId = readStringParam(params, 'token_id') ?? readStringParam(params, 'tokenId');\n  if (!contract || !tokenId) {\n    return errorResult('Both contract and token_id are required for view.');\n  }\n\n  const chainId = resolveChainId(readStringParam(params, 'chain'));\n\n  try {\n    const service = getNftService();\n    const token = await service.getToken(contract, tokenId, chainId);\n\n    return jsonResult({\n      chain: token.chain,\n      contract: token.contract,\n      tokenId: token.tokenId,\n      name: token.name,\n      description: token.description,\n      image: token.image,\n      collection: token.collection,\n      owner: token.owner,\n      lastSale: token.lastSalePrice,\n      rarityRank: token.rarity,\n      attributes: token.attributes.length > 0 ? token.attributes : undefined,\n    });\n  } catch (err) {\n    return errorResult(`NFT view failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handleTransfer(params: Record<string, unknown>) {\n  const contract = readStringParam(params, 'contract', { required: true });\n  const tokenId = readStringParam(params, 'token_id') ?? readStringParam(params, 'tokenId');\n  const toInput = readStringParam(params, 'to', { required: true });\n  if (!contract || !tokenId || !toInput) {\n    return errorResult('contract, token_id, and to are required for transfer.');\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  try {\n    // Resolve ENS if needed\n    let toAddress = toInput;\n    if (isEnsName(toInput)) {\n      const publicClient = requirePublicClient();\n      const resolved = await resolveAddressOrEns(toInput, publicClient);\n      toAddress = resolved.address;\n    }\n\n    const wallet = requireWalletClient();\n    const publicClient = requirePublicClient();\n\n    const hash = await wallet.writeContract({\n      address: contract as `0x${string}`,\n      abi: ERC721_TRANSFER_ABI,\n      functionName: 'safeTransferFrom',\n      args: [\n        state.address as `0x${string}`,\n        toAddress as `0x${string}`,\n        validateTokenId(tokenId),\n      ],\n    });\n\n    await publicClient.waitForTransactionReceipt({ hash });\n\n    return jsonResult({\n      status: 'success',\n      action: 'transfer',\n      contract,\n      tokenId,\n      from: state.address,\n      to: toAddress,\n      ensName: isEnsName(toInput) ? toInput : undefined,\n      txHash: hash,\n    });\n  } catch (err) {\n    return errorResult(`NFT transfer failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handleBuy(params: Record<string, unknown>) {\n  const contract = readStringParam(params, 'contract', { required: true });\n  const tokenId = readStringParam(params, 'token_id') ?? readStringParam(params, 'tokenId');\n  if (!contract || !tokenId) {\n    return errorResult('Both contract and token_id are required for buy.');\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 chainId = resolveChainId(readStringParam(params, 'chain'));\n\n  try {\n    const service = getNftService();\n    const buyOrder = await service.getBuyOrder(contract, tokenId, state.address, chainId);\n\n    if (!buyOrder.txData) {\n      return jsonResult({\n        status: 'no_listing',\n        contract,\n        tokenId,\n        message: buyOrder.status || 'No active listing found for this NFT.',\n      });\n    }\n\n    // Execute the buy transaction\n    const wallet = requireWalletClient();\n    const publicClient = requirePublicClient();\n    const hash = await wallet.sendTransaction({\n      to: buyOrder.txData.to as `0x${string}`,\n      data: buyOrder.txData.data as `0x${string}`,\n      value: BigInt(buyOrder.txData.value || '0'),\n    });\n\n    await publicClient.waitForTransactionReceipt({ hash });\n\n    return jsonResult({\n      status: 'success',\n      action: 'buy',\n      contract,\n      tokenId,\n      price: buyOrder.price,\n      marketplace: buyOrder.marketplace,\n      txHash: hash,\n      chain: chainName(chainId),\n    });\n  } catch (err) {\n    return errorResult(`NFT buy failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handleList(params: Record<string, unknown>) {\n  const contract = readStringParam(params, 'contract', { required: true });\n  const tokenId = readStringParam(params, 'token_id') ?? readStringParam(params, 'tokenId');\n  const priceInput = readStringParam(params, 'price', { required: true });\n  if (!contract || !tokenId || !priceInput) {\n    return errorResult('contract, token_id, and price are required for list.');\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 chainId = resolveChainId(readStringParam(params, 'chain'));\n\n  try {\n    const priceWei = validatePrice(priceInput).toString();\n    const service = getNftService();\n    const listResult = await service.getListOrder(\n      contract, tokenId, state.address, priceWei, chainId,\n    );\n\n    // If there are signing steps, the wallet needs to complete them\n    const signingSteps = listResult.steps.filter((s: any) =>\n      s.kind === 'signature' && s.items?.length > 0,\n    );\n\n    return jsonResult({\n      status: listResult.status,\n      action: 'list',\n      contract,\n      tokenId,\n      priceEth: priceInput,\n      orderId: listResult.orderId,\n      chain: chainName(chainId),\n      requiresSignature: signingSteps.length > 0,\n      note: signingSteps.length > 0\n        ? 'Listing requires wallet signature approval. The order will be posted to Reservoir/OpenSea.'\n        : 'Listing submitted successfully.',\n    });\n  } catch (err) {\n    return errorResult(`NFT list failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handleCollectionFloor(params: Record<string, unknown>) {\n  const collectionInput = readStringParam(params, 'collection')\n    ?? readStringParam(params, 'contract');\n  if (!collectionInput) {\n    return errorResult('collection (contract address or slug) is required for collection_floor.');\n  }\n\n  const chainId = resolveChainId(readStringParam(params, 'chain'));\n\n  try {\n    const service = getNftService();\n    const collection = await service.getCollectionFloor(collectionInput, chainId);\n\n    return jsonResult({\n      chain: collection.chain,\n      collection: collection.name,\n      contractId: collection.id,\n      image: collection.image,\n      floorPrice: collection.floorPrice\n        ? `${collection.floorPrice} ${collection.floorPriceCurrency}`\n        : 'no listings',\n      volume24h: collection.volume24h\n        ? `${collection.volume24h} ETH`\n        : null,\n      totalSupply: collection.totalSupply,\n      ownerCount: collection.ownerCount,\n    });\n  } catch (err) {\n    return errorResult(`Collection floor failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n\nasync function handlePortfolio(params: Record<string, unknown>) {\n  const state = getWalletState();\n  const addressInput = readStringParam(params, 'address') ?? state.address;\n  if (!addressInput) {\n    return errorResult('No wallet connected and no address provided.');\n  }\n\n  const chainId = resolveChainId(readStringParam(params, 'chain'));\n  const limit = readNumberParam(params, 'limit') ?? 50;\n\n  try {\n    const service = getNftService();\n    const items = await service.getPortfolio(addressInput, chainId, limit);\n\n    if (items.length === 0) {\n      return jsonResult({\n        chain: chainName(chainId),\n        address: addressInput,\n        nfts: [],\n        message: 'No NFTs found on this chain.',\n      });\n    }\n\n    // Group by collection\n    const byCollection: Record<string, typeof items> = {};\n    for (const item of items) {\n      const key = item.collection ?? item.contract;\n      if (!byCollection[key]) byCollection[key] = [];\n      byCollection[key].push(item);\n    }\n\n    return jsonResult({\n      chain: chainName(chainId),\n      address: addressInput,\n      totalNfts: items.length,\n      collections: Object.entries(byCollection).map(([name, nfts]) => ({\n        collection: name,\n        count: nfts.length,\n        floorPrice: nfts[0]?.floorPrice,\n        items: nfts.slice(0, 5).map(n => ({\n          tokenId: n.tokenId,\n          name: n.name,\n          image: n.image,\n        })),\n      })),\n    });\n  } catch (err) {\n    return errorResult(`Portfolio failed: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n"],"mappings":"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"}