Skip to content

Conversation

@premiumjibles
Copy link
Contributor

@premiumjibles premiumjibles commented Dec 2, 2025

Summary by CodeRabbit

  • New Features

    • Added contract-address lookup as a first-class entry point alongside search and asset ID.
    • Added filtering: asset type (native/token/all) and pool options (exclude/include/only).
    • Search now accepts optional network filtering.
  • Improvements

    • More accurate and faster asset retrieval via contract indexing and expanded lookup paths.
    • Asset results are enriched with market and display data when available.
    • Tool descriptions, input usage, and UI card wording clarified.

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

@vercel
Copy link

vercel bot commented Dec 2, 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 Dec 7, 2025 10:20pm

@coderabbitai
Copy link

coderabbitai bot commented Dec 2, 2025

📝 Walkthrough

Walkthrough

Adds contract-address lookup and filtering to asset search and the getAssets tool; centralizes asset enrichment via a new hydrateAsset helper; AssetService gains contract indexing plus searchByContract and searchWithFilters APIs; getAssets flow now routes by assetId, contractAddress, or searchTerm.

Changes

Cohort / File(s) Summary
getAssets tool & flow
apps/agentic-server/src/tools/getAssets.ts
Expanded public input schema to include contractAddress, assetType, and pools. Reworked enrichment into hydrateAsset(staticAsset, network) (defaults color/price, conditionally adds market data). executeGetAssets and helpers now route by assetId, contractAddress, or searchTerm. Shortened tool description and updated UI-facing metadata and usage docs.
AssetService indexing & search
packages/utils/src/AssetService.ts
Added assetsByContract index (skips assets with /slip44: in id). New APIs: searchByContract(rawContractAddress, network?) and searchWithFilters(term, options?) supporting network: Network, `assetType: 'all'

Sequence Diagram(s)

sequenceDiagram
    participant Client as Agent
    participant Tool as getAssetsTool
    participant Service as AssetService
    participant Enricher as hydrateAsset
    participant Market as MarketData

    Client->>Tool: request({searchTerm|assetId|contractAddress}, filters)
    Tool->>Service: route lookup

    alt assetId provided
        Service->>Service: getByAssetId(assetId)
        Service-->>Tool: staticAsset? 
    else contractAddress provided
        Service->>Service: searchByContract(contractAddress, network?)
        Service-->>Tool: matching staticAssets
    else searchTerm provided
        Service->>Service: searchWithFilters(term, {network, assetType, pools})
        Service-->>Tool: filtered staticAssets
    end

    loop for each staticAsset
        Tool->>Enricher: hydrateAsset(staticAsset, network?)
        Enricher->>Market: fetch (optional) market data (CoinGecko)
        Market-->>Enricher: price/market info (or none)
        Enricher-->>Tool: enriched asset
    end

    Tool-->>Client: GetAssetsOutput (assets[])
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify assetsByContract population and /slip44: exclusion.
  • Confirm searchByContract and searchWithFilters correctly apply network (chainId) constraints.
  • Check isPool() detection and pools filter semantics (exclude/include/only).
  • Ensure hydrateAsset correctly defaults color/price and safely handles missing market data.

Possibly related PRs

Poem

🐰
I hopped through maps and contracts bright,
Matched ids, names, and pools by night,
I hydrate, enrich, then send along,
Assets found — a tidy song!

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 accurately summarizes the main changes: asset searching enhancements via new contract-based lookup, filtering capabilities (network, assetType, pools), and API expansions in both the tool and service layers.
✨ 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 flexible-assets-

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 (6)
packages/utils/src/AssetService.ts (3)

14-14: Contract index population matches CAIP‑19 layout; minor resilience improvement possible

Indexing non‑slip44 assets by the substring after the post‑slash colon is consistent with CAIP‑19’s assetReference and should work well with your dataset. The only potential sharp edge is if future assetIds violate the expected chainId/namespace:reference shape, in which case indexOf(':', slashIdx) could be -1 and you’d end up indexing under the entire string. If you expect the asset catalog to evolve, consider a small guard (e.g., skip when colonIdx <= slashIdx) or centralizing CAIP‑19 parsing in a helper to keep this logic in one place.

Also applies to: 26-26, 41-50


144-158: searchByContract behavior is sound; consider normalizing and DRY‑ing network filtering

The contract lookup is case‑insensitive and correctly reuses the same network/chainId resolution pattern as the symbol/name searches. Two small polish ideas:

  • contractAddress could be .trim().toLowerCase() to avoid failures from accidental whitespace.
  • The network resolution and (assetNetwork === normalized || asset.chainId[.toLowerCase()] === candidateChainId) pattern is now duplicated in three methods; extracting a tiny helper to compute the predicate would reduce drift between them.

160-189: Filtered search semantics look correct; be aware of assetType × pools corner cases

searchWithFilters cleanly layers assetType and pools filters over the scored search() results, and the defaults (assetType = 'all', pools = 'exclude') align with the tool description. A couple of subtle behaviors to keep in mind:

  • “Native” is defined purely as assetId.includes('/slip44:'), which is fine today but will silently misclassify if new namespaces are added for other native-like assets.
  • Because assetType is applied before pools, combinations like assetType: 'native', pools: 'only' will (correctly but perhaps surprisingly) result in an empty list in most cases; if that’s not desired, you may want to special-case pools === 'only' to ignore assetType.
apps/agentic-server/src/tools/getAssets.ts (3)

65-92: Nice centralization of enrichment; consider typing and network fallback tweaks

enrichAndReturn is a good consolidation of the “StaticAsset → AssetWithMarketData” flow, and the assetIdToCoingecko + graceful fallback pattern looks solid. Two small improvements you might consider:

  • Type the staticAsset parameter as StaticAsset (or a named subset) instead of inlining the shape to avoid drifting from the canonical type.
  • If chainIdToNetwork[staticAsset.chainId] is ever undefined and no network is provided, you silently set network to ''; logging or surfacing that mismatch could make bad catalog entries easier to detect.

94-116: Lookup order and new contract path look good; returning only the top match is a design choice

The resolution order assetId → contractAddress → searchTerm is clear and predictable, and delegating all three paths through enrichAndReturn keeps the enrichment logic consistent. The only behavioral constraint to call out is that both the contract and search paths take only the first matching asset ([0]), even though the underlying service can return multiple matches (e.g., multi‑chain symbols or contract collisions). If you anticipate UIs that want to present a choice, you may eventually want a variant that returns the full (or top‑N) list.


121-123: Guard in executeGetAssets avoids pointless work; optional normalization for searchTerm

Short‑circuiting executeGetAssets when all of searchTerm, assetId, and contractAddress are falsy is sensible. If agents or UIs might send whitespace‑only search terms, you could defensively check searchTerm?.trim() here to avoid treating " " as a real query and accidentally returning broad matches, but that’s strictly a polish improvement.

📜 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 5bad346 and 536df73.

📒 Files selected for processing (2)
  • apps/agentic-server/src/tools/getAssets.ts (2 hunks)
  • packages/utils/src/AssetService.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/utils/src/AssetService.ts (2)
packages/types/src/asset.ts (2)
  • StaticAsset (30-30)
  • asset (3-26)
packages/types/src/network.ts (2)
  • networkToChainIdMap (63-82)
  • chainIdToNetwork (84-86)
⏰ 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 (1)
apps/agentic-server/src/tools/getAssets.ts (1)

130-147: Tool description matches behavior and clearly documents new filters

The updated description and METHODS/FILTERS sections align well with the implementation: assetType and pools behaviors mirror searchWithFilters, and the note about native assets being prioritized on symbol matches matches the scoring logic in AssetService.scoreMatch. This should make the tool significantly easier for agents to use correctly.

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)

27-27: Documentation inconsistency remains unaddressed.

The past review comment correctly identified that the description "(requires network)" is inconsistent with the actual behavior. The schema marks network as optional, and searchByContract (line 104) accepts undefined network. The tool description at line 136 correctly shows network? as optional.

This should be updated to either:

  • Remove "(requires network)"
  • Replace with "(optional; without network returns first match across all networks)"
🧹 Nitpick comments (1)
apps/agentic-server/src/tools/getAssets.ts (1)

66-74: Consider extracting the inline type definition.

The 9-line inline type for staticAsset makes the function signature harder to scan. Extracting it to a named type (e.g., StaticAsset or BaseAssetData) would improve readability and enable reuse if needed elsewhere.

type StaticAssetData = {
  assetId: string
  chainId: string
  symbol: string
  name: string
  precision: number
  color?: string
  icon: string
}

async function enrichAndReturn(
  staticAsset: StaticAssetData,
  network?: string
): Promise<GetAssetsOutput> {
  // ...
}
📜 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 536df73 and 66f556c.

📒 Files selected for processing (2)
  • apps/agentic-server/src/tools/getAssets.ts (2 hunks)
  • packages/utils/src/AssetService.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/utils/src/AssetService.ts
⏰ 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 (4)
apps/agentic-server/src/tools/getAssets.ts (4)

39-63: LGTM!

The error handling and fallback logic are well-implemented. Returning null on failure allows the caller to gracefully fall back to the base asset without market data.


94-116: LGTM!

The three-path routing (assetId → contractAddress → searchTerm) is clear and well-structured. The null checks before calling enrichAndReturn properly handle cases where searches return no results.


118-128: LGTM!

The routing logic correctly handles all three search methods. Returning an empty result when no search parameters are provided is a reasonable defensive approach, though you could optionally enforce at least one parameter at the schema level if desired.


130-147: LGTM!

The tool description is comprehensive and accurately documents the three search methods and filter options. Line 136 correctly shows network? as optional, which accurately reflects the implementation behavior. The usage guidance about native asset prioritization and pool filtering is helpful.

@premiumjibles premiumjibles merged commit 5c7e7d4 into main Dec 7, 2025
3 of 4 checks passed
@premiumjibles premiumjibles deleted the flexible-assets- branch December 7, 2025 22:23
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/getAssets.ts (2)

119-136: Tool description now matches schema and runtime behavior

The updated getAssetsTool.description:

  • Documents three methods with network? clearly optional for CONTRACT,
  • Explains assetType and pools filters and their defaults,
  • Notes that native assets are prioritized for symbol matches, matching the scoring logic in AssetService.search,
  • Clarifies that the tool returns data suitable for a single UI card.

This resolves the earlier mismatch between the schema and description around contract search and optional network.


65-81: Empty-string network fallback in hydrateAsset remains problematic

hydrateAsset currently computes:

const inferredNetwork = network ?? chainIdToNetwork[staticAsset.chainId] ?? ''

and then sets asset.network = inferredNetwork. When neither network nor chainIdToNetwork[staticAsset.chainId] is defined, this yields network: '', which is almost certainly not a valid network identifier and can break downstream consumers expecting a real network or a clearly absent value.

Given this was already flagged earlier, it would be good to resolve it here. For example:

async function hydrateAsset(staticAsset: StaticAsset, network?: Network): Promise<GetAssetsOutput> {
  const inferredNetwork = network ?? chainIdToNetwork[staticAsset.chainId]

  if (!inferredNetwork) {
    // Option A: fail fast
    throw new Error(`[hydrateAsset] Could not infer network for assetId: ${staticAsset.assetId}`)
    // Option B: make Asset.network optional and allow undefined, if you choose that broader change
  }

  const asset: Asset = {
    ...staticAsset,
    color: staticAsset.color ?? '',
    price: '0',
    network: inferredNetwork,
  }
  // rest unchanged...
}

You could also keep Asset.network as string but at least avoid '' and prefer either throwing or some explicit fallback strategy.

🧹 Nitpick comments (4)
packages/utils/src/AssetService.ts (3)

14-15: Contract index implementation for non-slip44 assets looks sound

Building assetsByContract only for non-/slip44: assetIds and extracting the contract as assetId.substring(colonIdx + 1).toLowerCase() matches CAIP-19 token ids (e.g., eip155:1/erc20:0x...). This should support efficient case-insensitive contract lookups.

If you ever ingest non-standard assetIds, a small defensive guard around colonIdx === -1 would make this more robust, but it's not strictly necessary given the current data pipeline.

Also applies to: 24-27, 28-50


115-129: Search aggregation and scoring pipeline looks correct

Combining symbol and name results into a Map<AssetId, StaticAsset> to dedupe, then applying scoreMatch and sorting by score before projecting back to assets preserves uniqueness and ordering by relevance as intended. This is consistent with the scoring logic and avoids duplicate assets from multiple search paths.


141-170: Pool/type filtering is aligned with doc semantics; consider not overriding explicit isPool=false

searchWithFilters correctly:

  • Delegates to search(term, network) for relevance ranking,
  • Splits assetType into native (/slip44:), token (non-/slip44:), or all,
  • Applies pool filtering based on 'exclude' | 'include' | 'only', with 'include' acting as a no-op.

isPool(asset) currently returns asset.isPool || asset.symbol.includes('/'). This can override an explicit isPool === false if a symbol contains /. If you expect any such assets, a safer pattern would be:

private isPool(asset: StaticAsset): boolean {
  return asset.isPool ?? asset.symbol.includes('/')
}

so that explicit false wins over the heuristic.

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

24-30: Schema additions and descriptions match the new behaviors

The updated getAssetsSchema:

  • Adds contractAddress, assetType, and pools,
  • Clarifies searchTerm as “Search by name or symbol,”
  • Marks network as optional “Chain to search on,”

which is consistent with how getAssetWithMarketData and assetService now behave. If you ever want stricter validation (e.g., require at least one of searchTerm/assetId/contractAddress), that can be layered via a refinement, but not required for correctness.

📜 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 66f556c and 870109d.

📒 Files selected for processing (2)
  • apps/agentic-server/src/tools/getAssets.ts (3 hunks)
  • packages/utils/src/AssetService.ts (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/utils/src/AssetService.ts (2)
packages/types/src/asset.ts (2)
  • StaticAsset (30-30)
  • asset (3-26)
packages/types/src/network.ts (2)
  • Network (44-44)
  • networkToChainIdMap (63-82)
apps/agentic-server/src/tools/getAssets.ts (4)
packages/types/src/network.ts (2)
  • NETWORKS (23-42)
  • chainIdToNetwork (84-86)
packages/types/src/asset.ts (3)
  • StaticAsset (30-30)
  • asset (3-26)
  • Asset (28-28)
packages/caip/src/adapters/coingecko/index.ts (1)
  • assetIdToCoingecko (59-59)
packages/utils/src/AssetService.ts (1)
  • assetService (177-177)
⏰ 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 (7)
packages/utils/src/AssetService.ts (4)

2-3: Typed imports for Network and chainId mapping look consistent

The added Network/StaticAsset type import and networkToChainIdMap import align with the new Network-aware search APIs; no issues here.


65-75: Network-aware symbol search is straightforward and type-safe

Lowercasing the input symbol and then filtering matches by asset.chainId === networkToChainIdMap[network] is a clean way to scope results to a network while keeping the API Network-typed.


97-113: Name search behavior (exact + partial, then optional network filter) is reasonable

The split between exact name matches and partial matches via assetsByName.entries() and the subsequent chainId filter when network is provided gives predictable behavior and keeps network scoping consistent with searchBySymbol. No correctness issues spotted.


131-139: Contract search correctly respects optional network filtering

Lowercasing the contract address, returning all matches by default, and then narrowing by chainId when network is supplied matches the intended semantics (with multi-chain contracts handled by the filter). The behavior is clear, and results[0] selection is handled at the caller.

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

2-2: StaticAsset import is appropriately used for hydration typing

Importing StaticAsset alongside Asset keeps hydrateAsset’s signature precise and documents that hydration starts from static data; no issues here.


83-105: Selection and hydration order for assetId/contract/searchTerm is coherent

getAssetWithMarketData now:

  1. Resolves by assetId via assetService.getAsset and hydrates,
  2. Falls back to contractAddress using assetService.searchByContract(contractAddress, network)[0],
  3. Then to searchTerm via assetService.searchWithFilters(searchTerm, { network, assetType, pools })[0],
  4. Returns { assets: [] } when nothing matches.

This preserves a clear precedence order and keeps the tool’s output shape stable (0 or 1 asset), which matches the card-focused UI description.


107-116: executeGetAssets gating logic correctly includes contractAddress

Adding contractAddress to the early-return condition ensures all three entry paths (assetId, contractAddress, searchTerm) are handled consistently before falling back to an empty result. No issues here.

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