Skip to content

Conversation

@premiumjibles
Copy link
Contributor

@premiumjibles premiumjibles commented Nov 27, 2025

Summary by CodeRabbit

  • New Features

    • Added market-data tools: Trending Tokens, Top Gainers/Losers, Trending Pools, Categories, and New Coins.
    • New UI cards: Trending (24h), Top Gainers/Losers, Recently Added coins, plus a reusable asset row showing rank, icon, price and 24h change.
  • Improvements

    • Consolidated price/enrichment flows for more consistent card data.
    • Streamlined UI-focused descriptions and unified tool behavior for clearer user-facing responses.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Nov 27, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
shapeshift-agentic Ready Ready Preview Comment Nov 27, 2025 9:45pm

@coderabbitai
Copy link

coderabbitai bot commented Nov 27, 2025

📝 Walkthrough

Walkthrough

Adds multiple CoinGecko-backed server tools, new Coingecko types and API wrappers, asset price helpers, a reusable AssetListItem UI, three ToolCard UIs (Trending, TopGainers/Losers, NewCoins), registers those UIs, and wires tools into the chat router with a logging wrapper.

Changes

Cohort / File(s) Summary
New Server Tools
apps/agentic-server/src/tools/getTrendingTokens.ts, apps/agentic-server/src/tools/getTopGainersLosers.ts, apps/agentic-server/src/tools/getTrendingPools.ts, apps/agentic-server/src/tools/getCategories.ts, apps/agentic-server/src/tools/getNewCoins.ts
New zod-backed tools: schemas, input/output types, executeGet* implementations, and exported tool objects that fetch, trim, and return CoinGecko data for UI consumption.
CoinGecko API & Types
apps/agentic-server/src/lib/asset/coingecko/api.ts, apps/agentic-server/src/lib/asset/coingecko/types.ts, apps/agentic-server/src/lib/asset/coingecko/index.ts
Added new API wrappers/endpoints and many response/trimmed TypeScript types; re-exported new functions and types.
Server Exports & Router
apps/agentic-server/src/index.ts, apps/agentic-server/src/routes/chat.ts
Exported new tools/types from server index; chat router adds new tools to buildTools, introduces wrapToolWithLogging, and updates prompts/tool registrations.
Asset Price Flow & Helpers
apps/agentic-server/src/tools/getAssets.ts, apps/agentic-server/src/lib/asset/prices.ts, apps/agentic-server/src/utils/assetHelpers.ts
Consolidated getAssets API (executeGetAssets), added enrich/getAssetWithMarketData, introduced getAssetPrices and AssetWithPrice type, and simplified asset resolution/price lookups; updated call sites.
Consume-site Callsite Updates
apps/agentic-server/src/tools/initiateSwap.ts, apps/agentic-server/src/tools/portfolio.ts
Replaced removed executeGetAssetsBasic usage with resolveAsset/getAssetPrices flows and updated descriptions and null/price handling.
Tool Description Edits
apps/agentic-server/src/tools/send.ts, apps/agentic-server/src/tools/receive.ts, apps/agentic-server/src/tools/transactionHistory.ts, apps/agentic-server/src/tools/getShapeShiftKnowledge.ts
Updated exported tool description strings to be more concise and UI/card-focused; no behavior changes.
UI Components & Registry
apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx, apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx, apps/agentic-chat/src/components/tools/NewCoinsUI.tsx, apps/agentic-chat/src/components/toolUIRegistry.tsx
Added three ToolCard-based UI components and registered them in TOOL_UI_REGISTRY mappings.
Shared UI Component
apps/agentic-chat/src/components/ui/AssetListItem.tsx
New reusable AssetListItem component rendering rank, icon (URL fallback/initials), name/subtitle, price, and 24h change with formatting and variant styling.
Context / Docs tweak
apps/agentic-server/src/context.ts
Text edits to guidance heading and swap capability note (clarifies EVM/Solana-only swaps).

Sequence Diagram(s)

sequenceDiagram
    participant User as Chat User
    participant UI as Client UI (ToolCard)
    participant Server as Agentic Server (routes/chat)
    participant Tool as Tool Executor (executeGet*)
    participant CG as CoinGecko API
    participant Resolver as AssetId Resolver

    User->>UI: request (e.g., "show trending tokens")
    UI->>Server: invoke registered tool execute
    Server->>Tool: executeGetTrendingTokens / executeGetTopGainersLosers / ...
    Tool->>CG: fetch raw data (getTrendingSearch / getTopGainersLosers / ...)
    CG-->>Tool: raw response
    Tool->>Resolver: map & resolve assetId/coingecko -> Trimmed*
    Resolver-->>Tool: trimmed items
    Tool-->>Server: trimmed tool output
    Server-->>UI: deliver tool output
    UI->>UI: useToolStateRender handles loading/error
    UI->>User: render ToolCard with AssetListItem rows
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas to focus on:

  • getAssets.ts refactor: single-asset vs bulk behavior, renames, and fallback semantics.
  • CoinGecko api/types: parameter handling, defaults, and trimming logic.
  • getAssetPrices implementation and propagation of priceChange24h.
  • Tool executors: default limits, duration enums, and coingeckoToAssetIds mapping.
  • routes/chat: wrapToolWithLogging correctness and tool wiring.
  • UI: AssetListItem icon fallback/accessibility and ToolCard state handling.

Possibly related PRs

Poem

🐰 I hopped through code with ears alight,
New tokens, gainers, pools in sight,
Cards that sparkle, rows that gleam,
Icons, ranks — a rabbit's dream,
I twitched my nose and said, "Good night!" ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: informational tooling' directly summarizes the main change: adding five new information-retrieval tools (trending tokens, top gainers/losers, trending pools, categories, new coins) to the agentic chat system.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch informational-tools

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (8)
apps/agentic-server/src/tools/send.ts (1)

121-132: Prompt update is clear and safe; consider one extra guardrail about execution claims

The new description cleanly scopes the tool’s behavior around the send card and should help reduce redundant or verbose replies. As a minor improvement, you might explicitly add that the assistant must not claim the transaction has already been sent or executed (only prepared/pending user confirmation), to avoid any misleading language about on-chain state.

apps/agentic-server/src/tools/receive.ts (1)

34-45: Clear tool description; consider softening the “Do not repeat the address” rule

The expanded description is clear and matches the UI‑card pattern in this PR. One small tweak: the hard “Do not repeat the address” could conflict with cases where the user explicitly asks “What’s my address?” or where the card fails to render (e.g., non‑UI contexts).

Consider something like:

-Your role is to supplement the card, not duplicate it. Do not repeat the address.
+Your role is to supplement the card, not duplicate it. Avoid repeating the full address
+unless the user explicitly asks for it or the card is not visible.

This keeps responses concise in the normal UI flow while leaving room for edge cases.

apps/agentic-server/src/context.ts (1)

24-24: Helpful guidance for unsupported swaps.

The new line provides clear instruction on how to handle user requests for swaps with unsupported assets, which improves the user experience.

Optional: Consider capitalizing consistently with line 17.

For consistency with line 17 (which uses lowercase: "bitcoin, litecoin, dogecoin, bitcoincash, cosmos, thorchain, tron, cardano, sui"), you might use lowercase in the examples here as well:

-    - If user requests swap with unsupported assets (Bitcoin, Cardano, etc.), explain swaps only support EVM and Solana
+    - If user requests swap with unsupported assets (bitcoin, cardano, etc.), explain swaps only support EVM and Solana
apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)

24-49: Consider extracting IconFromUrl as a shared component or consolidating with AssetIcon.

The IconFromUrl component duplicates fallback logic present in AssetIcon (lines 22-35 of AssetIcon.tsx). Both components handle image error states and render initials as fallback. If this pattern is used elsewhere, consider a shared primitive.

That said, the current implementation is correct and self-contained.

apps/agentic-server/src/tools/getTrendingPools.ts (1)

67-69: Consider aligning price change period with the requested duration.

The priceChange24h field always uses h24 regardless of the duration parameter. If the user requests 1h trending pools, showing 24h price change may be unexpected.

You could either:

  1. Keep as-is (24h is a standard metric) and clarify in the output field name
  2. Dynamically select the price change period based on duration
// Option 2: Dynamic selection
const durationToKey: Record<string, keyof NonNullable<typeof pool.attributes.price_change_percentage>> = {
  '5m': 'm5',
  '1h': 'h1', 
  '6h': 'h6',
  '24h': 'h24',
}
priceChange: pool.attributes.price_change_percentage?.[durationToKey[duration]] ?? null,
apps/agentic-server/src/tools/getNewCoins.ts (1)

17-30: Consider guarding formatTimeAgo against future timestamps

If activated_at ever lands slightly in the future (clock skew, API oddities), diffMs becomes negative and everything collapses to 'Just now'. Not a bug, but an easy robustness win would be an early guard:

 function formatTimeAgo(timestamp: number): string {
   const now = Date.now()
-  const diffMs = now - timestamp * 1000
+  const diffMs = now - timestamp * 1000
+  if (diffMs <= 0) return 'Just now'

and then keep the existing hour/day logic.

apps/agentic-server/src/tools/getAssets.ts (2)

62-87: Single-asset resolution and network inference deserve a quick sanity check

The precedence searchTerm → first assetIds[0]undefined is clear, and inferring network from chainIdToNetwork with an 'ethereum' fallback ensures the field is always populated. Two things worth verifying:

  • That combinations like { searchTerm, assetIds } are either not used or intentionally favor searchTerm.
  • That using the optional network parameter as an override (rather than purely a filter) for the returned asset’s network is acceptable for all current callers.

If either assumption doesn’t hold, you may want to document this behavior or split “filter network” from “override network” semantics.


89-113: Bulk price path looks correct; consider minor alignment on priceChange nullability

The bulk path:

  • Filters out unknown assets,
  • Fetches prices once via getSimplePrices(assetIds),
  • Overlays price and priceChange24h onto static assets while inferring network similarly to the single-asset path.

One small consistency tweak you might consider: explicitly normalizing priceChange24h to null when missing so that both single-asset and bulk responses use the same number | null shape instead of mixing undefined and null. Not mandatory, but it can simplify UI checks.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e4701d5 and 3f66c45.

📒 Files selected for processing (24)
  • apps/agentic-chat/src/components/toolUIRegistry.tsx (2 hunks)
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/ui/AssetListItem.tsx (1 hunks)
  • apps/agentic-server/src/context.ts (1 hunks)
  • apps/agentic-server/src/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/api.ts (2 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/types.ts (1 hunks)
  • apps/agentic-server/src/routes/chat.ts (2 hunks)
  • apps/agentic-server/src/tools/getAssets.ts (2 hunks)
  • apps/agentic-server/src/tools/getCategories.ts (1 hunks)
  • apps/agentic-server/src/tools/getNewCoins.ts (1 hunks)
  • apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1 hunks)
  • apps/agentic-server/src/tools/getTopGainersLosers.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingPools.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingTokens.ts (1 hunks)
  • apps/agentic-server/src/tools/initiateSwap.ts (4 hunks)
  • apps/agentic-server/src/tools/portfolio.ts (4 hunks)
  • apps/agentic-server/src/tools/receive.ts (1 hunks)
  • apps/agentic-server/src/tools/send.ts (1 hunks)
  • apps/agentic-server/src/tools/transactionHistory.ts (1 hunks)
  • apps/agentic-server/src/utils/assetHelpers.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-18T20:08:31.777Z
Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 73
File: apps/agentic-chat/src/components/assistant-ui/GetPortalsAssets.tsx:30-33
Timestamp: 2025-09-18T20:08:31.777Z
Learning: In assistant UI components using makeAssistantToolUI, the toolName should match the exact key name as defined in the agent's tools configuration object, not the underlying tool's id. For example, if a tool is referenced as 'getPortalsAssetsTool' in the agent's tools object, the UI component should use toolName: 'getPortalsAssetsTool'.

Applied to files:

  • apps/agentic-chat/src/components/toolUIRegistry.tsx
🧬 Code graph analysis (11)
apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (5)
apps/agentic-chat/src/components/tools/toolUIHelpers.tsx (2)
  • ToolUIComponentProps (6-8)
  • useToolStateRender (10-31)
apps/agentic-server/src/index.ts (1)
  • TrimmedGainerLoserCoin (93-93)
apps/agentic-server/src/lib/asset/coingecko/types.ts (1)
  • TrimmedGainerLoserCoin (202-212)
apps/agentic-chat/src/components/ui/ToolCard.tsx (1)
  • ToolCard (71-78)
apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)
  • AssetListItem (51-112)
apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (5)
apps/agentic-chat/src/components/tools/toolUIHelpers.tsx (2)
  • ToolUIComponentProps (6-8)
  • useToolStateRender (10-31)
apps/agentic-server/src/index.ts (1)
  • TrimmedNewCoin (96-96)
apps/agentic-server/src/lib/asset/coingecko/types.ts (1)
  • TrimmedNewCoin (236-243)
apps/agentic-chat/src/components/ui/ToolCard.tsx (1)
  • ToolCard (71-78)
apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)
  • AssetListItem (51-112)
apps/agentic-server/src/tools/getTrendingPools.ts (2)
apps/agentic-server/src/lib/asset/coingecko/types.ts (3)
  • TrimmedTrendingPool (214-225)
  • TrendingPoolIncluded (148-159)
  • TrendingPoolData (105-146)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getTrendingPools (134-142)
apps/agentic-server/src/routes/chat.ts (6)
apps/agentic-server/src/index.ts (5)
  • getTrendingTokensTool (67-67)
  • getTopGainersLosersTool (73-73)
  • getTrendingPoolsTool (79-79)
  • getCategoriesTool (85-85)
  • getNewCoinsTool (90-90)
apps/agentic-server/src/tools/getTrendingTokens.ts (1)
  • getTrendingTokensTool (39-54)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)
  • getTopGainersLosersTool (53-68)
apps/agentic-server/src/tools/getTrendingPools.ts (1)
  • getTrendingPoolsTool (77-81)
apps/agentic-server/src/tools/getCategories.ts (1)
  • getCategoriesTool (42-46)
apps/agentic-server/src/tools/getNewCoins.ts (1)
  • getNewCoinsTool (53-68)
apps/agentic-chat/src/components/toolUIRegistry.tsx (3)
apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1)
  • TrendingTokensUI (10-56)
apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1)
  • TopGainersLosersUI (10-95)
apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (1)
  • NewCoinsUI (10-55)
apps/agentic-server/src/lib/asset/coingecko/api.ts (2)
apps/agentic-server/src/lib/asset/coingecko/index.ts (10)
  • getTrendingSearch (4-4)
  • TrendingSearchResponse (13-13)
  • getTopGainersLosers (5-5)
  • TopGainersLosersResponse (14-14)
  • getTrendingPools (6-6)
  • TrendingPoolsResponse (15-15)
  • getCategories (7-7)
  • CategoriesResponse (16-16)
  • getNewCoins (8-8)
  • NewCoinsResponse (17-17)
apps/agentic-server/src/lib/asset/coingecko/types.ts (5)
  • TrendingSearchResponse (62-74)
  • TopGainersLosersResponse (92-95)
  • TrendingPoolsResponse (161-164)
  • CategoriesResponse (179-179)
  • NewCoinsResponse (189-189)
apps/agentic-server/src/utils/assetHelpers.ts (4)
apps/agentic-server/src/lib/schemas/swapSchemas.ts (1)
  • AssetInput (76-76)
packages/types/src/asset.ts (1)
  • Asset (28-28)
apps/agentic-server/src/index.ts (1)
  • executeGetAssets (5-5)
apps/agentic-server/src/tools/getAssets.ts (1)
  • executeGetAssets (115-129)
apps/agentic-server/src/tools/portfolio.ts (2)
apps/agentic-server/src/tools/getAssets.ts (1)
  • executeGetAssets (115-129)
packages/types/src/asset.ts (1)
  • asset (3-26)
apps/agentic-chat/src/components/ui/AssetListItem.tsx (5)
packages/caip/src/constants.ts (1)
  • AssetId (176-176)
apps/agentic-chat/src/lib/utils.ts (1)
  • cn (5-7)
apps/agentic-chat/src/lib/bignumber.ts (1)
  • bnOrZero (5-13)
apps/agentic-chat/src/components/ui/AssetIcon.tsx (1)
  • AssetIcon (12-47)
apps/agentic-chat/src/lib/number.ts (2)
  • formatFiat (70-82)
  • formatPercent (98-117)
apps/agentic-server/src/tools/getTrendingTokens.ts (3)
apps/agentic-server/src/lib/asset/coingecko/types.ts (2)
  • TrimmedTrendingCoin (192-200)
  • TrendingCoinItem (37-60)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getTrendingSearch (107-110)
packages/caip/src/adapters/coingecko/index.ts (1)
  • coingeckoToAssetIds (57-57)
apps/agentic-server/src/tools/getAssets.ts (4)
packages/types/src/asset.ts (2)
  • asset (3-26)
  • Asset (28-28)
packages/utils/src/AssetService.ts (1)
  • assetService (135-135)
packages/types/src/network.ts (1)
  • chainIdToNetwork (84-86)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getSimplePrices (56-101)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: main
🔇 Additional comments (33)
apps/agentic-server/src/tools/transactionHistory.ts (1)

114-115: Tool description update is clear and aligned with behavior

The new description cleanly communicates that this tool is for filtered transaction queries and that responses should present/format data directly without assuming UI cards. This matches the implementation and the broader analytics‑focused tooling direction.

apps/agentic-server/src/context.ts (1)

20-20: LGTM! Clearer section heading.

The change from "Tool Usage:" to "Network-Specific Capabilities:" better describes the content of this section and improves documentation clarity.

apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1)

60-64: Clarified tool semantics look good

The updated description clearly signals that this is a pure informational tool with no UI card, which should reduce redundant card-oriented phrasing in responses. No behavioral changes—safe update.

apps/agentic-server/src/utils/assetHelpers.ts (1)

5-32: Good migration to unified executeGetAssets

Switching resolveAsset to use executeGetAssets with { searchTerm, network } keeps the single-asset resolution semantics while routing through the new shared asset pipeline. The length checks and error messages still correctly enforce “exactly one asset” behavior.

apps/agentic-server/src/tools/portfolio.ts (2)

10-118: executeGetAssets integration and 24h change mapping look consistent

Using executeGetAssets({ assetIds }) aligns this tool with the new unified asset API and still supports both single- and multi-asset portfolios via the internal branching. Normalizing priceChange24h with ?? undefined is a nice touch to avoid leaking null while keeping zero changes intact.


153-168: Rich portfolio description matches UI‑card pattern

The expanded portfolioTool.description clearly documents what the card shows and how the assistant should respond (brief, non-duplicative summaries). This aligns well with the new informational tooling guidelines.

apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1)

1-55: Trending tokens UI is wired cleanly and matches existing patterns

State handling via useToolStateRender, the output cast, and the ToolCard + AssetListItem composition all mirror your other tool UIs. Prop usage (price, priceChange24h, rank, assetId) matches TrimmedTrendingCoin and AssetListItem expectations, so this should render reliably.

apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1)

1-95: Top gainers/losers UI is consistent and robust to empty sets

The component cleanly splits gainers and losers into separate ToolCards, uses variant="gain"/"loss" correctly for styling, and short‑circuits when both arrays are empty. The type assertion matches TrimmedGainerLoserCoin, so as long as the server keeps that contract, this should be solid.

apps/agentic-server/src/tools/initiateSwap.ts (2)

21-362: USD swap flow’s move to executeGetAssets preserves behavior

Using executeGetAssets to resolve the sell asset in executeInitiateSwapUsd (with searchTerm + optional network) keeps the previous semantics: clear errors on zero/multiple matches, then price‑based conversion to crypto before delegating to executeSwapInternal. The rest of the swap pipeline (rate selection, approvals, summary) stays untouched, so behavior should match the old path while benefiting from the unified asset API.


293-308: Swap tool descriptions now align with the card‑first UX

Both initiateSwapTool and initiateSwapUsdTool now explicitly describe what the UI card shows and instruct the assistant to add a short, supplementary sentence instead of restating data. This should significantly reduce verbose or duplicative responses around swap details.

Also applies to: 364-379

apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (1)

1-55: New coins UI component is well‑structured and type‑aligned

This follows the established tool UI pattern: proper loading/error handling, safe early return on empty data, and a clear ToolCard layout. The AssetListItem props line up with TrimmedNewCoin, and the “Listed {activatedAtFormatted}” subtitle is a nice contextual touch.

apps/agentic-chat/src/components/toolUIRegistry.tsx (1)

9-38: Tool registry entries are correctly implemented with names matching agent configuration.

The three new registry entries—getTrendingTokensTool, getTopGainersLosersTool, and getNewCoinsTool—align perfectly with the tool definitions exported from the server and configured in the agent's tools object (apps/agentic-server/src/routes/chat.ts). The UI component imports are also properly in place. No issues detected.

apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)

51-112: LGTM!

The component correctly handles:

  • Optional rank display with proper formatting
  • Icon priority cascade (assetId → iconUrl → initials fallback)
  • Conditional price/change rendering guarded by hasPrice/hasChange
  • Variant-based color override with sensible defaults
  • Proper use of tabular-nums for numeric alignment
apps/agentic-server/src/lib/asset/coingecko/index.ts (1)

1-23: LGTM!

Clean barrel file that correctly re-exports the new CoinGecko API functions and associated types. The exports are well-organized with functions and types separated.

apps/agentic-server/src/tools/getTrendingPools.ts (1)

21-75: LGTM!

The implementation correctly:

  • Builds lookup maps from the included array with type filtering
  • Handles missing relationships and attributes with sensible fallbacks
  • Slices results to the requested limit before processing
  • Maintains null safety throughout the mapping
apps/agentic-server/src/tools/getCategories.ts (2)

21-40: LGTM!

Clean implementation with:

  • Sensible defaults (market_cap_change_24h for trending relevance)
  • Proper mapping from user-friendly input to API parameters
  • Null-safe field access with fallbacks
  • Efficient slice-then-map pattern

6-12: LGTM!

The schema provides clear validation with helpful descriptions. The limit bounds (1-20) are appropriate for category data.

apps/agentic-server/src/lib/asset/coingecko/api.ts (1)

103-168: No issues found — original review is accurate.

All CoinGecko Pro API endpoints are correctly implemented:

  • /search/trending — valid trending search endpoint ✓
  • /coins/top_gainers_losers — valid gainers/losers endpoint with correct duration/top_coins parameters ✓
  • /onchain/networks/trending_pools — valid all-networks trending pools endpoint with correct include and duration params ✓
  • /coins/categories — valid categories endpoint with correct order parameter ✓
  • /coins/list/new — valid new coins endpoint ✓

The function signatures, parameter defaults, and types all align with CoinGecko Pro API documentation. The implementation is clean, well-documented, and consistent with the existing codebase patterns.

apps/agentic-server/src/tools/getTrendingTokens.ts (3)

7-15: Input schema and output typing are well-bounded

Limit validation (1–15 with a default of 5) and the dedicated GetTrendingTokensInput/GetTrendingTokensOutput types give a clear, narrow surface for the tool; no issues from a correctness standpoint.


17-36: Trending token mapping looks correct and null-safe

Slicing by limit and mapping TrendingCoinItem into TrimmedTrendingCoin (including optional assetId via coingeckoToAssetIds) is clean and handles missing data fields via optional chaining and null fallbacks. This should be robust even when CoinGecko omits nested fields.


39-53: Tool description aligns with UI-card pattern

The description clearly constrains the LLM to “supplement” the card rather than re-list data, and the default responses are short and on-brand. This is consistent with the other informational tools introduced in this PR.

apps/agentic-server/src/tools/getNewCoins.ts (3)

7-15: New-coins schema is consistent with the other tools

The limit bounds (1–20, default 5) and dedicated input/output types mirror the other CoinGecko tools and provide a predictable interface.


32-51: New-coin mapping and assetId resolution look sound

Slicing by limit, mapping to TrimmedNewCoin, and deriving assetId via coingeckoToAssetIds is straightforward. The dual fields activatedAt (raw) and activatedAtFormatted (human-readable) should make UI rendering flexible without extra client logic.


53-68: Tool description clearly scopes LLM behavior

The “UI CARD DISPLAYS…” block plus sample default sentences fits the new informational-tool pattern and should help keep responses concise and non-duplicative of card contents.

apps/agentic-server/src/tools/getTopGainersLosers.ts (2)

7-21: Duration and limit parameters are well-scoped

The duration enum and limit (1–10, default 5) provide a tidy and self-documenting API for this tool. Leaving duration optional with a default of '24h' is a reasonable choice.


53-68: Top gainers/losers tool description is precise and UI-aware

The copy clearly instructs the model not to re-list tokens or percentages already visible in the card, and the suggested one-liners keep responses succinct. This matches the intended “informational tooling” UX.

apps/agentic-server/src/index.ts (1)

66-97: Public exports for new tools and types are coherent

Re-exporting the new tools and their input/output types, plus the Trimmed* CoinGecko types, keeps the server’s public surface consistent with existing tooling. This should make it straightforward for both the router and UI to consume these features without reaching into deep paths.

apps/agentic-server/src/routes/chat.ts (1)

21-27: New informational tools are wired into the chat router consistently

The added imports and buildTools entries for getTrendingTokensTool, getTopGainersLosersTool, getTrendingPoolsTool, getCategoriesTool, and getNewCoinsTool mirror the existing pattern: spread the base tool, wrap execute with a logging layer, and avoid touching wallet context for these wallet-agnostic calls. No correctness issues spotted here.

Also applies to: 163-197

apps/agentic-server/src/tools/getAssets.ts (4)

32-35: Unified GetAssetsOutput simplifies the API surface

Consolidating into a single { assets: AssetWithMarketData[] } output removes the split between “basic” and “with market data” paths, which should reduce branching for callers and UI.


36-60: enrichWithMarketData correctly layers CoinGecko fields on top of static assets

The enrichment step safely handles missing fields (using ?? null and optional chaining) and augments the base Asset with icon, market cap, volume, supply, sentiment, rank, and description. The scoped error log plus null return is a reasonable pattern that lets the caller gracefully fall back.


115-129: Routing logic in executeGetAssets matches the new API model

The dispatcher cleanly chooses:

  • single-asset enrichment when searchTerm is present or exactly one assetId is provided,
  • bulk price fetch when assetIds.length > 1,
  • otherwise returns an empty list.

This is straightforward and keeps the branching close to the tool entrypoint.


131-147: Updated getAssetsTool description matches the informational tooling pattern

The guidance around the UI card (what it shows vs what the LLM should add) is clear and mirrors the new market-info tools. Wiring execute to executeGetAssets completes the refactor to the unified output.

apps/agentic-server/src/lib/asset/coingecko/types.ts (1)

36-243: New CoinGecko endpoint and trimmed types are consistent with tool usage

The added types (TrendingCoinItem, TopGainersLosersResponse, TrendingPool*, CategoryData, NewCoinData, and the various Trimmed* shapes) align with how the tools consume and emit data:

  • Raw response types expose the full CoinGecko payloads, including optional nested fields.
  • Trimmed variants keep only the minimal fields the tools and UI need, helping to control LLM context size.
  • Nullability and optionality (e.g., price vs priceChange*, marketCapRank, assetId?) match the access patterns in the new tools.

I don’t see structural mismatches between these definitions and the tool mappers in this PR.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)

7-13: Align duration support with exposed price‑change fields

duration accepts '1h' | '24h' | '7d' | '14d' | '30d' and GainerLoserCoin includes usd_14d_change/usd_30d_change, but TrimmedGainerLoserCoin and mapCoin only surface 1h/24h/7d. Callers can never see 14d/30d changes even when requesting those durations.

Either (a) extend the trimmed type and mapper, or (b) narrow the allowed duration values to the periods you actually expose:

-// apps/agentic-server/src/lib/asset/coingecko/types.ts
 export type TrimmedGainerLoserCoin = {
   id: string
   name: string
   symbol: string
   price: number
   priceChange24h: number
   priceChange1h?: number
   priceChange7d?: number
+  priceChange14d?: number
+  priceChange30d?: number
   marketCapRank: number | null
   assetId?: string
 }
-// apps/agentic-server/src/tools/getTopGainersLosers.ts
       price: coin.usd,
       priceChange24h: coin.usd_24h_change,
       priceChange1h: coin.usd_1h_change,
-      priceChange7d: coin.usd_7d_change,
+      priceChange7d: coin.usd_7d_change,
+      priceChange14d: coin.usd_14d_change,
+      priceChange30d: coin.usd_30d_change,

Alternatively, if you intend to always show 24h change regardless of selection, consider restricting duration to '1h' | '24h' | '7d' to avoid implying 14d/30d data is available.

Also applies to: 31-43

🧹 Nitpick comments (5)
apps/agentic-server/src/context.ts (1)

20-24: Docs update is accurate; consider a minor wording polish

The new section correctly describes capabilities and clarifies unsupported swap assets; this is a useful addition and matches the preceding lists of supported networks. To tighten the language, you might make the last bullet a bit clearer and more grammatical:

-    - If user requests swap with unsupported assets (Bitcoin, Cardano, etc.), explain swaps only support EVM and Solana
+    - If the user requests a swap with unsupported assets (e.g., Bitcoin, Cardano), explain that swaps only support EVM chains and Solana

This keeps it consistent with the “SUPPORTED/NOT SUPPORTED” phrasing above and reads more naturally.

apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)

66-79: Consider simplifying formatting and clarifying variant vs numeric sign behavior

You currently wrap price/priceChange24h with bnOrZero and then pass the resulting BigNumbers into formatFiat/formatPercent, which already apply bnOrZero internally. You could pass the raw props directly (and potentially drop the memos) to trim a bit of indirection.

Also, variant ('gain' | 'loss') only affects color while the arrow direction and leading + come from changeNum. If a caller ever passes variant='gain'|'loss' with a contradictory or missing numeric change, the visuals could diverge from the intent; consider either deriving the icon/sign from variant in those cases or documenting that variant is purely cosmetic.

Also applies to: 99-107

apps/agentic-server/src/tools/getNewCoins.ts (1)

17-30: Consider handling edge cases in formatTimeAgo.

The function assumes positive time differences. If activated_at is in the future (data anomaly) or very old (months/years), the output may be misleading.

Consider adding handling for edge cases:

 function formatTimeAgo(timestamp: number): string {
   const now = Date.now()
   const diffMs = now - timestamp * 1000
+  
+  if (diffMs < 0) return 'Just now' // Future timestamp edge case
+  
   const diffHours = Math.floor(diffMs / (1000 * 60 * 60))
   const diffDays = Math.floor(diffHours / 24)
 
   if (diffDays > 0) {
     return `${diffDays} day${diffDays === 1 ? '' : 's'} ago`
   }
   if (diffHours > 0) {
     return `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`
   }
   return 'Just now'
 }
apps/agentic-server/src/routes/chat.ts (1)

36-46: Type signature could be simplified.

The generic constraint uses execute: (args: never) => unknown which is unconventional. While the as T cast makes it work, this loses compile-time safety for the wrapped execute call.

Consider a cleaner signature:

-function wrapToolWithLogging<
-  T extends { description: string; inputSchema: unknown; execute: (args: never) => unknown },
->(name: string, tool: T): T {
+function wrapToolWithLogging<TArgs, TReturn>(
+  name: string,
+  tool: { description: string; inputSchema: unknown; execute: (args: TArgs) => TReturn }
+): typeof tool {
   return {
     ...tool,
-    execute: (args: Parameters<T['execute']>[0]) => {
+    execute: (args: TArgs) => {
       console.log(`[Tool] ${name}:`, JSON.stringify(args, null, 2))
       return tool.execute(args)
     },
-  } as T
+  }
 }
apps/agentic-server/src/tools/getAssets.ts (1)

89-113: Potential mismatch between assetIds and staticAssets.

Line 99 calls getSimplePrices(assetIds) with the original input, but staticAssets (lines 93-96) may have filtered out invalid assets. If assetService.getAsset(id) returns undefined for some IDs, the price fetching will include IDs that won't appear in the final output.

This isn't a bug per se (extra prices are just ignored), but it's slightly inefficient.

Consider using the filtered asset IDs for price fetching:

   const staticAssets = assetIds
     .map(id => assetService.getAsset(id))
     .filter((a): a is NonNullable<typeof a> => a !== undefined)

   if (staticAssets.length === 0) return { assets: [] }

-  const prices = await getSimplePrices(assetIds)
+  const prices = await getSimplePrices(staticAssets.map(a => a.assetId))
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3f66c45 and 2b59446.

📒 Files selected for processing (24)
  • apps/agentic-chat/src/components/toolUIRegistry.tsx (2 hunks)
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/ui/AssetListItem.tsx (1 hunks)
  • apps/agentic-server/src/context.ts (1 hunks)
  • apps/agentic-server/src/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/api.ts (2 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/types.ts (1 hunks)
  • apps/agentic-server/src/routes/chat.ts (6 hunks)
  • apps/agentic-server/src/tools/getAssets.ts (2 hunks)
  • apps/agentic-server/src/tools/getCategories.ts (1 hunks)
  • apps/agentic-server/src/tools/getNewCoins.ts (1 hunks)
  • apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1 hunks)
  • apps/agentic-server/src/tools/getTopGainersLosers.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingPools.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingTokens.ts (1 hunks)
  • apps/agentic-server/src/tools/initiateSwap.ts (4 hunks)
  • apps/agentic-server/src/tools/portfolio.ts (4 hunks)
  • apps/agentic-server/src/tools/receive.ts (1 hunks)
  • apps/agentic-server/src/tools/send.ts (1 hunks)
  • apps/agentic-server/src/tools/transactionHistory.ts (1 hunks)
  • apps/agentic-server/src/utils/assetHelpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • apps/agentic-server/src/tools/initiateSwap.ts
  • apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx
  • apps/agentic-server/src/tools/getCategories.ts
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx
  • apps/agentic-server/src/tools/receive.ts
  • apps/agentic-server/src/tools/transactionHistory.ts
  • apps/agentic-server/src/tools/getShapeShiftKnowledge.ts
  • apps/agentic-chat/src/components/toolUIRegistry.tsx
  • apps/agentic-server/src/index.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-22T20:32:10.539Z
Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 76
File: apps/agentic-server/src/mastra/tools/asset/coingecko/constants.ts:1-10
Timestamp: 2025-09-22T20:32:10.539Z
Learning: When cross-app dependencies are identified (like server code importing from chat packages), the user prefers to extract shared constants into dedicated packages in the packages/ directory following the existing pattern of shapeshiftoss/types and shapeshiftoss/utils.

Applied to files:

  • apps/agentic-server/src/routes/chat.ts
🧬 Code graph analysis (8)
apps/agentic-server/src/tools/getTrendingPools.ts (2)
apps/agentic-server/src/lib/asset/coingecko/types.ts (3)
  • TrimmedTrendingPool (214-225)
  • TrendingPoolIncluded (148-159)
  • TrendingPoolData (105-146)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getTrendingPools (134-142)
apps/agentic-server/src/tools/getTrendingTokens.ts (3)
apps/agentic-server/src/lib/asset/coingecko/types.ts (2)
  • TrimmedTrendingCoin (192-200)
  • TrendingCoinItem (37-60)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getTrendingSearch (107-110)
packages/caip/src/adapters/coingecko/index.ts (1)
  • coingeckoToAssetIds (57-57)
apps/agentic-server/src/tools/getNewCoins.ts (3)
apps/agentic-server/src/lib/asset/coingecko/types.ts (2)
  • TrimmedNewCoin (236-243)
  • NewCoinData (182-187)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getNewCoins (165-168)
packages/caip/src/adapters/coingecko/index.ts (1)
  • coingeckoToAssetIds (57-57)
apps/agentic-chat/src/components/ui/AssetListItem.tsx (5)
packages/caip/src/constants.ts (1)
  • AssetId (176-176)
apps/agentic-chat/src/lib/utils.ts (1)
  • cn (5-7)
apps/agentic-chat/src/lib/bignumber.ts (1)
  • bnOrZero (5-13)
apps/agentic-chat/src/components/ui/AssetIcon.tsx (1)
  • AssetIcon (12-47)
apps/agentic-chat/src/lib/number.ts (2)
  • formatFiat (70-82)
  • formatPercent (98-117)
apps/agentic-server/src/utils/assetHelpers.ts (4)
apps/agentic-server/src/lib/schemas/swapSchemas.ts (1)
  • AssetInput (76-76)
packages/types/src/asset.ts (1)
  • Asset (28-28)
apps/agentic-server/src/index.ts (1)
  • executeGetAssets (5-5)
apps/agentic-server/src/tools/getAssets.ts (1)
  • executeGetAssets (115-129)
apps/agentic-server/src/routes/chat.ts (7)
apps/agentic-server/src/tools/getAssets.ts (1)
  • getAssetsTool (131-146)
apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1)
  • getShapeShiftKnowledgeTool (60-64)
apps/agentic-server/src/tools/getTrendingTokens.ts (1)
  • getTrendingTokensTool (39-54)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)
  • getTopGainersLosersTool (53-68)
apps/agentic-server/src/tools/getTrendingPools.ts (1)
  • getTrendingPoolsTool (77-81)
apps/agentic-server/src/tools/getCategories.ts (1)
  • getCategoriesTool (42-46)
apps/agentic-server/src/tools/getNewCoins.ts (1)
  • getNewCoinsTool (53-68)
apps/agentic-server/src/tools/getTopGainersLosers.ts (5)
apps/agentic-server/src/index.ts (4)
  • GetTopGainersLosersInput (75-75)
  • GetTopGainersLosersOutput (76-76)
  • TrimmedGainerLoserCoin (93-93)
  • executeGetTopGainersLosers (74-74)
apps/agentic-server/src/lib/asset/coingecko/types.ts (1)
  • TrimmedGainerLoserCoin (202-212)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getTopGainersLosers (116-128)
apps/agentic-server/src/lib/asset/coingecko/index.ts (1)
  • getTopGainersLosers (5-5)
packages/caip/src/adapters/coingecko/index.ts (1)
  • coingeckoToAssetIds (57-57)
apps/agentic-server/src/lib/asset/coingecko/types.ts (2)
apps/agentic-server/src/lib/asset/coingecko/index.ts (10)
  • TrendingCoinItem (20-20)
  • TrendingSearchResponse (13-13)
  • TopGainersLosersResponse (14-14)
  • TrendingPoolData (21-21)
  • TrendingPoolIncluded (22-22)
  • TrendingPoolsResponse (15-15)
  • CategoryData (18-18)
  • CategoriesResponse (16-16)
  • NewCoinData (19-19)
  • NewCoinsResponse (17-17)
apps/agentic-server/src/index.ts (5)
  • TrimmedTrendingCoin (92-92)
  • TrimmedGainerLoserCoin (93-93)
  • TrimmedTrendingPool (94-94)
  • TrimmedCategory (95-95)
  • TrimmedNewCoin (96-96)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: main
🔇 Additional comments (31)
apps/agentic-server/src/tools/send.ts (1)

121-132: LGTM! Clear UX guidance for the AI agent.

The expanded description provides excellent context for the AI agent:

  • Clarifies what the UI card already displays
  • Establishes the "supplement, not duplicate" principle
  • Offers natural, concise response examples
  • Sets clear expectations for when to elaborate

This aligns with the broader PR pattern of UI-focused tool descriptions.

apps/agentic-server/src/utils/assetHelpers.ts (1)

5-11: Switch to executeGetAssets preserves resolveAsset behavior

Using executeGetAssets({ searchTerm, network }) keeps the zero/one/many‑asset handling intact while routing through the unified asset lookup, so this refactor looks safe and consistent with the new API surface.

apps/agentic-server/src/tools/portfolio.ts (1)

11-12: Portfolio integration with executeGetAssets and priceChange handling looks solid

Fetching assets via executeGetAssets({ assetIds }) correctly delegates to the bulk pricing path, and mapping priceChange24h: asset.priceChange24h ?? undefined aligns with the optional number type instead of leaking null. The updated portfolioTool description also matches the new UI‑card convention.

Also applies to: 78-79, 98-106, 153-167

apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1)

11-51: TopGainersLosersUI wiring matches server types and tool UI patterns

The component cleanly reuses useToolStateRender, safely bails when there’s no data, and renders gainers/losers via AssetListItem with the expected { gainers, losers, duration } shape from the server; this is consistent with the other tool UIs and looks good.

Also applies to: 53-88

apps/agentic-server/src/lib/asset/coingecko/index.ts (1)

1-23: Barrel export cleanly centralizes CoinGecko APIs and types

This index module neatly re‑exports the CoinGecko functions and their value/response types, simplifying imports elsewhere without changing behavior.

apps/agentic-server/src/tools/getTrendingPools.ts (1)

6-19: Trending pools tool mapping and fallbacks look robust

The schema/defaults, included‑resource maps, and pool mapper all line up with TrimmedTrendingPool, and the fallbacks for missing tokens/dex/network/metrics ('Unknown', 'Unknown DEX', 'unknown', null) make this resilient to partial API responses. The tool wrapper is consistent with the rest of the CoinGecko tools.

Also applies to: 21-75, 77-81

apps/agentic-server/src/tools/getTrendingTokens.ts (1)

7-15: Trending tokens tool is consistent and safely maps CoinGecko data

executeGetTrendingTokens enforces a sensible limit, slices the API response, and maps to TrimmedTrendingCoin with appropriate null fallbacks and optional assetId, matching the shared types and patterns used by the other CoinGecko-backed tools.

Also applies to: 17-37, 39-54

apps/agentic-server/src/lib/asset/coingecko/api.ts (6)

5-14: LGTM!

Import additions are clean and correctly typed to match the new API functions.


103-110: LGTM!

Simple, well-documented endpoint wrapper following the established pattern.


116-128: LGTM!

Good use of typed union literals for duration and topCoins parameters with sensible defaults.


134-142: LGTM!

Properly includes related entities (base_token,quote_token,dex,network) for enriched pool data.


148-159: LGTM!

The order parameter type properly enumerates all valid CoinGecko sort options.


165-168: LGTM!

Simple endpoint wrapper consistent with the other functions.

apps/agentic-server/src/tools/getNewCoins.ts (4)

1-5: LGTM!

Imports are appropriate for the tool's functionality.


7-9: LGTM!

Schema properly defines optional limit with reasonable bounds (1-20) and self-documenting description.


32-51: LGTM!

The execution logic is clean - fetches data, slices to limit, and maps to trimmed format. The assetId: assetIds[0] correctly handles the case where no mapping exists (will be undefined).


53-67: LGTM!

Tool description follows the established pattern with clear UI card guidance and natural response examples.

apps/agentic-server/src/routes/chat.ts (4)

21-26: LGTM!

New tool imports are correctly added and alphabetically ordered.


79-81: LGTM!

Good refactoring - simple tools that don't need walletContext now use the unified logging wrapper.


144-149: LGTM!

All five new informational tools are properly registered with consistent logging wrappers.


194-199: LGTM!

Good addition to the system prompt - categorizing tools helps the LLM select the appropriate tool for user queries.

apps/agentic-server/src/tools/getAssets.ts (5)

32-34: LGTM!

Simplified output type consolidates previous basic and market data variants.


36-60: LGTM!

Good rename to enrichWithMarketData which better describes the function's purpose. Error handling returns null allowing callers to fallback gracefully.


62-87: LGTM!

Clean single-asset flow with proper fallback when CoinGecko enrichment fails.


115-129: LGTM!

Clear routing logic: single asset (by search or single ID) goes to detailed fetch, multiple IDs go to bulk pricing.


131-146: LGTM!

Tool description follows the established pattern with clear UI card guidance.

apps/agentic-server/src/lib/asset/coingecko/types.ts (5)

36-74: LGTM!

Well-structured types matching the CoinGecko trending search API response. The nested data object with optional fields properly handles the variable response shape.


76-95: LGTM!

Clean type definition for gainers/losers with appropriate optional fields for different time periods.


97-164: LGTM!

Comprehensive pool types capturing the nested structure of the onchain API response, including relationships and included entities.


166-189: LGTM!

Categories and new coins types are straightforward and match the API response shapes.


191-243: LGTM!

Trimmed types effectively reduce payload size for LLM context while preserving essential fields. Good design decision to include assetId as optional for UI linking.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)

23-51: Align supported durations with exposed price-change fields and de-duplicate logging

Two small gaps here:

  1. The schema and API both support '14d' and '30d', and the response type includes usd_14d_change/usd_30d_change, but TrimmedGainerLoserCoin + mapCoin only expose 1h/24h/7d changes. Either:

    • Extend TrimmedGainerLoserCoin and mapCoin to surface 14d/30d changes as optional fields, or
    • Restrict duration to the intervals you actually expose (e.g., '1h' | '24h' | '7d').
  2. executeGetTopGainersLosers logs its input, and in routes/chat.ts this tool is also wrapped with wrapToolWithLogging, so each call will be logged twice. Similar to getNewCoins, consider removing the local console.log and relying on the wrapper for logging.

🧹 Nitpick comments (10)
apps/agentic-server/src/tools/receive.ts (1)

34-45: Updated receiveTool description is clear and matches the card-centric UX

The new description does a good job of:

  • Making the card the primary surface (address + QR) and clearly stating the tool should supplement, not duplicate.
  • Steering the model toward short, natural confirmations by default and only elaborating when asked.

One small optional refinement: the hard “Do not repeat the address” rule might be too strict for edge cases (e.g., explicit user request, accessibility/screen readers). You could soften it to something like “Avoid re-printing the full address unless the user explicitly asks for it.”

apps/agentic-server/src/tools/getCategories.ts (1)

21-40: Clean implementation with proper defaults and null-safe mapping.

The executor correctly:

  • Applies sensible defaults for sortBy and limit
  • Constructs the API order parameter appropriately
  • Maps the response with null-safe handling using ??

The console.log on line 22 is acceptable for debugging, but consider using a structured logger for consistency with production logging practices if one exists in the codebase.

apps/agentic-server/src/tools/getNewCoins.ts (2)

17-30: Time-ago helper works but treats future timestamps as “Just now”

If activated_at is ever slightly in the future (clock skew, delayed ingestion), diffMs becomes negative and you still return 'Just now'. Consider clamping diffMs at 0 or explicitly handling future values (e.g., 'in X hours' or '0 hours ago') if that matters for the UI.


32-51: Avoid duplicate logging now that tools are wrapped in chat.ts

executeGetNewCoins logs its input, and in apps/agentic-server/src/routes/chat.ts this tool is also passed through wrapToolWithLogging, so each call will be logged twice. Consider dropping the local console.log and relying on the shared wrapper for consistent, centralized logging.

apps/agentic-server/src/tools/getTopGainersLosers.ts (1)

7-21: Consider narrowing the output duration type for better safety

GetTopGainersLosersOutput.duration is typed as string even though the schema only permits '1h' | '24h' | '7d' | '14d' | '30d'. Narrowing this to the same union would give better type safety to consumers without changing runtime behavior.

apps/agentic-server/src/routes/chat.ts (2)

77-81: Central logging is good; consider cleaning up per-tool console.log calls

Using wrapToolWithLogging for mathCalculator, getAssets, account, switchNetwork, and the new market-data tools gives you a nice, consistent logging story. Some of those tool executors (e.g., executeGetNewCoins, executeGetTopGainersLosers) also perform their own console.log, which will now double-log arguments.

Suggested follow-up: standardize on router-level logging via wrapToolWithLogging and strip redundant logging from the tool modules themselves.

Also applies to: 127-149


36-46: The type constraint is awkward but currently safe; the concern about argument loss is theoretical

All tools in the codebase follow a single-parameter execute signature (e.g., execute: (input: SomeInput) => Promise<Output>). The current constraint correctly enforces this pattern for all 11 wrapped tools. The use of never in the type is semantically confusing, but it doesn't cause practical issues today since no multi-argument tools exist. The suggested refactor using (...args: any[]) => unknown is defensive programming—it would prevent accidental argument loss if a multi-argument tool were added—but it's not addressing a current problem. This is worth considering for future extensibility, though the current approach is type-safe as written.

apps/agentic-server/src/tools/portfolio.ts (1)

75-106: executeGetAssets integration and priceChange24h threading look good; consider passing network explicitly

Routing assetIds through executeGetAssets cleanly reuses the bulk pricing path, and mapping priceChange24h: asset.priceChange24h ?? undefined keeps the portfolio type aligned with the new optional market-data field while allowing JSON serialization to drop missing values.

If you want to make the network semantics more explicit (and avoid relying on chainIdToNetwork inference in getBulkAssetPrices), you could also pass network into executeGetAssets({ assetIds, network }); behavior should be equivalent today but slightly clearer.

apps/agentic-server/src/tools/getAssets.ts (2)

89-113: Tighten getBulkAssetPrices to price only known assets and optionally fail open on pricing errors

The bulk path is straightforward, but there are two small improvements you might consider:

  • You currently call getSimplePrices(assetIds) even for IDs where assetService.getAsset returned undefined. Passing only the resolved IDs would avoid unnecessary downstream lookups and keep behavior aligned with the assets you actually return:

  • const prices = await getSimplePrices(assetIds)

  • const priceMap = new Map(prices.map(p => [p.assetId, { price: p.price, priceChange24h: p.priceChange24h }]))

  • const pricedAssetIds = staticAssets.map(a => a.assetId)
  • const prices = await getSimplePrices(pricedAssetIds)
  • const priceMap = new Map(
  • prices.map(p => [p.assetId, { price: p.price, priceChange24h: p.priceChange24h }]),
  • )

- Unlike the single-asset path (which catches enrichment failures), any exception from `getSimplePrices` will currently bubble up and fail the entire tool. If you want similar resilience for bulk requests, you could wrap this call in a `try/catch` and fall back to returning `staticAssets` with `price: '0'` and inferred `network`.

---

`115-128`: **executeGetAssets routing is clear; consider toning down logging if traffic is high**

The routing logic (searchTerm/single asset → `getAssetWithMarketData`, multi-asset → `getBulkAssetPrices`, else empty) is easy to follow and matches the intended API.

If this tool ends up on a hot path, you may eventually want to downgrade `console.log('[getAssets]:', input)` to a debug-level logger or gate it by environment to avoid noisy logs, but it’s fine for initial rollout.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used**: CodeRabbit UI

**Review profile**: CHILL

**Plan**: Pro

**Disabled knowledge base sources:**

- Linear integration is disabled by default for public repositories

> You can enable these sources in your CodeRabbit configuration.

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2b594463552c3b4c427c04833ac743c6ad88313a and ea292abc50ea97fb6f57dc98e08db17c85cb486e.

</details>

<details>
<summary>📒 Files selected for processing (24)</summary>

* `apps/agentic-chat/src/components/toolUIRegistry.tsx` (2 hunks)
* `apps/agentic-chat/src/components/tools/NewCoinsUI.tsx` (1 hunks)
* `apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx` (1 hunks)
* `apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx` (1 hunks)
* `apps/agentic-chat/src/components/ui/AssetListItem.tsx` (1 hunks)
* `apps/agentic-server/src/context.ts` (1 hunks)
* `apps/agentic-server/src/index.ts` (1 hunks)
* `apps/agentic-server/src/lib/asset/coingecko/api.ts` (2 hunks)
* `apps/agentic-server/src/lib/asset/coingecko/index.ts` (1 hunks)
* `apps/agentic-server/src/lib/asset/coingecko/types.ts` (1 hunks)
* `apps/agentic-server/src/routes/chat.ts` (6 hunks)
* `apps/agentic-server/src/tools/getAssets.ts` (2 hunks)
* `apps/agentic-server/src/tools/getCategories.ts` (1 hunks)
* `apps/agentic-server/src/tools/getNewCoins.ts` (1 hunks)
* `apps/agentic-server/src/tools/getShapeShiftKnowledge.ts` (1 hunks)
* `apps/agentic-server/src/tools/getTopGainersLosers.ts` (1 hunks)
* `apps/agentic-server/src/tools/getTrendingPools.ts` (1 hunks)
* `apps/agentic-server/src/tools/getTrendingTokens.ts` (1 hunks)
* `apps/agentic-server/src/tools/initiateSwap.ts` (4 hunks)
* `apps/agentic-server/src/tools/portfolio.ts` (4 hunks)
* `apps/agentic-server/src/tools/receive.ts` (1 hunks)
* `apps/agentic-server/src/tools/send.ts` (1 hunks)
* `apps/agentic-server/src/tools/transactionHistory.ts` (1 hunks)
* `apps/agentic-server/src/utils/assetHelpers.ts` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (12)</summary>

* apps/agentic-server/src/tools/initiateSwap.ts
* apps/agentic-server/src/tools/getTrendingTokens.ts
* apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx
* apps/agentic-server/src/utils/assetHelpers.ts
* apps/agentic-server/src/context.ts
* apps/agentic-server/src/lib/asset/coingecko/index.ts
* apps/agentic-server/src/tools/send.ts
* apps/agentic-server/src/tools/getTrendingPools.ts
* apps/agentic-server/src/index.ts
* apps/agentic-server/src/tools/transactionHistory.ts
* apps/agentic-chat/src/components/toolUIRegistry.tsx
* apps/agentic-server/src/lib/asset/coingecko/types.ts

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>📚 Learning: 2025-09-22T20:32:10.539Z</summary>

Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 76
File: apps/agentic-server/src/mastra/tools/asset/coingecko/constants.ts:1-10
Timestamp: 2025-09-22T20:32:10.539Z
Learning: When cross-app dependencies are identified (like server code importing from chat packages), the user prefers to extract shared constants into dedicated packages in the packages/ directory following the existing pattern of shapeshiftoss/types and shapeshiftoss/utils.


**Applied to files:**
- `apps/agentic-server/src/routes/chat.ts`

</details>

</details><details>
<summary>🧬 Code graph analysis (5)</summary>

<details>
<summary>apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (4)</summary><blockquote>

<details>
<summary>apps/agentic-chat/src/components/tools/toolUIHelpers.tsx (2)</summary>

* `ToolUIComponentProps` (6-8)
* `useToolStateRender` (10-31)

</details>
<details>
<summary>apps/agentic-server/src/lib/asset/coingecko/types.ts (1)</summary>

* `TrimmedTrendingCoin` (192-200)

</details>
<details>
<summary>apps/agentic-chat/src/components/ui/ToolCard.tsx (1)</summary>

* `ToolCard` (71-78)

</details>
<details>
<summary>apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)</summary>

* `AssetListItem` (60-110)

</details>

</blockquote></details>
<details>
<summary>apps/agentic-server/src/tools/portfolio.ts (3)</summary><blockquote>

<details>
<summary>apps/agentic-server/src/index.ts (1)</summary>

* `executeGetAssets` (5-5)

</details>
<details>
<summary>apps/agentic-server/src/tools/getAssets.ts (1)</summary>

* `executeGetAssets` (115-129)

</details>
<details>
<summary>packages/types/src/asset.ts (1)</summary>

* `asset` (3-26)

</details>

</blockquote></details>
<details>
<summary>apps/agentic-server/src/tools/getNewCoins.ts (3)</summary><blockquote>

<details>
<summary>apps/agentic-server/src/lib/asset/coingecko/types.ts (2)</summary>

* `TrimmedNewCoin` (236-243)
* `NewCoinData` (182-187)

</details>
<details>
<summary>apps/agentic-server/src/lib/asset/coingecko/api.ts (1)</summary>

* `getNewCoins` (165-168)

</details>
<details>
<summary>packages/caip/src/adapters/coingecko/index.ts (1)</summary>

* `coingeckoToAssetIds` (57-57)

</details>

</blockquote></details>
<details>
<summary>apps/agentic-server/src/lib/asset/coingecko/api.ts (2)</summary><blockquote>

<details>
<summary>apps/agentic-server/src/lib/asset/coingecko/index.ts (10)</summary>

* `getTrendingSearch` (4-4)
* `TrendingSearchResponse` (13-13)
* `getTopGainersLosers` (5-5)
* `TopGainersLosersResponse` (14-14)
* `getTrendingPools` (6-6)
* `TrendingPoolsResponse` (15-15)
* `getCategories` (7-7)
* `CategoriesResponse` (16-16)
* `getNewCoins` (8-8)
* `NewCoinsResponse` (17-17)

</details>
<details>
<summary>apps/agentic-server/src/lib/asset/coingecko/types.ts (5)</summary>

* `TrendingSearchResponse` (62-74)
* `TopGainersLosersResponse` (92-95)
* `TrendingPoolsResponse` (161-164)
* `CategoriesResponse` (179-179)
* `NewCoinsResponse` (189-189)

</details>

</blockquote></details>
<details>
<summary>apps/agentic-server/src/routes/chat.ts (7)</summary><blockquote>

<details>
<summary>apps/agentic-server/src/tools/getAssets.ts (1)</summary>

* `getAssetsTool` (131-146)

</details>
<details>
<summary>apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1)</summary>

* `getShapeShiftKnowledgeTool` (60-64)

</details>
<details>
<summary>apps/agentic-server/src/tools/getTrendingTokens.ts (1)</summary>

* `getTrendingTokensTool` (39-54)

</details>
<details>
<summary>apps/agentic-server/src/tools/getTopGainersLosers.ts (1)</summary>

* `getTopGainersLosersTool` (53-68)

</details>
<details>
<summary>apps/agentic-server/src/tools/getTrendingPools.ts (1)</summary>

* `getTrendingPoolsTool` (77-81)

</details>
<details>
<summary>apps/agentic-server/src/tools/getCategories.ts (1)</summary>

* `getCategoriesTool` (42-46)

</details>
<details>
<summary>apps/agentic-server/src/tools/getNewCoins.ts (1)</summary>

* `getNewCoinsTool` (53-68)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (15)</summary><blockquote>

<details>
<summary>apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1)</summary><blockquote>

`60-64`: **LGTM!**

The updated description is more concise and aligns with the consistent pattern used across the new tools in this PR.

</blockquote></details>
<details>
<summary>apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1)</summary><blockquote>

`10-55`: **Well-structured component following established patterns.**

The implementation correctly uses `useToolStateRender` for state management and `AssetListItem` for consistent rendering. The 1-based ranking display is appropriate.

One consideration: returning `null` for empty tokens (lines 23-25) means the UI silently disappears. If this is intentional for cleaner UX, it's fine. Otherwise, consider showing an empty state message like "No trending tokens found."

</blockquote></details>
<details>
<summary>apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (1)</summary><blockquote>

`10-55`: **LGTM!**

The component follows the established pattern from `TrendingTokensUI` with appropriate differentiation (Sparkles icon, purple color, "Listed" subtitle). The implementation is consistent and well-structured.

</blockquote></details>
<details>
<summary>apps/agentic-chat/src/components/ui/AssetListItem.tsx (2)</summary><blockquote>

`30-58`: **Well-implemented fallback handling for icons.**

The `FallbackIcon` and `IconFromUrl` subcomponents provide good fallback behavior. The `onError` handler in `IconFromUrl` gracefully degrades to the initials-based fallback.

Minor observation: The `!url` check on line 46 is defensive since the parent already gates `IconFromUrl` rendering on `iconUrl` being truthy (line 86), but this extra safety is harmless.

---

`60-109`: **LGTM!**

The component is well-designed with:
- Clear icon rendering priority (assetId → iconUrl → fallback)
- Appropriate memoization for BigNumber conversion
- Flexible variant system for gain/loss styling
- Clean conditional rendering for optional price/change display

This reusable component will serve the multiple tool UIs well.

</blockquote></details>
<details>
<summary>apps/agentic-server/src/tools/getCategories.ts (1)</summary><blockquote>

`42-46`: **LGTM!**

The tool export follows the established pattern with a clear description indicating no UI card, consistent with other tools in this PR.

</blockquote></details>
<details>
<summary>apps/agentic-server/src/tools/getNewCoins.ts (1)</summary><blockquote>

`53-68`: **Tool contract is clear and aligned with the “supplement the card” pattern**

The description, schema, and trimmed output shape match the informational-card usage pattern from the other tools; nothing blocking here.

</blockquote></details>
<details>
<summary>apps/agentic-server/src/lib/asset/coingecko/api.ts (1)</summary><blockquote>

`103-168`: **New market-data wrapper functions look consistent and type-safe**

Each helper cleanly wraps a single endpoint with specific param unions and returns the matching response type, consistent with `./types`. Centralizing these calls behind the shared client and small wrappers looks good.

</blockquote></details>
<details>
<summary>apps/agentic-server/src/tools/getTopGainersLosers.ts (1)</summary><blockquote>

`53-68`: **Tool description and schema/output wiring look solid**

Description text, schema, executor, and exported tool object are coherent and follow the same “informational card” pattern as the other tools; no blockers here.

</blockquote></details>
<details>
<summary>apps/agentic-server/src/routes/chat.ts (1)</summary><blockquote>

`194-199`: **System prompt updates correctly reflect new tool surface**

The new **Tool Categories** section clearly lists the added informational tools (trending tokens, gainers/losers, new coins, categories, pools) and keeps behavior guidance consistent with the rest of the prompt. Looks good.

</blockquote></details>
<details>
<summary>apps/agentic-server/src/tools/portfolio.ts (2)</summary><blockquote>

`11-11`: **Switch to unified `executeGetAssets` entrypoint looks correct**

Using `executeGetAssets` here keeps the portfolio tool on the new consolidated API surface and avoids the deprecated basic variant; no further wiring changes are needed in this file.

---

`154-165`: **Updated `portfolioTool` description matches the new UI-card pattern**

The card-focused description and examples clearly instruct the model not to echo portfolio data and to respond tersely by default, which is consistent with the new informational tools and should help keep responses clean.

</blockquote></details>
<details>
<summary>apps/agentic-server/src/tools/getAssets.ts (3)</summary><blockquote>

`32-55`: **Market-data enrichment mapping is solid; just confirm how `description` is rendered**

The `AssetWithMarketData` shape and field mapping from CoinGecko (`price`, caps, volumes, supplies, sentiment, rank) look consistent and defensively handle missing data with `null`/`'0'` fallbacks.

One thing to double-check: `data.description?.en` often contains HTML from CoinGecko. If any UI renders this as HTML instead of plain text, ensure it’s properly sanitized/escaped to avoid XSS issues.

---

`62-87`: **Single-asset flow and fallback behavior look correct**

The single-asset path (search term or one assetId) cleanly:

- Resolves a base asset.
- Infers a network (falling back to `'ethereum'`).
- Attempts CoinGecko enrichment and falls back to the static asset with `price: '0'` if anything fails.

This is a reasonable balance between enriching results and staying resilient when market data isn’t available.

---

`132-146`: **Updated `getAssetsTool` description and executor wiring look good**

The new description clearly communicates the UI-card behavior and keeps responses terse by default, and wiring `execute` to `executeGetAssets` matches the new unified API surface.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)

31-44: Missing priceChange14d and priceChange30d fields in the mapper.

The schema accepts '14d' and '30d' durations, and the API returns usd_14d_change and usd_30d_change fields in GainerLoserCoin, but the mapper only populates priceChange1h, priceChange24h, and priceChange7d. Users requesting 14d/30d data won't see the corresponding price changes.

Either add the missing fields to the mapper and type:

 const mapCoin = (coin: (typeof data.top_gainers)[0]): TrimmedGainerLoserCoin => {
   const assetIds = coingeckoToAssetIds(coin.id)
   return {
     id: coin.id,
     name: coin.name,
     symbol: coin.symbol,
     price: coin.usd,
     priceChange24h: coin.usd_24h_change,
     priceChange1h: coin.usd_1h_change,
     priceChange7d: coin.usd_7d_change,
+    priceChange14d: coin.usd_14d_change,
+    priceChange30d: coin.usd_30d_change,
     marketCapRank: coin.market_cap_rank,
     assetId: assetIds[0],
   }
 }

Or narrow the allowed duration values to '1h' | '24h' | '7d' if you don't intend to expose longer periods.

apps/agentic-server/src/lib/asset/coingecko/types.ts (1)

202-212: Add missing priceChange14d and priceChange30d fields.

GainerLoserCoin includes usd_14d_change and usd_30d_change (lines 88-89), but TrimmedGainerLoserCoin only has fields up to 7d. This should be updated to support the full range of durations allowed by the tool schema.

 export type TrimmedGainerLoserCoin = {
   id: string
   name: string
   symbol: string
   price: number
   priceChange24h: number
   priceChange1h?: number
   priceChange7d?: number
+  priceChange14d?: number
+  priceChange30d?: number
   marketCapRank: number | null
   assetId?: string
 }
🧹 Nitpick comments (7)
apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1)

10-55: Tighten output typing and consider an explicit empty-state

The UI flow looks solid. Two small refinements you might consider:

  • Instead of casting output as { tokens: TrimmedTrendingCoin[] }, import and use the concrete tool output type from the server package so type drift is caught at compile time.
  • When tokens is empty you currently return null, which means the whole card disappears; if this tool is user-invoked, a short “No trending tokens found” message might be a nicer UX than rendering nothing.
apps/agentic-server/src/tools/initiateSwap.ts (1)

323-341: Avoid double-resolving sellAsset in the USD swap path

In executeInitiateSwapUsd you resolve sellAsset (including a price lookup via resolveAssetgetAssetPrices) to compute sellAmountCrypto, and then executeSwapInternal resolves both assets again via resolveSwapAssets, which triggers another price lookup for the same sell asset.

This is functionally correct, but:

  • It adds an extra asset/price lookup on every USD swap.
  • It can introduce slight drift between the price used to derive sellAmountCrypto and the price used later for USD summaries.

If you want to tighten this up, consider passing pre-resolved assets into executeSwapInternal (or extracting a shared helper that both paths can use) so the USD-path only resolves/prices the sell asset once.

apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)

11-110: Well-structured list item; minor nits around change handling

This component is nicely factored (icon fallback, URL loader, main row). Two small, non-blocking nits:

  • changeNum is computed on every render even when priceChange24h is null/undefined; you could gate bnOrZero behind hasChange to skip unnecessary work for rows without change data.
  • With changeNum.gte(0) you’ll show a “trending up” icon for exactly 0% moves; if you’d prefer a neutral or “no change” representation, you might special-case changeNum.isZero().

Neither is critical; just potential polish if you revisit this component.

apps/agentic-server/src/lib/asset/prices.ts (1)

12-33: Consider tightening the getSimplePrices call to known assets and de-duping IDs

Functionally this looks good, but there are a couple of easy efficiency wins:

  • You currently call getSimplePrices(assetIds) even though you filter out unknown IDs when building staticAssets. If callers ever pass bad IDs, you may be asking CoinGecko for prices you’ll never use. Passing staticAssets.map(a => a.assetId) instead would align the remote call with the assets you actually return.
  • If assetIds can contain duplicates, a simple Set-based dedupe before calling getSimplePrices would avoid redundant lookups while preserving the returned order via staticAssets.

Not blocking, but worth considering if this helper ends up on hot paths like portfolio or batch tools.

apps/agentic-server/src/tools/getTrendingPools.ts (1)

6-81: Trending pools mapping looks solid; a few small type/ergonomic tweaks

The mapping from the raw CoinGecko response into TrimmedTrendingPool is careful and defensive (good use of safe fallbacks for missing relationships). A few minor refinements you might consider:

  • limit is a number but not constrained to integers; if a caller passed 3.5, slice(0, limit) would effectively use 3. If that matters, you could normalize (e.g., Math.floor(limit)) or validate/round before slicing.
  • GetTrendingPoolsOutput.duration is typed as string even though it’s always one of '5m' | '1h' | '6h' | '24h'. Tightening that type makes downstream consumers safer.
  • The console.log('[getTrendingPools]:', input) is useful during development but may get noisy in production; switching to your structured logger or removing once this endpoint is stable would keep logs cleaner.

All low-priority; the core implementation looks correct.

apps/agentic-server/src/routes/chat.ts (1)

36-46: Consider improving the type signature for better type safety.

The never type for args loses type information. A more precise generic signature would preserve the execute function's parameter type:

-function wrapToolWithLogging<
-  T extends { description: string; inputSchema: unknown; execute: (args: never) => unknown },
->(name: string, tool: T): T {
+function wrapToolWithLogging<TArgs, TReturn, T extends { description: string; inputSchema: unknown; execute: (args: TArgs) => TReturn }>(
+  name: string,
+  tool: T
+): T {
   return {
     ...tool,
-    execute: (args: Parameters<T['execute']>[0]) => {
+    execute: (args: TArgs) => {
       console.log(`[Tool] ${name}:`, JSON.stringify(args, null, 2))
       return tool.execute(args)
     },
   } as T
 }

That said, the current implementation works correctly at runtime since TypeScript erases types anyway.

apps/agentic-server/src/tools/getAssets.ts (1)

62-87: Clarify behavior when both searchTerm and assetId are provided.

When both parameters are supplied, searchTerm silently takes precedence (lines 65-69). Consider either:

  1. Documenting this in the schema descriptions, or
  2. Using assetId when provided (more specific lookup) and falling back to searchTerm
-  const asset = searchTerm
-    ? assetService.search(searchTerm, network)[0]
-    : assetId
-      ? assetService.getAsset(assetId)
-      : undefined
+  const asset = assetId
+    ? assetService.getAsset(assetId)
+    : searchTerm
+      ? assetService.search(searchTerm, network)[0]
+      : undefined

This prioritizes the more specific assetId lookup over the fuzzy searchTerm search.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ea292ab and 810111f.

📒 Files selected for processing (25)
  • apps/agentic-chat/src/components/toolUIRegistry.tsx (2 hunks)
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/ui/AssetListItem.tsx (1 hunks)
  • apps/agentic-server/src/context.ts (1 hunks)
  • apps/agentic-server/src/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/api.ts (2 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/types.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/prices.ts (1 hunks)
  • apps/agentic-server/src/routes/chat.ts (6 hunks)
  • apps/agentic-server/src/tools/getAssets.ts (3 hunks)
  • apps/agentic-server/src/tools/getCategories.ts (1 hunks)
  • apps/agentic-server/src/tools/getNewCoins.ts (1 hunks)
  • apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1 hunks)
  • apps/agentic-server/src/tools/getTopGainersLosers.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingPools.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingTokens.ts (1 hunks)
  • apps/agentic-server/src/tools/initiateSwap.ts (3 hunks)
  • apps/agentic-server/src/tools/portfolio.ts (4 hunks)
  • apps/agentic-server/src/tools/receive.ts (1 hunks)
  • apps/agentic-server/src/tools/send.ts (1 hunks)
  • apps/agentic-server/src/tools/transactionHistory.ts (1 hunks)
  • apps/agentic-server/src/utils/assetHelpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (12)
  • apps/agentic-server/src/tools/send.ts
  • apps/agentic-server/src/tools/receive.ts
  • apps/agentic-server/src/tools/getTrendingTokens.ts
  • apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx
  • apps/agentic-server/src/tools/getShapeShiftKnowledge.ts
  • apps/agentic-chat/src/components/toolUIRegistry.tsx
  • apps/agentic-server/src/tools/getCategories.ts
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx
  • apps/agentic-server/src/context.ts
  • apps/agentic-server/src/tools/getNewCoins.ts
  • apps/agentic-server/src/tools/portfolio.ts
  • apps/agentic-server/src/tools/transactionHistory.ts
🧰 Additional context used
🧬 Code graph analysis (3)
apps/agentic-server/src/tools/getTrendingPools.ts (2)
apps/agentic-server/src/lib/asset/coingecko/types.ts (3)
  • TrimmedTrendingPool (214-225)
  • TrendingPoolIncluded (148-159)
  • TrendingPoolData (105-146)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getTrendingPools (108-116)
apps/agentic-server/src/tools/getAssets.ts (5)
packages/types/src/network.ts (2)
  • NETWORKS (23-42)
  • chainIdToNetwork (84-86)
packages/types/src/asset.ts (2)
  • asset (3-26)
  • Asset (28-28)
packages/utils/src/AssetService.ts (1)
  • assetService (135-135)
packages/utils/src/index.ts (1)
  • assetService (35-35)
packages/caip/src/adapters/coingecko/index.ts (1)
  • assetIdToCoingecko (59-59)
apps/agentic-server/src/routes/chat.ts (7)
apps/agentic-server/src/tools/getAssets.ts (1)
  • getAssetsTool (101-116)
apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1)
  • getShapeShiftKnowledgeTool (60-64)
apps/agentic-server/src/tools/getTrendingTokens.ts (1)
  • getTrendingTokensTool (39-54)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)
  • getTopGainersLosersTool (53-68)
apps/agentic-server/src/tools/getTrendingPools.ts (1)
  • getTrendingPoolsTool (77-81)
apps/agentic-server/src/tools/getCategories.ts (1)
  • getCategoriesTool (42-46)
apps/agentic-server/src/tools/getNewCoins.ts (1)
  • getNewCoinsTool (53-68)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: main
🔇 Additional comments (15)
apps/agentic-server/src/utils/assetHelpers.ts (1)

8-24: Confirm first-result selection semantics in resolveAsset

assetService.search may return multiple candidates but you now always take assets[0] and treat that as the resolved asset. That’s fine if search is ordered deterministically with the “best” match first, but it does change behavior vs explicit multi-match handling (e.g. ambiguous symbols across networks). It’d be good to confirm this ordering guarantee and whether you still want to surface ambiguity to the caller in any cases (like cross-chain symbols), or if “first match wins” is now the intentional contract.

apps/agentic-server/src/tools/initiateSwap.ts (2)

291-303: Updated initiateSwapTool description looks clear and card-centric

The new description tightly scopes the tool to the UI card and avoids duplicating card data in text responses. No code issues here; this should help produce more concise assistant output around swaps.


345-356: initiateSwapUsdTool description aligns well with the new card UX

Same as the crypto-amount variant, the updated description is focused on the UI card and gives the agent clear guidance to avoid repeating data already visible to the user. Implementation looks good.

apps/agentic-server/src/lib/asset/coingecko/index.ts (1)

1-23: Expanded CoinGecko exports look consistent and complete

Re-exporting the new API functions (getTrendingSearch, getTopGainersLosers, getTrendingPools, getCategories, getNewCoins) and their response/trimmed types from this index keeps the CoinGecko integration surface centralized. Names are consistent with the underlying api and types modules; no issues here.

apps/agentic-server/src/index.ts (1)

66-97: New informational tools and trimmed types are cleanly exposed from the server root

Exporting the new tools (getTrendingTokensTool, getTopGainersLosersTool, getTrendingPoolsTool, getCategoriesTool, getNewCoinsTool) plus their execute/input/output types, alongside the trimmed CoinGecko types, makes the agentic-server package a nice single entry point for both tool wiring and UI typing (e.g., TrendingTokensUI consuming TrimmedTrendingCoin). Names and groupings are consistent with the rest of the file.

apps/agentic-server/src/tools/getTopGainersLosers.ts (1)

53-68: LGTM!

The tool description is well-structured with clear guidance for UI card integration and appropriate response behavior.

apps/agentic-server/src/lib/asset/coingecko/api.ts (1)

89-134: LGTM!

The new API functions follow the existing patterns in this file: thin wrappers around axios calls with appropriate type annotations and sensible defaults. Error handling is delegated to callers, consistent with the existing getMarketData and getBulkPrices functions.

apps/agentic-server/src/routes/chat.ts (2)

79-81: LGTM!

The new tools are properly integrated with the logging wrapper. The distinction between tools using wrapToolWithLogging (stateless tools) vs inline wrappers (tools requiring walletContext injection) is logical.

Also applies to: 127-127, 144-149


194-199: LGTM!

The new Tool Categories section in the system prompt provides clear organization of available tools, improving the LLM's ability to select appropriate tools for user requests.

apps/agentic-server/src/tools/getAssets.ts (2)

36-60: LGTM!

The enrichWithMarketData function handles errors gracefully by logging and returning null, allowing callers to fall back to unenriched data. The field mapping from CoinGecko response to AssetWithMarketData is comprehensive.


101-116: LGTM!

The tool description follows the established pattern for UI card integration, guiding the LLM to supplement rather than duplicate displayed data.

apps/agentic-server/src/lib/asset/coingecko/types.ts (4)

36-95: LGTM!

The trending tokens and gainers/losers type definitions accurately model the CoinGecko API response structures with appropriate optional fields.


97-164: LGTM!

The trending pools types comprehensively model the nested structure including relationships for base/quote tokens, DEX, and network data.


166-189: LGTM!

Categories and new coins types are well-defined with appropriate optional fields matching the CoinGecko API responses.


191-201: LGTM!

The trimmed types for TrendingCoin, TrendingPool, Category, and NewCoin provide lean payloads for LLM context while preserving essential data for UI rendering.

Also applies to: 214-243

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)

31-44: Missing 14d/30d price change fields — previously flagged.

The schema supports '14d' and '30d' durations, but the mapper only populates priceChange1h, priceChange24h, and priceChange7d. This was already identified in a previous review.

🧹 Nitpick comments (7)
apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)

43-48: Tighten TypeScript types/narrowing for assetId and iconUrl conditionals

At runtime the conditionals are safe, but with strict typing there’s a good chance these patterns will complain:

  • IconFromUrl requires url: string, but it’s called as {!assetId && iconUrl && <IconFromUrl url={iconUrl} ... />}, where iconUrl is string | undefined.
  • Similarly, AssetIcon likely expects assetId: AssetId, but is called as {assetId && <AssetIcon assetId={assetId} ... />} where assetId is AssetId | undefined.

Consider one of:

  • Narrow before render:
const hasAssetId = !!assetId
const hasIconUrl = !!iconUrl

{hasAssetId && <AssetIcon assetId={assetId!} className="w-8 h-8" />}
{!hasAssetId && hasIconUrl && <IconFromUrl url={iconUrl!} symbol={symbol} />}
  • Or relax the child prop types to accept string | undefined and handle fallback inside.

This keeps the nice JSX conditionals while avoiding TS complaints in strict mode.

Also applies to: 72-88, 94-105

apps/agentic-server/src/lib/asset/coingecko/types.ts (1)

36-190: Types look good; consider minor tightening for assetId and nullable ranks

The new response and trimmed types align well with the API wrappers and intended UI usage. Two small optional refinements:

  • For the trimmed types, you could reuse AssetId instead of string for assetId to preserve stronger typing end‑to‑end.
  • If CoinGecko ever omits market_cap_rank in trending results, you may want marketCapRank: number | null on TrimmedTrendingCoin (to mirror GainerLoserCoin) to reflect that possibility.

Not blocking, but would make the types a bit more future‑proof.

Also applies to: 191-243

apps/agentic-server/src/utils/assetHelpers.ts (1)

2-5: resolveAsset correctly unifies search, pricing, and network resolution

The new flow (search → first match → price via getAssetPrices → inferred network) is coherent and handles missing price data by falling back to '0'. This should improve consistency with other price‑aware paths. There is a tiny redundancy in re‑looking up the asset inside getAssetPrices, but that’s a micro‑optimization you can defer.

Also applies to: 8-24

apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1)

63-71: Type assertion without runtime validation may cause subtle bugs.

The type assertion on output assumes a specific shape. If the tool output structure changes or is malformed, accessing data.gainers or data.losers could fail silently or cause unexpected behavior.

Consider adding a minimal runtime check or using a type guard:

  const data = output as
    | { gainers: TrimmedGainerLoserCoin[]; losers: TrimmedGainerLoserCoin[]; duration: string }
    | undefined

-  if (!data || (data.gainers.length === 0 && data.losers.length === 0)) {
+  if (!data || !Array.isArray(data.gainers) || !Array.isArray(data.losers)) {
+    return null
+  }
+
+  if (data.gainers.length === 0 && data.losers.length === 0) {
    return null
  }
apps/agentic-server/src/tools/getTrendingTokens.ts (1)

17-18: Redundant logging — wrapToolWithLogging already logs tool calls.

The console.log statement here duplicates the logging added by wrapToolWithLogging in chat.ts. Consider removing this line to avoid duplicate log entries.

 export async function executeGetTrendingTokens(input: GetTrendingTokensInput): Promise<GetTrendingTokensOutput> {
-  console.log('[getTrendingTokens]:', input)
-
   const limit = input.limit ?? 5
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)

23-24: Redundant logging — wrapToolWithLogging already logs tool calls.

Same as getTrendingTokens, this console.log duplicates the logging wrapper in chat.ts.

 export async function executeGetTopGainersLosers(input: GetTopGainersLosersInput): Promise<GetTopGainersLosersOutput> {
-  console.log('[getTopGainersLosers]:', input)
-
   const duration = input.duration ?? '24h'
apps/agentic-server/src/routes/chat.ts (1)

36-46: Type constraint could be improved for better safety.

The execute: (args: never) => unknown constraint is overly restrictive in the type definition but works at runtime due to the as T cast. Consider a more precise generic:

-function wrapToolWithLogging<
-  T extends { description: string; inputSchema: unknown; execute: (args: never) => unknown },
->(name: string, tool: T): T {
+function wrapToolWithLogging<TArgs, TReturn, T extends { description: string; inputSchema: unknown; execute: (args: TArgs) => TReturn }>(
+  name: string,
+  tool: T
+): T {
   return {
     ...tool,
-    execute: (args: Parameters<T['execute']>[0]) => {
+    execute: (args: TArgs) => {
       console.log(`[Tool] ${name}:`, JSON.stringify(args, null, 2))
       return tool.execute(args)
     },
   } as T
 }

That said, the current implementation works correctly at runtime.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 810111f and 8120fa9.

📒 Files selected for processing (25)
  • apps/agentic-chat/src/components/toolUIRegistry.tsx (2 hunks)
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/ui/AssetListItem.tsx (1 hunks)
  • apps/agentic-server/src/context.ts (1 hunks)
  • apps/agentic-server/src/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/api.ts (2 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/types.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/prices.ts (1 hunks)
  • apps/agentic-server/src/routes/chat.ts (6 hunks)
  • apps/agentic-server/src/tools/getAssets.ts (3 hunks)
  • apps/agentic-server/src/tools/getCategories.ts (1 hunks)
  • apps/agentic-server/src/tools/getNewCoins.ts (1 hunks)
  • apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1 hunks)
  • apps/agentic-server/src/tools/getTopGainersLosers.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingPools.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingTokens.ts (1 hunks)
  • apps/agentic-server/src/tools/initiateSwap.ts (3 hunks)
  • apps/agentic-server/src/tools/portfolio.ts (4 hunks)
  • apps/agentic-server/src/tools/receive.ts (1 hunks)
  • apps/agentic-server/src/tools/send.ts (1 hunks)
  • apps/agentic-server/src/tools/transactionHistory.ts (1 hunks)
  • apps/agentic-server/src/utils/assetHelpers.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/agentic-server/src/context.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • apps/agentic-server/src/tools/getCategories.ts
  • apps/agentic-server/src/tools/getTrendingPools.ts
  • apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx
  • apps/agentic-server/src/index.ts
  • apps/agentic-server/src/lib/asset/prices.ts
  • apps/agentic-server/src/tools/getNewCoins.ts
  • apps/agentic-chat/src/components/toolUIRegistry.tsx
  • apps/agentic-server/src/tools/receive.ts
🧰 Additional context used
🧬 Code graph analysis (6)
apps/agentic-server/src/tools/getTrendingTokens.ts (4)
apps/agentic-server/src/lib/asset/coingecko/types.ts (2)
  • TrimmedTrendingCoin (192-200)
  • TrendingCoinItem (37-60)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getTrendingSearch (89-92)
apps/agentic-server/src/lib/asset/coingecko/index.ts (2)
  • getTrendingSearch (4-4)
  • TrendingCoinItem (20-20)
packages/caip/src/adapters/coingecko/index.ts (1)
  • coingeckoToAssetIds (57-57)
apps/agentic-server/src/utils/assetHelpers.ts (4)
apps/agentic-server/src/lib/schemas/swapSchemas.ts (1)
  • AssetInput (76-76)
packages/types/src/asset.ts (1)
  • Asset (28-28)
apps/agentic-server/src/lib/asset/prices.ts (1)
  • getAssetPrices (12-33)
packages/types/src/network.ts (1)
  • chainIdToNetwork (84-86)
apps/agentic-server/src/tools/initiateSwap.ts (1)
apps/agentic-server/src/utils/assetHelpers.ts (1)
  • resolveAsset (8-25)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
apps/agentic-server/src/lib/asset/coingecko/types.ts (5)
  • TrendingSearchResponse (62-74)
  • TopGainersLosersResponse (92-95)
  • TrendingPoolsResponse (161-164)
  • CategoriesResponse (179-179)
  • NewCoinsResponse (189-189)
apps/agentic-server/src/lib/asset/coingecko/types.ts (2)
apps/agentic-server/src/lib/asset/coingecko/index.ts (10)
  • TrendingCoinItem (20-20)
  • TrendingSearchResponse (13-13)
  • TopGainersLosersResponse (14-14)
  • TrendingPoolData (21-21)
  • TrendingPoolIncluded (22-22)
  • TrendingPoolsResponse (15-15)
  • CategoryData (18-18)
  • CategoriesResponse (16-16)
  • NewCoinData (19-19)
  • NewCoinsResponse (17-17)
apps/agentic-server/src/index.ts (5)
  • TrimmedTrendingCoin (92-92)
  • TrimmedGainerLoserCoin (93-93)
  • TrimmedTrendingPool (94-94)
  • TrimmedCategory (95-95)
  • TrimmedNewCoin (96-96)
apps/agentic-server/src/routes/chat.ts (7)
apps/agentic-server/src/tools/getAssets.ts (1)
  • getAssetsTool (101-116)
apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1)
  • getShapeShiftKnowledgeTool (60-64)
apps/agentic-server/src/tools/getTrendingTokens.ts (1)
  • getTrendingTokensTool (39-54)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)
  • getTopGainersLosersTool (53-68)
apps/agentic-server/src/tools/getTrendingPools.ts (1)
  • getTrendingPoolsTool (77-81)
apps/agentic-server/src/tools/getCategories.ts (1)
  • getCategoriesTool (42-46)
apps/agentic-server/src/tools/getNewCoins.ts (1)
  • getNewCoinsTool (39-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: main
🔇 Additional comments (14)
apps/agentic-server/src/tools/send.ts (1)

121-132: Send tool description aligns well with new UI‑card pattern

The updated description clearly constrains responses to supplement the card and provides good default phrasing; no behavioral risks here.

apps/agentic-chat/src/components/ui/AssetListItem.tsx (1)

30-41: Overall AssetListItem implementation looks solid

Icon fallback behavior, price/change guards, and variant-based coloring are all straightforward and cohesive; aside from the TS‑narrowing note above, this is ready to use as a shared row component.

Also applies to: 50-58, 79-108

apps/agentic-server/src/tools/transactionHistory.ts (1)

113-125: Transaction history description matches the new UI‑card guidance

The updated description clearly frames this as a card‑backed tool with concise default responses; no impact on existing query/filter behavior.

apps/agentic-server/src/lib/asset/coingecko/api.ts (1)

5-14: New CoinGecko API wrappers are straightforward and consistent with existing client

The added functions (getTrendingSearch, getTopGainersLosers, getTrendingPools, getCategories, getNewCoins) cleanly wrap the respective endpoints, reuse the shared axios client, and keep error propagation simple. Combined with the existing getSimplePrices fallback behavior, this is a solid foundation for the new informational tools.

Also applies to: 31-87, 89-134

apps/agentic-server/src/tools/portfolio.ts (1)

6-8: Portfolio now leverages shared pricing helper and card‑centric description

Switching to getAssetPrices for balance enrichment keeps pricing logic centralized and lets you surface priceChange24h cleanly. The updated portfolioTool description matches the new UI‑card interaction model and shouldn’t affect existing behavior.

Also applies to: 75-113, 153-165

apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1)

18-51: LGTM!

The GainerLoserCard component is well-structured with appropriate early return for empty arrays, clean JSX composition, and proper use of the ToolCard compound component pattern.

apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1)

60-64: LGTM!

The updated description is concise and clearly communicates that this tool has no UI card, guiding the LLM to format the response itself. This aligns with the pattern established by other tools in this PR (e.g., getCategoriesTool, getTrendingPoolsTool).

apps/agentic-server/src/lib/asset/coingecko/index.ts (1)

1-23: LGTM!

The barrel file cleanly re-exports the new API functions and types, maintaining a clear separation between function exports and type exports. This provides a well-organized public API surface for the coingecko module.

apps/agentic-server/src/tools/initiateSwap.ts (2)

327-332: LGTM!

The refactor to use resolveAsset directly simplifies the USD-path flow. The error handling correctly validates that a price is available before proceeding with the USD-to-crypto conversion.


292-306: LGTM!

The updated tool descriptions provide clear UI card guidance and example responses, maintaining consistency with other tools in this PR. The instruction to "supplement the card, not duplicate it" will help reduce verbose LLM responses.

apps/agentic-server/src/tools/getTrendingTokens.ts (1)

23-37: LGTM!

The mapping logic safely handles optional fields with nullish coalescing, and correctly extracts the first assetId from the coingecko mapping (which may be undefined for unmapped tokens, as allowed by the TrimmedTrendingCoin type).

apps/agentic-server/src/tools/getTopGainersLosers.ts (1)

53-68: LGTM!

The tool definition follows the established pattern with clear UI card guidance and example responses.

apps/agentic-server/src/routes/chat.ts (2)

77-150: LGTM!

The buildTools function appropriately uses wrapToolWithLogging for stateless tools and inline wrappers for tools requiring walletContext injection. The new informational tools are correctly integrated.


194-201: LGTM!

The system prompt updates provide clear tool categorization and UI behavior guidance that aligns with the individual tool descriptions. This will help the LLM make better tool selection decisions and produce appropriate responses.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/agentic-server/src/tools/getAssets.ts (1)

97-112: LGTM - Clear tool description with UI card guidance.

The description provides good instructions for the LLM on how to supplement the UI card without duplicating information.

🧹 Nitpick comments (6)
apps/agentic-server/src/tools/portfolio.ts (1)

105-105: Minor: Redundant nullish coalescing with undefined.

asset.priceChange24h ?? undefined is equivalent to just asset.priceChange24h when the fallback is undefined. However, this is harmless and makes the intent explicit.

apps/agentic-server/src/tools/getTrendingTokens.ts (1)

17-21: Consider adding error handling for API failures.

The getTrendingSearch() call doesn't have try/catch. If the CoinGecko API fails, the error will propagate up. This may be intentional if handled at a higher level, but consider whether a graceful fallback or specific error message would improve UX.

#!/bin/bash
# Check if there's error handling at the route/tool execution level
rg -n "getTrendingTokensTool" --type=ts -A 10 -B 2
apps/agentic-server/src/tools/getCategories.ts (1)

21-40: Consider adding error handling for the API call.

The getCategories(order) call at line 28 can throw on network failures or API errors. Other similar tools in the codebase have try-catch blocks. Consider wrapping in try-catch to provide a meaningful error message or empty result.

 export async function executeGetCategories(input: GetCategoriesInput): Promise<GetCategoriesOutput> {
   console.log('[getCategories]:', input)
 
   const sortBy = input.sortBy ?? 'market_cap_change_24h'
   const limit = input.limit ?? 10
 
   const order = sortBy === 'market_cap' ? 'market_cap_desc' : 'market_cap_change_24h_desc'
-  const data = await getCategories(order)
+  let data
+  try {
+    data = await getCategories(order)
+  } catch (error) {
+    console.error('[getCategories] API error:', error)
+    return { categories: [], sortedBy: sortBy }
+  }
 
   const categories: TrimmedCategory[] = data.slice(0, limit).map((cat: CategoryData) => ({
apps/agentic-server/src/tools/getTrendingPools.ts (1)

50-72: Consider defensive check for data.data before slicing.

If the API returns an unexpected response structure, data.data could be undefined, causing a runtime error on .slice().

-  const pools: TrimmedTrendingPool[] = data.data.slice(0, limit).map((pool: TrendingPoolData) => {
+  const pools: TrimmedTrendingPool[] = (data.data ?? []).slice(0, limit).map((pool: TrendingPoolData) => {
apps/agentic-server/src/routes/chat.ts (1)

36-46: Good abstraction, but the as T cast bypasses type checking.

The wrapper correctly preserves the tool structure, but casting to T at line 45 could hide type mismatches. Consider using a more precise return type or ensuring the spread preserves the exact type.

The current implementation works correctly for the use cases in this file. The cast is acceptable given the controlled usage pattern.

apps/agentic-server/src/lib/asset/coingecko/api.ts (1)

16-24: Consider adding validation for COINGECKO_API_KEY at module load time, following the pattern used elsewhere in the codebase.

The API key is read from the environment but never validated. If undefined, axios will send the string "undefined" in the auth header, causing API authentication failures with unclear error messages. The codebase already establishes this validation pattern (e.g., tools/send.ts, utils/feeEstimation.ts). Add a check like:

const COINGECKO_API_KEY = process.env.COINGECKO_API_KEY
if (!COINGECKO_API_KEY) {
  throw new Error('COINGECKO_API_KEY environment variable is required')
}

This prevents confusing auth errors and aligns with existing error-handling conventions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8120fa9 and 1a23586.

📒 Files selected for processing (25)
  • apps/agentic-chat/src/components/toolUIRegistry.tsx (2 hunks)
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx (1 hunks)
  • apps/agentic-chat/src/components/ui/AssetListItem.tsx (1 hunks)
  • apps/agentic-server/src/context.ts (1 hunks)
  • apps/agentic-server/src/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/api.ts (2 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/index.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/coingecko/types.ts (1 hunks)
  • apps/agentic-server/src/lib/asset/prices.ts (1 hunks)
  • apps/agentic-server/src/routes/chat.ts (6 hunks)
  • apps/agentic-server/src/tools/getAssets.ts (3 hunks)
  • apps/agentic-server/src/tools/getCategories.ts (1 hunks)
  • apps/agentic-server/src/tools/getNewCoins.ts (1 hunks)
  • apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1 hunks)
  • apps/agentic-server/src/tools/getTopGainersLosers.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingPools.ts (1 hunks)
  • apps/agentic-server/src/tools/getTrendingTokens.ts (1 hunks)
  • apps/agentic-server/src/tools/initiateSwap.ts (3 hunks)
  • apps/agentic-server/src/tools/portfolio.ts (4 hunks)
  • apps/agentic-server/src/tools/receive.ts (1 hunks)
  • apps/agentic-server/src/tools/send.ts (1 hunks)
  • apps/agentic-server/src/tools/transactionHistory.ts (1 hunks)
  • apps/agentic-server/src/utils/assetHelpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (12)
  • apps/agentic-server/src/context.ts
  • apps/agentic-chat/src/components/tools/TopGainersLosersUI.tsx
  • apps/agentic-chat/src/components/tools/TrendingTokensUI.tsx
  • apps/agentic-server/src/tools/initiateSwap.ts
  • apps/agentic-chat/src/components/toolUIRegistry.tsx
  • apps/agentic-chat/src/components/tools/NewCoinsUI.tsx
  • apps/agentic-server/src/tools/getShapeShiftKnowledge.ts
  • apps/agentic-server/src/tools/getTopGainersLosers.ts
  • apps/agentic-server/src/lib/asset/prices.ts
  • apps/agentic-server/src/index.ts
  • apps/agentic-server/src/tools/receive.ts
  • apps/agentic-server/src/tools/getNewCoins.ts
🧰 Additional context used
🧬 Code graph analysis (8)
apps/agentic-server/src/tools/getTrendingPools.ts (2)
apps/agentic-server/src/lib/asset/coingecko/types.ts (3)
  • TrimmedTrendingPool (214-225)
  • TrendingPoolIncluded (148-159)
  • TrendingPoolData (105-146)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getTrendingPools (108-116)
apps/agentic-server/src/tools/getCategories.ts (2)
apps/agentic-server/src/lib/asset/coingecko/types.ts (2)
  • TrimmedCategory (227-234)
  • CategoryData (167-177)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
  • getCategories (118-129)
apps/agentic-server/src/tools/portfolio.ts (2)
apps/agentic-server/src/lib/asset/prices.ts (1)
  • getAssetPrices (12-33)
packages/types/src/asset.ts (1)
  • asset (3-26)
apps/agentic-server/src/utils/assetHelpers.ts (4)
apps/agentic-server/src/lib/schemas/swapSchemas.ts (1)
  • AssetInput (76-76)
packages/types/src/asset.ts (1)
  • Asset (28-28)
apps/agentic-server/src/lib/asset/prices.ts (1)
  • getAssetPrices (12-33)
packages/types/src/network.ts (1)
  • chainIdToNetwork (84-86)
apps/agentic-server/src/tools/getAssets.ts (5)
packages/types/src/network.ts (2)
  • NETWORKS (23-42)
  • chainIdToNetwork (84-86)
packages/types/src/asset.ts (2)
  • asset (3-26)
  • Asset (28-28)
packages/utils/src/AssetService.ts (1)
  • assetService (135-135)
packages/utils/src/index.ts (1)
  • assetService (35-35)
packages/caip/src/adapters/coingecko/index.ts (1)
  • assetIdToCoingecko (59-59)
apps/agentic-server/src/lib/asset/coingecko/api.ts (1)
apps/agentic-server/src/lib/asset/coingecko/types.ts (5)
  • TrendingSearchResponse (62-74)
  • TopGainersLosersResponse (92-95)
  • TrendingPoolsResponse (161-164)
  • CategoriesResponse (179-179)
  • NewCoinsResponse (189-189)
apps/agentic-server/src/routes/chat.ts (7)
apps/agentic-server/src/tools/getAssets.ts (1)
  • getAssetsTool (97-112)
apps/agentic-server/src/tools/getShapeShiftKnowledge.ts (1)
  • getShapeShiftKnowledgeTool (60-64)
apps/agentic-server/src/tools/getTrendingTokens.ts (1)
  • getTrendingTokensTool (39-54)
apps/agentic-server/src/tools/getTopGainersLosers.ts (1)
  • getTopGainersLosersTool (53-68)
apps/agentic-server/src/tools/getTrendingPools.ts (1)
  • getTrendingPoolsTool (77-81)
apps/agentic-server/src/tools/getCategories.ts (1)
  • getCategoriesTool (42-46)
apps/agentic-server/src/tools/getNewCoins.ts (1)
  • getNewCoinsTool (39-54)
apps/agentic-server/src/lib/asset/coingecko/types.ts (2)
apps/agentic-server/src/lib/asset/coingecko/index.ts (10)
  • TrendingCoinItem (20-20)
  • TrendingSearchResponse (13-13)
  • TopGainersLosersResponse (14-14)
  • TrendingPoolData (21-21)
  • TrendingPoolIncluded (22-22)
  • TrendingPoolsResponse (15-15)
  • CategoryData (18-18)
  • CategoriesResponse (16-16)
  • NewCoinData (19-19)
  • NewCoinsResponse (17-17)
apps/agentic-server/src/index.ts (5)
  • TrimmedTrendingCoin (92-92)
  • TrimmedGainerLoserCoin (93-93)
  • TrimmedTrendingPool (94-94)
  • TrimmedCategory (95-95)
  • TrimmedNewCoin (96-96)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: main
🔇 Additional comments (25)
apps/agentic-server/src/tools/transactionHistory.ts (1)

114-125: Card‑oriented description is clear and consistent

The updated description clearly frames this as a card‑supplement tool, with good guardrails against duplicating card data and appropriately short default responses. No issues from a correctness or API standpoint.

apps/agentic-server/src/tools/send.ts (1)

121-132: Description update follows consistent UI-card pattern.

The multi-line description with UI guidance aligns with the broader tooling updates in this PR. The format is consistent with other tools (portfolio, getTrendingTokens) and provides clear instructions for supplementing rather than duplicating card data.

apps/agentic-server/src/tools/portfolio.ts (3)

6-6: Import change aligns with new asset pricing utility.

The switch to getAssetPrices consolidates asset price fetching and provides consistent priceChange24h data across the codebase.


78-78: Asset resolution updated to use centralized pricing utility.

This change properly aligns with the new getAssetPrices function which returns enriched asset data including prices and 24h changes.


154-165: Description follows consistent UI-card guidance pattern.

The multi-line description with example responses aligns with the PR's approach across all updated tools.

apps/agentic-server/src/utils/assetHelpers.ts (2)

9-16: Simplified asset resolution with proper error handling.

The refactored resolveAsset now uses assetService.search() directly and properly handles the case where no assets are found. The error message appropriately includes the network context when provided.


18-24: Price fetching and network resolution look correct.

The function correctly:

  • Fetches price data for the resolved asset
  • Falls back to '0' if no price is available
  • Resolves network from input, then chainId mapping, then empty string

One consideration: the network field in the return type comes from chainIdToNetwork which returns Network | undefined based on the type snippet. The fallback chain handles this appropriately.

apps/agentic-server/src/lib/asset/coingecko/index.ts (1)

1-23: Clean barrel exports for CoinGecko module.

The expanded exports properly expose new API functions and types. Using export type for type-only exports is the correct pattern for TypeScript.

apps/agentic-server/src/tools/getTrendingTokens.ts (3)

7-9: Schema looks good with sensible defaults.

The Zod schema properly validates the limit parameter with min/max constraints and provides a clear description.


39-54: Tool description follows consistent UI-card pattern.

The description properly guides the AI to supplement rather than duplicate card data, with appropriate example responses.


23-34: The review comment is incorrect. AssetListItem gracefully handles undefined assetId through fallback logic.

The assetId field is intentionally optional in the TrimmedTrendingCoin type definition (line 199 of types.ts: assetId?: string). When assetIds[0] is undefined, the AssetListItem component handles it safely:

  • If assetId exists, it renders an AssetIcon (line 85)
  • If assetId is undefined but iconUrl is provided, it uses that (line 86)
  • If neither exists, it renders a FallbackIcon with the symbol's first letter (line 87)

This defensive UI pattern is consistent across the codebase and works correctly when CoinGecko IDs lack CAIP mappings.

apps/agentic-chat/src/components/ui/AssetListItem.tsx (3)

30-41: LGTM - Simple and effective fallback icon.

Clean implementation using first character of symbol as fallback.


43-58: LGTM - Good error handling for image loading.

The hasError state and onError callback provide graceful degradation to the fallback icon.


60-109: LGTM - Well-structured component with proper conditional rendering.

The icon fallback chain (assetId → iconUrl → symbol initials) and conditional price/change display are implemented correctly.

apps/agentic-server/src/tools/getCategories.ts (1)

6-19: LGTM - Schema and types are well-defined.

Good use of optional parameters with sensible defaults documented in descriptions.

apps/agentic-server/src/tools/getTrendingPools.ts (1)

29-48: LGTM - Clean lookup map construction with proper fallbacks.

Good use of Maps for efficient lookups. The fallback values ensure graceful handling of missing data.

apps/agentic-server/src/lib/asset/coingecko/api.ts (1)

89-134: LGTM - Consistent API endpoint implementations.

All new functions follow the established pattern and have proper type annotations. Default parameter values align with the CoinGecko API documentation.

apps/agentic-server/src/tools/getAssets.ts (1)

36-60: LGTM - Robust error handling and field mapping.

Proper null coalescing for all optional market data fields, and the try-catch ensures graceful degradation.

apps/agentic-server/src/routes/chat.ts (2)

144-149: LGTM - New informational tools properly integrated.

All new tools (getTrendingTokensTool, getTopGainersLosersTool, getTrendingPoolsTool, getCategoriesTool, getNewCoinsTool) are correctly wrapped with logging and added to the tools object.


194-201: LGTM - Clear tool categorization in system prompt.

The organized tool categories and UI behavior guidance will help the LLM use tools appropriately.

apps/agentic-server/src/lib/asset/coingecko/types.ts (5)

36-74: Well-structured trending tokens types.

The type definitions for trending tokens are comprehensive and properly handle optional fields and nested structures. The separation between required fields (id, name, symbol, etc.) and optional data object is appropriate for API response handling.


76-95: Good null handling in top gainers/losers types.

The types correctly handle nullable values with market_cap_rank: number | null and appropriately mark time-based change fields as optional, reflecting the varying availability of historical data.


97-164: Comprehensive trending pools types with proper optionality.

The trending pools types handle complex nested structures well, with appropriate optional fields throughout. The separation of data and included arrays follows JSON:API conventions, and the relationships structure enables proper entity linking.


166-189: Clean and straightforward category and new coins types.

The category and new coins types are well-defined with appropriate optionality. The required activated_at field as a number (timestamp) is the correct choice for reliable temporal data.


191-243: Excellent design of trimmed types for LLM context optimization.

The trimmed types demonstrate thoughtful design:

  • Convention consistency: Switching from snake_case (raw API) to camelCase (application layer) shows good separation of concerns
  • Context optimization: Reducing fields to minimize LLM token usage is a practical consideration
  • Type safety preserved: Proper null handling and optional fields maintain type safety
  • Enrichment support: Optional assetId fields enable integration with ShapeShift's asset system
  • Formatted timestamps: activatedAtFormatted in TrimmedNewCoin improves readability

The apparent inconsistency in numeric types (e.g., price: string | null vs price: number) correctly reflects the underlying API differences between endpoints.

@premiumjibles premiumjibles merged commit 66ab284 into main Nov 27, 2025
4 checks passed
@premiumjibles premiumjibles deleted the informational-tools branch November 27, 2025 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants