Skip to content

Comments

switch from lite-api to api.jup.ag with API key auth#4

Open
odilitime wants to merge 57 commits into1.xfrom
odi-dev
Open

switch from lite-api to api.jup.ag with API key auth#4
odilitime wants to merge 57 commits into1.xfrom
odi-dev

Conversation

@odilitime
Copy link
Member

@odilitime odilitime commented Feb 11, 2026

lite-api.jup.ag no longer works; basic tier now requires an API key. Reads JUPITER_API_KEY from runtime settings and sends x-api-key header on all quote and swap requests. Also adds build.ts, tsconfig.build.json, expanded .gitignore, and various type annotation fixes.


Note

Medium Risk
Touches core quote/swap request flow and makes startup depend on a configured JUPITER_API_KEY, which could break runtime behavior if misconfigured or if queue/caching logic has edge cases; build changes are localized but may affect publishing outputs.

Overview
Migrates the Jupiter integration off lite-api.jup.ag to api.jup.ag and makes an API key mandatory: JupiterService.start() now reads JUPITER_API_KEY from runtime settings, injects it via x-api-key on quote/swap/metadata requests, and clears it on stop().

Reworks request handling into a shared, round-robin, 1-req/sec rate-limited queue covering quotes, swaps, and token/price metadata; adds unified retry/backoff logging and a bounded TTL route cache keyed by mint pair + amount + slippage. Token/price helpers are updated: getTokenPair() now uses the Tokens/Markets APIs, getCurrentPrices() is added via price/v3, and getHistoricalPrices() is retained but now delegates to current snapshot prices.

Build tooling switches from tsup to a Bun-based build.ts plus tsconfig.build.json for declaration-only output; package.json scripts/engines are updated, .gitignore is expanded, and a .prr/lessons.md file is added.

Written by Cursor Bugbot for commit 0079fc5. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • New Features

    • API key–based authentication with queued, rate-limited request processing and route caching for repeated queries.
    • New Bun-based build runner and build configuration.
  • Improvements

    • Exponential-backoff retries, clearer consolidated error logging, and updated build flow that ensures TypeScript declarations.
  • Chores

    • Expanded ignore rules to cover build artifacts, env files, IDE/system caches, logs and temp files.
  • Tests

    • Added a test demonstrating failure handling for missing commands.
  • Documentation

    • Added internal PR review lessons file.

Greptile Overview

Greptile Summary

Migrates Jupiter API integration from lite-api.jup.ag to api.jup.ag with API key authentication via x-api-key header, sourced from JUPITER_API_KEY runtime setting.

Key Changes:

  • Adds getApiHeaders() function to inject x-api-key header when API key is configured
  • Updates base URL constant to https://api.jup.ag/swap/v1 for quote and swap endpoints
  • Improves TypeScript typing for queue handlers, quote responses, and cache utilities
  • Refines cache key to include amount parameter for better cache granularity
  • Replaces tsup build with custom Bun-based build.ts that runs ESM bundling + TypeScript declaration generation

Issues Found:

  • getTokenPair() and getHistoricalPrices() methods still call the old https://public.jupiterapi.com endpoints, which may not accept the new API key header
  • dev script references --watch flag, but build.ts doesn't implement watch mode
  • Dead code in build.ts (unreachable else branch due to if (true) condition)

Confidence Score: 3/5

  • Mostly safe to merge, but has endpoint inconsistencies that could cause runtime issues
  • Core quote/swap functionality properly migrated to new API with authentication, but two methods (getTokenPair, getHistoricalPrices) still use old endpoints that may not work. Build system changes are functional despite minor issues with watch mode and dead code.
  • Pay close attention to src/service.ts - verify that getTokenPair and getHistoricalPrices work with the old endpoint or need migration

Important Files Changed

Filename Overview
src/service.ts Updates to api.jup.ag with API key auth; two methods still use old public.jupiterapi.com endpoint
build.ts New Bun-based build script; contains unreachable dead code in conditional branch
package.json Switches from tsup to custom build.ts; dev script references unimplemented --watch flag

Sequence Diagram

sequenceDiagram
    participant Client as JupiterService
    participant API as api.jup.ag
    participant Queue as Request Queue
    
    Note over Client: Service starts, reads API key from settings
    Client->>Client: Load API key configuration
    
    Note over Client,API: Quote Request Flow
    Client->>Queue: quoteEnqueue(url)
    Queue->>Queue: Add to quotes queue
    Queue->>API: GET /swap/v1/quote (with auth header)
    API-->>Queue: Quote response
    Queue-->>Client: Return quote data
    
    Note over Client,API: Swap Request Flow
    Client->>Queue: swapEnqueue(url, payload)
    Queue->>Queue: Add to swaps queue
    Queue->>API: POST /swap/v1/swap (with auth header)
    API-->>Queue: Swap transaction data
    Queue-->>Client: Return swap data
    
    Note over Queue: Queues process at 1 req/sec<br/>with exponential backoff on 429
Loading

lite-api.jup.ag no longer works; basic tier now requires an API key.
Reads JUPITER_API_KEY from runtime settings and sends x-api-key header
on all quote and swap requests. Also adds build.ts, tsconfig.build.json,
expanded .gitignore, and various type annotation fixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI review requested due to automatic review settings February 11, 2026 00:58
@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a Bun-based build orchestrator and tsconfig.build.json, expands .gitignore rules, introduces a Bun-oriented test file, adds PR-review lessons, and refactors src/service.ts to add API-key startup gating, shared rate-limit queues with retries/backoff, a TTL FIFO route cache, centralized API headers, and improved error logging.

Changes

Cohort / File(s) Summary
Build system
build.ts, package.json, tsconfig.build.json
Adds build.ts (Bun-based build orchestrator), updates package.json build script to bun run build.ts and adds engines.bun + typescript devDependency, and introduces tsconfig.build.json for dist output, declarations, and sourcemaps.
Jupiter service
src/service.ts
Large refactor: introduces module-level API key and startup gating, shared per-operation rate-limit queues (quotes/swaps/metadata) with retry/backoff, centralized getApiHeaders, TTL FIFO route cache with eviction, unified JUPITER_BASE_URL routing, and standardized error handling/logging. Adds private fields for routeCache and apiKey.
Repository ignore rules
.gitignore
Expands ignore list (build outputs, .tsbuildinfo, .turbo, env files, IDE folders, coverage, logs, caches, temp files, bundler artifacts, .pr-resolver-state.json); removes node_modules entry from Build outputs section.
Tests & scripts
test_fail.ts
Adds a Bun-targeted test script that runs a non-existent command to exercise failure handling; logs and exits with non-zero on error.
PR review notes
.prr/lessons.md
Adds auto-generated PR review lessons documenting concerns and recommended fixes specific to src/service.ts (instructional only, no code changes).

Sequence Diagram(s)

sequenceDiagram
    rect rgba(52,152,219,0.5)
    participant Client
    end
    rect rgba(46,204,113,0.5)
    participant JupiterService
    end
    rect rgba(241,196,15,0.5)
    participant RouteCache
    end
    rect rgba(155,89,182,0.5)
    participant RateLimitQueue
    end
    rect rgba(231,76,60,0.5)
    participant JupiterAPI
    end

    Client->>JupiterService: request quote/swap/metadata(params)
    JupiterService->>RouteCache: check cache(key)
    alt cache hit
        RouteCache-->>JupiterService: cached result
        JupiterService-->>Client: return cached result
    else cache miss
        JupiterService->>RateLimitQueue: enqueue request(params, apiKey, headers)
        RateLimitQueue-->>JupiterService: dequeue/process
        JupiterService->>JupiterAPI: HTTP request (with getApiHeaders)
        alt 429 or transient error
            JupiterAPI-->>RateLimitQueue: error
            RateLimitQueue->>RateLimitQueue: schedule retry (exponential backoff)
            RateLimitQueue-->>JupiterService: retry processed
            JupiterService->>JupiterAPI: retry request
        end
        JupiterAPI-->>JupiterService: response
        JupiterService->>RouteCache: set cache(key, response, ttl)
        JupiterService-->>Client: return response
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 Bun warms my paws at break of day,
Queues hum softly while I hop and play.
Keys and caches guard the trail I roam,
Backoffs nudge retries till requests come home.
Hooray — this rabbit hops back to the code!

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: migrating from lite-api to api.jup.ag with API key authentication, which is the core objective reflected throughout the changeset.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into 1.x
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch odi-dev

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

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

5 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link

greptile-apps bot commented Feb 11, 2026

Additional Comments (2)

src/service.ts
getTokenPair still uses the old https://public.jupiterapi.com endpoint which may not accept the new API key header


src/service.ts
getHistoricalPrices still uses the old https://public.jupiterapi.com endpoint which may not accept the new API key header

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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/service.ts (2)

356-374: ⚠️ Potential issue | 🔴 Critical

Bug: outAmount is divided by input decimals instead of output decimals.

outAmount is denominated in the output token's atomic units (USDC with 6 decimals by default), but line 369 divides by 10 ** inputDecimals. For any input token whose decimals differ from the output token's (e.g., SOL with 9 decimals), the returned price will be off by orders of magnitude.

Example: 1 SOL → 150 USDC yields outAmount = 150_000_000, but 150_000_000 / 10^9 = 0.15 instead of the correct 150_000_000 / 10^6 = 150.

Proposed fix
   async getTokenPrice(
     tokenMint: string,
     quoteMint: string = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
-    inputDecimals: number = 6
+    inputDecimals: number = 6,
+    outputDecimals: number = 6
   ): Promise<number> {
     try {
       const baseAmount = 10 ** inputDecimals;
       const quote = await this.getQuote({
         inputMint: tokenMint,
         outputMint: quoteMint,
         amount: baseAmount,
         slippageBps: 50,
       });
-      return Number((quote as any).outAmount) / 10 ** inputDecimals;
+      return Number((quote as any).outAmount) / 10 ** outputDecimals;
     } catch (error) {

218-233: ⚠️ Potential issue | 🟡 Minor

Cache key uses raw amount but the API receives intAmount — key mismatch possible.

Line 218 parses amount to an integer (intAmount), but line 224 builds the cache key using the original amount. If amount is a float (e.g., 1000.5), the cache key will differ from what's actually queried, causing cache misses or stale hits for the truncated value.

Proposed fix
-      const key = inputMint + '_' + outputMint + '_' + amount
+      const key = inputMint + '_' + outputMint + '_' + intAmount
🤖 Fix all issues with AI agents
In `@package.json`:
- Around line 15-16: The dev script is misleading because "dev": "bun run
build.ts --watch" passes --watch but build.ts doesn't handle it, and tsup
remains unused in devDependencies; either implement watch handling in build.ts
(detect the "--watch" flag in build.ts's argument parsing and start a
file-watcher or call the existing build loop when watch=true) or remove the
watch flag from package.json and delete the unused "tsup" entry from
devDependencies; locate references to the "build" and "dev" scripts in
package.json and the build logic in build.ts to add flag parsing (e.g., checking
process.argv for "--watch") or to simplify scripts and prune "tsup" from
devDependencies accordingly.

In `@src/service.ts`:
- Line 178: routeCache currently accumulates entries added by getQuote and never
evicts them; fix by applying a TTL and/or size cap when inserting and reading
from routeCache: use the existing setCacheExp/getCacheExp helpers to attach and
check expiration for entries stored under the composite key used in getQuote
(inputMint, outputMint, amount), and remove expired entries on access;
additionally implement a simple size cap (e.g., LRU or FIFO) in the same module
so when routeCache.length exceeds the limit you evict oldest entries—ensure the
logic is centralized around the routeCache field and the getQuote function so
all inserts and lookups respect TTL and cap.
- Around line 8-21: The module-level jupiterApiKey and import-time queue timers
cause global shared state and last-writer-wins behavior; move the API key and
header logic into the JupiterService instance (e.g., make jupiterApiKey an
instance property and convert getApiHeaders into an instance method on
JupiterService), update any call sites to use the instance method, and pass the
instance API key into the queue/retry helpers rather than reading a module-level
variable; also stop starting the queue timers at import—initialize and start
those timers from JupiterService.start() or the constructor so each service
instance controls its own timers and retry behavior.
🧹 Nitpick comments (3)
build.ts (1)

36-54: Remove if (true) constant condition and dead else branch.

The if (true) guard (flagged by Biome's noConstantCondition) makes the type-check-only path on lines 45–54 unreachable dead code. If the alternative path is kept for future toggling, consider using an explicit config flag or environment variable instead.

Proposed cleanup
   const dtsStart = Date.now();
-  if (true) { // Always generate .d.ts
-    console.log("📝 Generating TypeScript declarations...");
-    try {
-      await $`tsc --project tsconfig.build.json`;
-      console.log(`✅ Declarations generated in ${((Date.now() - dtsStart) / 1000).toFixed(2)}s`);
-    } catch (error) {
-      console.warn(`⚠️  TypeScript declaration generation had errors (${((Date.now() - dtsStart) / 1000).toFixed(2)}s)`);
-      console.warn("   Build will continue - fix type errors when possible");
-    }
-  } else {
-    console.log("🔍 Type checking...");
-    try {
-      await $`tsc --noEmit --incremental --project tsconfig.build.json`;
-      console.log(`✅ Type check passed in ${((Date.now() - dtsStart) / 1000).toFixed(2)}s`);
-    } catch (error) {
-      console.warn(`⚠️  Type checking had errors (${((Date.now() - dtsStart) / 1000).toFixed(2)}s)`);
-      console.warn("   Build will continue - fix type errors when possible");
-    }
+  console.log("📝 Generating TypeScript declarations...");
+  try {
+    await $`tsc --project tsconfig.build.json`;
+    console.log(`✅ Declarations generated in ${((Date.now() - dtsStart) / 1000).toFixed(2)}s`);
+  } catch (error) {
+    console.warn(`⚠️  TypeScript declaration generation had errors (${((Date.now() - dtsStart) / 1000).toFixed(2)}s)`);
+    console.warn("   Build will continue - fix type errors when possible");
   }
src/service.ts (2)

312-316: Redundant API headers — applied both here and inside getSwapWithRetry.

getApiHeaders() is called here at line 314 to build the payload, and then again inside getSwapWithRetry (line 119) where it's merged with payload.headers. The duplication is harmless but confusing. Pick one site — either the caller or the retry helper — to own header injection.


76-96: Queue polling starts at module import — before any service is configured.

checkQuoteQueues() (line 96) and checkSwapQueues() (line 172) fire as soon as this module is imported, running setTimeout loops indefinitely even if no JupiterService is ever started. These timers should be started from start() and cleared in stop() to avoid unnecessary work and allow clean shutdown.

Also applies to: 153-172

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the Jupiter integration to use api.jup.ag and attach an x-api-key header sourced from runtime settings, and replaces the previous tsup-based build with a Bun-based build script plus a dedicated TS build tsconfig.

Changes:

  • Switch quote/swap requests from lite-api.jup.ag to api.jup.ag and add API-key header support via JUPITER_API_KEY.
  • Add Bun-based build pipeline (build.ts) and tsconfig.build.json for declaration generation.
  • Expand .gitignore to include additional build/cache/artifact patterns.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/service.ts Uses new Jupiter base URL, injects x-api-key header, and adds some type annotations/caching tweaks.
build.ts New Bun build script to bundle ESM output and generate .d.ts via tsc.
tsconfig.build.json New TS config intended for declaration-only emit.
package.json Switches build/dev scripts from tsup to Bun build script.
.gitignore Adds common dependency/build/cache/log ignore patterns.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 4 to 28
async function build() {
const totalStart = Date.now();
const pkg = await Bun.file("package.json").json();
const externalDeps = [
...Object.keys(pkg.dependencies ?? {}),
...Object.keys(pkg.peerDependencies ?? {}),
];

// Use the clean script from package.json
if (pkg.scripts?.clean) {
console.log("🧹 Cleaning...");
await $`bun run clean`.quiet();
}

const esmStart = Date.now();
console.log("🔨 Building @elizaos/plugin-jupiter...");
const esmResult = await Bun.build({
entrypoints: ["src/index.ts"],
outdir: "dist",
target: "node",
format: "esm",
sourcemap: "external",
minify: false,
external: externalDeps,
});
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

dev runs bun run build.ts --watch, but build.ts never reads CLI args and doesn’t enable any watch mode for Bun.build. As-is, --watch is ignored and dev mode will just run a single build and exit.

Copilot uses AI. Check for mistakes.
odilitime and others added 5 commits February 11, 2026 01:04
build.ts doesn't implement watch mode; tsup does natively.

Co-authored-by: Cursor <cursoragent@cursor.com>
Both methods were using fabricated public.jupiterapi.com URLs that never
existed. getTokenPair now uses Tokens API V2 Search endpoint with API key
auth. getHistoricalPrices now uses Price API V3 (current prices only, as
Jupiter does not offer a historical price endpoint).

Co-authored-by: Cursor <cursoragent@cursor.com>
api.jup.ag requires an API key for all requests. If none is configured,
log an error and bail out of start() instead of silently failing on
every request.

Co-authored-by: Cursor <cursoragent@cursor.com>
getTokenPrice was dividing outAmount by inputDecimals instead of
outputDecimals — e.g. 1 SOL (9 decimals) to USDC (6 decimals) would
return 0.15 instead of 150. Added outputDecimals param defaulting to 6.

Cache key in getQuote now uses intAmount (the parsed value actually sent
to the API) instead of the raw amount param, preventing mismatches when
a float is passed in.

Co-authored-by: Cursor <cursoragent@cursor.com>
routeCache was an unbounded Record that never evicted entries. Now uses
a Map with 30s TTL and 100-entry FIFO cap. Expired entries are swept on
insert, and oldest entries are evicted when at capacity.

Queue timers (checkQuoteQueues/checkSwapQueues) were starting at import
time even if no service was created or JUPITER_API_KEY was missing. Now
deferred behind startQueues() which is called once from start().

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/service.ts (2)

751-765: ⚠️ Potential issue | 🟠 Major

stop() doesn't cancel queue timers — processing continues after "stop".

checkQuoteQueues and checkSwapQueues schedule themselves with setTimeout indefinitely. stop() only flips isRunning but never breaks the timer chain, so the queues keep draining (or spinning) after the service claims to be stopped. Additionally, queuesStarted is never reset, so a subsequent start() on a new instance won't re-initialize the timers.

Store the timer handles and clear them in stop():

♻️ Sketch
-let queuesStarted = false;
+let queuesStarted = false;
+let quoteTimer: ReturnType<typeof setTimeout> | null = null;
+let swapTimer: ReturnType<typeof setTimeout> | null = null;

 // in checkQuoteQueues:
-  setTimeout(checkQuoteQueues, delayInMs)
+  quoteTimer = setTimeout(checkQuoteQueues, delayInMs)

 // in checkSwapQueues:
-  setTimeout(checkSwapQueues, delayInMs)
+  swapTimer = setTimeout(checkSwapQueues, delayInMs)

+function stopQueues() {
+  if (quoteTimer) clearTimeout(quoteTimer);
+  if (swapTimer) clearTimeout(swapTimer);
+  queuesStarted = false;
+}

 // in stop():
+  stopQueues();
   this.isRunning = false;

711-749: ⚠️ Potential issue | 🟠 Major

Static start() returns a non-running service silently when the API key is missing.

If JUPITER_API_KEY is absent, instance start() logs an error and returns (line 738), but the static start() (line 711-715) still returns the service object to the caller. Downstream code will receive a JupiterService where isRunning === false and no queue timers are active, yet no error is thrown. This makes misconfiguration hard to detect.

Either throw from start() so the caller knows the service failed, or have the static factory propagate the failure:

      if (!apiKey) {
-       logger.error('JUPITER_API_KEY is not set — Jupiter service will not start. Get one at https://portal.jup.ag');
-       return;
+       throw new Error('JUPITER_API_KEY is not set — Jupiter service cannot start. Get one at https://portal.jup.ag');
      }
🧹 Nitpick comments (6)
src/service.ts (6)

224-239: Route cache TTL + eviction looks good; minor lint fix on line 231.

The static analysis tool flags line 231 because the forEach callback implicitly returns the boolean from Map.prototype.delete. While harmless at runtime, it's easy to silence:

♻️ Suggested fix
-    expired.forEach(k => this.routeCache.delete(k));
+    for (const k of expired) this.routeCache.delete(k);

123-129: getApiHeaders() called twice in the swap path — redundant merge.

executeSwap already sets headers: getApiHeaders() in the payload (line 342), and then getSwapWithRetry merges getApiHeaders() again at line 128 before spreading payload.headers on top. The result is correct but getApiHeaders() is invoked twice with identical output.

Pick one site — either let the caller set headers (and don't call getApiHeaders() again inside getSwapWithRetry), or always apply them inside getSwapWithRetry and don't require callers to pass them.


262-266: parseInt(String(amount)) silently truncates fractional values.

amount is typed number. If a caller computes atomic units via floating-point math and passes e.g. 1000000.7, parseInt silently drops the fraction. Math.round (or Math.trunc if truncation is intentional) makes the intent explicit and avoids the unnecessary String() conversion:

-      const intAmount = parseInt(String(amount))
+      const intAmount = Math.round(amount)

78-84: Untyped quote / swap parameters in queue processors.

processQuoteQueue and processSwapQueue accept untyped parameters. A lightweight interface (e.g., { url: string; resolveHandle: (v: unknown) => void; rejectHandle: (r?: any) => void }) would prevent accidental property misspellings and align with the typed enqueue functions.


590-628: getHistoricalPrices doesn't use the timeframe parameter and returns at most 2 current-price entries.

The method signature accepts timeframe but ignores it, and the implementation returns current snapshots, not historical data. The inline comment on lines 587-589 acknowledges this, but callers relying on the name and signature will be misled. Consider renaming to getCurrentPrices or removing the unused timeframe field to avoid confusion.


772-788: Remove unused getCacheExp and setCacheExp functions.

These helper functions are never called anywhere in the codebase and are not exported. They appear to be leftover experimental code (indicated by the "hack these in here" comment). Removing them will reduce confusion and clutter.

Iteration 1

prr-fix:prrc_kwdootnhpm6mw0f0
prr-fix:prrc_kwdootnhpm6mw0my
prr-fix:prrc_kwdootnhpm6mw0nz
prr-fix:prrc_kwdootnhpm6mw0m7
prr-fix:prrc_kwdootnhpm6mw0my
prr-fix:prrc_kwdootnhpm6mw0nt
prr-fix:prrc_kwdootnhpm6mw0ne
prr-fix:prrc_kwdootnhpm6mw0nj
prr-fix:prrc_kwdootnhpm6mw1ez
prr-fix:prrc_kwdootnhpm6mw-ag
prr-fix:prrc_kwdootnhpm6mw-ai
prr-fix:prrc_kwdootnhpm6mw-ak
prr-fix:prrc_kwdootnhpm6mw1ex
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/service.ts (1)

756-769: ⚠️ Potential issue | 🟡 Minor

stop() does not halt the queue polling timers.

checkQuoteQueues and checkSwapQueues use recursive setTimeout that runs indefinitely once startQueues() is called. stop() only flips isRunning but never cancels these timers, so the polling loops continue after the service is "stopped". This also means any items enqueued after stop() will still be processed.

Consider storing the timeout handles and clearing them in stop(), or checking a running flag at the top of each check*Queues function to break the loop.

🤖 Fix all issues with AI agents
In `@build.ts`:
- Around line 37-43: The catch block after the tsc invocation (the await $`tsc
--project tsconfig.build.json` around dtsStart) is currently swallowing errors;
change it to log the actual error/details (include the caught error variable)
and fail the build in CI/strict modes by exiting non‑zero (e.g.,
process.exit(1>) or rethrow) when an env flag like CI or STRICT_BUILD (or a
--strict CLI flag you add) is set; otherwise still warn but print full error
output and include the elapsed time using dtsStart so you can debug
missing/failed .d.ts generation.

In `@src/service.ts`:
- Around line 562-565: getTokenPair and getHistoricalPrices are calling fetch()
directly (the two fetch(...) calls creating inputResponse/outputResponse and the
later historical price fetches), bypassing the app's rate-limiting queue and
risking 429s; change these to use the same queued/throttled request path used
for quotes/swaps (i.e., route the token metadata and historical-price HTTP
requests through the existing queue dispatch/enqueue method instead of calling
fetch() directly), or add a dedicated throttled wrapper that uses the queue for
all requests that hit api.jup.ag so both getTokenPair and getHistoricalPrices
use the centralized rate-limiter.
🧹 Nitpick comments (7)
package.json (2)

17-21: Build/dev script inconsistency: build uses Bun but dev still uses tsup.

The production build (bun run build.ts) and the dev build (tsup --format esm --dts --watch) use entirely different toolchains, which can produce subtly different output (module resolution, tree-shaking, source maps). This makes it easy to miss issues that only appear in the production build.

Consider either:

  • Adding --watch support to build.ts and using it for dev too, or
  • Keeping tsup for both until the migration is complete.

7-9: engines.bun constraint may be too loose and lacks a node engine entry.

"bun": ">=1.0.0" allows any Bun version. Since Bun.build() API has evolved across versions, consider pinning to a narrower range (e.g., ">=1.1.0"). Also, if the package is consumed by Node-based projects (the build targets node), you may want a node engine entry too.

src/service.ts (5)

228-231: Static analysis: forEach callback implicitly returns a value.

Array.push() returns the new length, so the arrow function body implicitly returns a number. While forEach ignores return values, the linter flags this as suspicious. Use a block body or prefix with void.

Proposed fix
-    this.routeCache.forEach((v, k) => {
-      if (now > v.expiry) expired.push(k);
-    });
+    for (const [k, v] of this.routeCache) {
+      if (now > v.expiry) expired.push(k);
+    }

123-129: Headers are constructed twice for swap requests — redundant but worth simplifying.

executeSwap (line 342) already calls getApiHeaders() to build payload.headers. Then getSwapWithRetry calls getApiHeaders() again and merges with payload.headers (line 128). The double call is functionally harmless but adds confusion.

Let getSwapWithRetry own header construction exclusively, and have callers pass only the request body/method — or at least document the merge contract.

Proposed simplification in executeSwap
       const swapData = await swapEnqueue(`${JUPITER_BASE_URL}/swap`, {
         method: 'POST',
-        headers: getApiHeaders(),
         body: JSON.stringify(body),
       })

34-60: Network-level fetch failures (DNS, TCP, TLS) are not retried.

Both getQuoteWithRetry and getSwapWithRetry only retry on HTTP 429 responses. If fetch itself throws (e.g., TypeError for DNS resolution failure, connection reset, or timeout), the error propagates immediately and exhausts no retries. Wrapping the fetch call in a try/catch inside the loop and treating transient network errors as retryable would improve resilience.

Also applies to: 123-151


37-37: Debug console.log statements should use logger or be removed.

Multiple console.log calls are scattered throughout the queue and retry functions (e.g., lines 37, 43, 91, 100, 126, 166, 175). These bypass the structured logger used elsewhere in the service and will produce noisy output in production. Either promote them to logger.debug / logger.info or remove them.

Also applies to: 91-91, 100-100, 126-126, 166-166, 175-175


262-262: Use Math.trunc() instead of parseInt(String(amount)) for clarity and efficiency.

The parseInt(String(amount)) pattern works correctly, but is unnecessarily verbose. Since amount is already a number, Math.trunc(amount) directly truncates the value and is the idiomatic approach in modern JavaScript.

Suggested change
-      const intAmount = parseInt(String(amount))
+      const intAmount = Math.trunc(amount)

Iteration 1

prr-fix:prrc_kwdootnhpm6mw0no
prr-fix:prrc_kwdootnhpm6mw0nq
prr-fix:prrc_kwdootnhpm6nec1l
prr-fix:prrc_kwdootnhpm6nec1n
prr-fix:prrc_kwdootnhpm6neder
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: 2

🤖 Fix all issues with AI agents
In `@src/service.ts`:
- Around line 244-251: The queue timer loops started by startQueues() (which
calls checkQuoteQueues, checkSwapQueues, checkMetadataQueues) never get
cancelled because stop() only flips isRunning and queuesStarted prevents
restart; update the implementation to track the timer IDs (e.g., store them in a
module-level object or array like queueTimerIds) when scheduling setTimeout in
each check*Queue and add a new stopQueues() that clears those timers with
clearTimeout and resets queuesStarted; alternatively (or in addition) make each
check*Queue read a running flag (isRunning or queuesRunning) at the top and stop
rescheduling when false; finally call stopQueues() from stop() to ensure timers
are cancelled and stale chains are broken.
- Line 327: The code uses parseInt(String(amount)) to derive intAmount which is
fragile for large number-typed amount values; replace this expression with an
explicit numeric truncation like Math.trunc(Number(amount)) (or
Math.floor(Number(amount)) if you prefer rounding down) to drop any fractional
atomic units safely; update the assignment to intAmount and remove
parseInt(String(amount)) references so amount (the number parameter) is
converted via Number(...) and truncated with Math.trunc to avoid
scientific-notation parsing issues.
🧹 Nitpick comments (4)
src/service.ts (4)

405-409: Redundant double-application of API headers in executeSwap.

getApiHeaders(this.apiKey) is set in the payload at line 407, and then this.apiKey is also passed as the third argument to swapEnqueue. Inside getSwapWithRetry (line 127), headers are rebuilt from the apiKey param and merged with payload.headers — so the same headers are computed and spread twice.

Pick one path: either pass headers in the payload or rely on the apiKey parameter. The current duplication will silently mask bugs if the two diverge.

Suggested: drop headers from payload, let getSwapWithRetry handle it
       const swapData = await swapEnqueue(`${JUPITER_BASE_URL}/swap`, {
         method: 'POST',
-        headers: getApiHeaders(this.apiKey),
         body: JSON.stringify(body),
       }, this.apiKey)

293-296: Arrow function in forEach implicitly returns the result of Map.delete().

Static analysis flags this as useIterableCallbackReturn. Trivial fix: add braces or use a for...of loop.

Fix
-    expired.forEach(k => this.routeCache.delete(k));
+    for (const k of expired) this.routeCache.delete(k);

32-34: Scattered console.log debug statements — use logger consistently.

The module imports logger from @elizaos/core but the queue/retry functions use raw console.log for debug output (lines 34, 40, 89, 98, 125, 133, 174, 203, 231, 238). These should use logger.debug or logger.info for consistent log levels and structured output, and the commented-out console.log lines (32, 50, etc.) should be removed.

Also applies to: 40-40, 89-89, 98-98


648-684: getHistoricalPrices returns current snapshots — consider renaming.

The method name and return type (Array<{ timestamp: number; price: number }>) suggest time-series data, but it returns at most two current-price entries. The inline comments acknowledge this, but callers will find the API misleading. Consider renaming to getCurrentPrices or getPriceSnapshot to match the actual behavior. If the historical signature must be preserved for backward compatibility, a @deprecated JSDoc pointing to the new name would help.

Iteration 1

prr-fix:prrc_kwdootnhpm6nec1p
prr-fix:prrc_kwdootnhpm6neg29
prr-fix:prrc_kwdootnhpm6neg2-
timestamp: now,
price: Number(tokenData.usdPrice),
});
}
Copy link

Choose a reason for hiding this comment

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

Zero-priced tokens are silently dropped

Low Severity

getCurrentPrices() uses if (tokenData?.usdPrice), which treats 0 as missing. Tokens with an actual usdPrice of 0 are omitted from results, producing incomplete price snapshots.

Fix in Cursor Fix in Web

Iteration 3

prr-fix:prrc_kwdootnhpm6mw0my
prr-fix:prrc_kwdootnhpm6mw1ex
prr-fix:prrc_kwdootnhpm6nec1n
prr-fix:prrc_kwdootnhpm6neipk
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: 3

🤖 Fix all issues with AI agents
In `@src/service.ts`:
- Around line 659-692: getCurrentPrices currently returns Array<{
timestamp:number; price:number }> with no mint identifier, breaking mapping when
one token is missing; modify the function (getCurrentPrices) to include the mint
address in each returned entry (e.g. { mint: string; timestamp: number; price:
number }) and update the method's return type accordingly, ensure the loop that
builds prices uses the loop variable mint to set the mint field and still only
includes entries when usdPrice is defined, and adjust any callers or type
annotations that expect the old shape.
- Around line 245-258: stopQueues() currently clears timers but leaves pending
items in the quotes, swaps, and metadata queues whose promises never settle;
modify stopQueues to iterate each queue (quotes, swaps, metadata), for each
queued item call its rejectHandle (or resolveHandle if you prefer resolve) with
a clear Error explaining the queue was stopped, then clear those arrays and
clear the corresponding timers (queueTimers.quotes, queueTimers.swaps,
queueTimers.metadata) before setting queuesStarted = false; reference the
stopQueues function and the queued-item fields resolveHandle/rejectHandle to
implement the drain-and-reject behavior so callers don't hang.

In `@test_fail.ts`:
- Around line 3-11: The test currently treats the thrown error as failure;
invert the exit logic in async function main so the expected path (await $`bun
run non_existent_command` throws) results in process.exit(0) and the unexpected
path (no throw) results in process.exit(1). Update the try/catch around the
awaited command in main: on success (no exception) log the unexpected outcome
and call process.exit(1), and in the catch block log the expected outcome and
call process.exit(0).
🧹 Nitpick comments (5)
src/service.ts (5)

297-312: Static analysis: forEach callback implicitly returns the boolean from Map.delete().

Line 304's arrow function k => this.routeCache.delete(k) returns the boolean result of delete(). While harmless at runtime, it triggers the Biome lint rule useIterableCallbackReturn. Use a block body to suppress the implicit return.

Proposed fix
-    expired.forEach(k => this.routeCache.delete(k));
+    expired.forEach(k => { this.routeCache.delete(k); });

413-417: Headers are applied twice for swap requests.

executeSwap constructs the payload with headers: getApiHeaders(this.apiKey) (line 415) and also passes this.apiKey as the third argument to swapEnqueue (line 417). Inside getSwapWithRetry (line 128-129), the API headers are merged again via { ...getApiHeaders(apiKey), ...payload.headers }. The result is correct (same key both times) but redundant — either pass headers in the payload or via apiKey, not both.

Proposed fix — let getSwapWithRetry own the headers
       const swapData = await swapEnqueue(`${JUPITER_BASE_URL}/swap`, {
         method: 'POST',
-        headers: getApiHeaders(this.apiKey),
         body: JSON.stringify(body),
       }, this.apiKey)

7-7: Queue items and enqueue functions are entirely untyped.

The three queues use any[] and the process*Queue functions accept untyped parameters. Introducing a simple interface per queue item would catch mismatches at compile time and improve IDE support.

Example interface sketch
interface QueueItem<T = unknown> {
  url: string;
  apiKey: string | null;
  resolveHandle: (value: T) => void;
  rejectHandle: (reason?: unknown) => void;
}

interface SwapQueueItem extends QueueItem {
  payload: RequestInit;
}

Also applies to: 61-74, 106-121, 182-196


636-639: Promise.all with two metadata-queue items serialises to ~2 s minimum.

Both metadataEnqueue calls enter the same 1 RPS queue, so they execute sequentially despite the Promise.all. This is technically correct for rate limiting, but if latency matters for getTokenPair, consider batching both mints into a single request (if the API supports it) or documenting the expected delay.


32-58: Retry loops lack a jitter component, risking thundering-herd on shared queues.

Both getQuoteWithRetry and getMetadataWithRetry (and getSwapWithRetry) use pure exponential backoff (delay *= 2) on 429s. When multiple items are queued and all hit 429 simultaneously, they'll all retry at the same wall-clock intervals. Adding a small random jitter (e.g., delay *= 2; delay += Math.random() * 500;) would spread retries out.

Also applies to: 198-218

Comment on lines 659 to 692
async getCurrentPrices({
inputMint,
outputMint,
timeframe = '24h', // Options: 1h, 24h, 7d, 30d
}: {
inputMint: string;
outputMint: string;
timeframe?: string;
}): Promise<Array<{ timestamp: number; price: number }>> {
try {
// Fetch historical price data from Jupiter API
const response = await fetch(
`https://public.jupiterapi.com/v1/prices/${inputMint}/${outputMint}?timeframe=${timeframe}`
// Routed through metadata queue to respect rate limits
const result: any = await metadataEnqueue(
`https://api.jup.ag/price/v3?ids=${inputMint},${outputMint}`,
this.apiKey
);

if (!response.ok) {
throw new Error('Failed to fetch historical prices');
const prices: Array<{ timestamp: number; price: number }> = [];
const now = Date.now();

for (const mint of [inputMint, outputMint]) {
const tokenData = result[mint];
// Check for defined price, allowing 0
if (tokenData && tokenData.usdPrice !== undefined && tokenData.usdPrice !== null) {
prices.push({
timestamp: now,
price: Number(tokenData.usdPrice),
});
}
}

return await response.json();
return prices;
} catch (error) {
logger.error('Failed to get historical prices:', error);
logger.error('Failed to get prices:', error);
throw error;
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

getCurrentPrices return type doesn't identify which token each price belongs to.

The method returns Array<{ timestamp: number; price: number }> with up to two entries, but there's no way for the caller to know which element corresponds to inputMint vs outputMint. If one token has no price data, the array shrinks and the positional mapping breaks. Consider including the mint address in each entry.

Proposed adjustment
-  const prices: Array<{ timestamp: number; price: number }> = [];
+  const prices: Array<{ mint: string; timestamp: number; price: number }> = [];
   ...
         prices.push({
+          mint,
           timestamp: now,
           price: Number(tokenData.usdPrice),
         });

Also note: the return type signature still says Array<{ timestamp: number; price: number }> — update the method signature to match if you add the mint field.

🤖 Prompt for AI Agents
In `@src/service.ts` around lines 659 - 692, getCurrentPrices currently returns
Array<{ timestamp:number; price:number }> with no mint identifier, breaking
mapping when one token is missing; modify the function (getCurrentPrices) to
include the mint address in each returned entry (e.g. { mint: string; timestamp:
number; price: number }) and update the method's return type accordingly, ensure
the loop that builds prices uses the loop variable mint to set the mint field
and still only includes entries when usdPrice is defined, and adjust any callers
or type annotations that expect the old shape.

Iteration 1

prr-fix:prrc_kwdootnhpm6mw1ex
prr-fix:prrc_kwdootnhpm6nedeq
prr-fix:prrc_kwdootnhpm6nfiha
prr-fix:prrc_kwdootnhpm6nfijz
prr-fix:prrc_kwdootnhpm6nfij1
outputMint: string;
timeframe?: string;
}): Promise<Array<{ timestamp: number; price: number }>> {
}): Promise<Array<{ mint: string; timestamp: number; price: number }>> {
Copy link

Choose a reason for hiding this comment

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

Public price API contract was broken

Medium Severity

The commit removes getHistoricalPrices and replaces it with getCurrentPrices with a different request/response contract. Existing consumers calling getHistoricalPrices or relying on timeframe and historical point output will break because there is no compatibility method or adapter in src/service.ts.

Additional Locations (1)

Fix in Cursor Fix in Web

Iteration 3

prr-fix:prrc_kwdootnhpm6mw-ag
prr-fix:prrc_kwdootnhpm6neg2-
prr-fix:prrc_kwdootnhpm6mw0nd
prr-fix:prrc_kwdootnhpm6neiph
prr-fix:prrc_kwdootnhpm6neipi
prr-fix:prrc_kwdootnhpm6nfig9
prr-fix:prrc_kwdootnhpm6nfijx
Iteration 1

prr-fix:prrc_kwdootnhpm6nfig9
prr-fix:prrc_kwdootnhpm6mw-ag
prr-fix:prrc_kwdootnhpm6mw-ai
prr-fix:prrc_kwdootnhpm6mw-ak
prr-fix:prrc_kwdootnhpm6nec1l
prr-fix:prrc_kwdootnhpm6neiph
prr-fix:prrc_kwdootnhpm6neipi
prr-fix:prrc_kwdootnhpm6nf5rl
prr-fix:prrc_kwdootnhpm6ngqp2
prr-fix:prrc_kwdootnhpm6ngbhr
prr-fix:prrc_kwdootnhpm6ngbht
prr-fix:prrc_kwdootnhpm6ngvcq
prr-fix:prrc_kwdootnhpm6nla7u
prr-fix:prrc_kwdootnhpm6n-mbg
prr-fix:prrc_kwdootnhpm6neg29
prr-fix:prrc_kwdootnhpm6ngqp5
prr-fix:prrc_kwdootnhpm6nfiha
prr-fix:prrc_kwdootnhpm6ngpvu
prr-fix:prrc_kwdootnhpm6oavuv
prr-fix:prrc_kwdootnhpm6oavur
prr-fix:prrc_kwdootnhpm6oas3t
prr-fix:prrc_kwdootnhpm6ngxtt
Iteration 3

prr-fix:prrc_kwdootnhpm6n_86m
prr-fix:prrc_kwdootnhpm6nfijx
prr-fix:prrc_kwdootnhpm6mw0no
prr-fix:prrc_kwdootnhpm6mw0nq
prr-fix:prrc_kwdootnhpm6neder
prr-fix:prrc_kwdootnhpm6neg2-
delayInMs -= took
if (delayInMs < 0) delayInMs = 0
console.log('swap took', took.toLocaleString() + 'ms', 'delay now', delayInMs)
}
Copy link

Choose a reason for hiding this comment

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

Three queue checker functions are unreachable dead code

Medium Severity

checkQuoteQueues, checkSwapQueues, and checkMetadataQueues (~130 lines total) are never invoked. startQueues only calls the unified checkQueues function, which handles all three queue types via dequeueNextItem. These three functions only reference themselves recursively and are completely dead code. They share the inFlight and nextRequestAt state with the active checkQueues, so if they were ever accidentally called, they'd corrupt the rate-limiting logic.

Additional Locations (2)

Fix in Cursor Fix in Web

Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
Iteration 2

prr-fix:prrc_kwdootnhpm6nf5ri
prr-fix:prrc_kwdootnhpm6oyyin
prr-fix:prrc_kwdootnhpm6mw1ex
delayInMs -= took
if (delayInMs < 0) delayInMs = 0
console.log('swap took', took.toLocaleString() + 'ms', 'delay now', delayInMs)
}
Copy link

Choose a reason for hiding this comment

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

Dead per-queue processor functions never called

Medium Severity

checkQuoteQueues, checkSwapQueues, and checkMetadataQueues (~90 lines total) are fully implemented but never called from any entry point. startQueues only invokes the unified checkQueues function. These dead functions also read and write the same shared mutable state (inFlight, nextRequestAt, timers) as the active checkQueues, creating a fragile situation where accidentally re-enabling any of them would cause conflicting concurrent queue processing and rate-limit violations.

Additional Locations (2)

Fix in Cursor Fix in Web

Iteration 1

prr-fix:prrc_kwdootnhpm6oas3s
prr-fix:prrc_kwdootnhpm6nla7p
prr-fix:prrc_kwdootnhpm6n-mbd
prr-fix:prrc_kwdootnhpm6n_sro
prr-fix:prrc_kwdootnhpm6n_xkn
prr-fix:prrc_kwdootnhpm6oy_tm
`https://api.jup.ag/markets/v1?baseMint=${inputMint}&quoteMint=${outputMint}`,
this.getApiHeaders()
),
]) as [any[], any[], any];
Copy link

Choose a reason for hiding this comment

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

getTokenPair bypasses rate-limiting queue with concurrent requests

High Severity

getTokenPair calls getMetadataWithRetry directly via Promise.all, firing 3 concurrent HTTP requests that completely bypass the shared rate-limiting queue. Every other API method (getQuote, executeSwap, getCurrentPrices) correctly uses its respective enqueue function (quoteEnqueue, swapEnqueue, metadataEnqueue). The metadataEnqueue function exists specifically for this purpose and is correctly used in getCurrentPrices. These unqueued concurrent requests will likely trigger 429 rate-limit errors from the Jupiter API.

Additional Locations (2)

Fix in Cursor Fix in Web

Changes:
- package.json: The `--watch` flag is passed to `build.ts`, but `build.ts` doesn't implement ...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- package.json: package.json switches build/dev scripts to Bun, but the repo doesn’t declare ...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- package.json: ### Dev script `--watch` flag is silently ignored

**Medium Severity**

<!-- ...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
Iteration 1

prr-fix:prrc_kwdootnhpm6pevbs
Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- build.ts: The `if (true) { // Always generate .d.ts } else { ... }` block is dead code ...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- build.ts: ### Build succeeds after declaration failures

**Medium Severity**

<!-- DESC...
- build.ts: _⚠️ Potential issue_ | _🟠 Major_

**Silently continuing after declaration ge...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
Iteration 1

prr-fix:prrc_kwdootnhpm6oyyip
prr-fix:prrc_kwdootnhpm6oy_ty
prr-fix:prrc_kwdootnhpm6pe3so
Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- build.ts: The `if (true) { // Always generate .d.ts } else { ... }` block is dead code ...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- build.ts: ### Build succeeds after declaration failures

**Medium Severity**

<!-- DESC...
- build.ts: _⚠️ Potential issue_ | _🟠 Major_

**Silently continuing after declaration ge...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### PR review tool comments committed as code

**Low Severity**

<!-- DESCRIP...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### Automated review comments left in production code

**Low Severity**

<!--...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
- build.ts: ### Dev watch mode never activates in build script

**Medium Severity**

<!--...
Changes:
- package.json: The `--watch` flag is passed to `build.ts`, but `build.ts` doesn't implement ...
- build.ts: The `if (true) { // Always generate .d.ts } else { ... }` block is dead code ...
- package.json: package.json switches build/dev scripts to Bun, but the repo doesn’t declare ...
- package.json: ### Dev script `--watch` flag is silently ignored

**Medium Severity**

<!-- ...
- build.ts: ### Build succeeds after declaration failures

**Medium Severity**

<!-- DESC...
- build.ts: _⚠️ Potential issue_ | _🟠 Major_

**Silently continuing after declaration ge...
- build.ts: ### Dev watch mode never activates in build script

**Medium Severity**

<!--...
Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### PR review tool comments committed as code

**Low Severity**

<!-- DESCRIP...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### Automated review comments left in production code

**Low Severity**

<!--...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### PR review tool comments committed as code

**Low Severity**

<!-- DESCRIP...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### Automated review comments left in production code

**Low Severity**

<!--...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### PR review tool comments committed as code

**Low Severity**

<!-- DESCRIP...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### Automated review comments left in production code

**Low Severity**

<!--...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
Changes:
- build.ts: The `if (true) { // Always generate .d.ts } else { ... }` block is dead code ...
- build.ts: ### Dead else branch due to `if (true)` conditional

**Low Severity**

<!-- D...
- build.ts: ### Build succeeds after declaration failures

**Medium Severity**

<!-- DESC...
- build.ts: _⚠️ Potential issue_ | _🟠 Major_

**Silently continuing after declaration ge...
- build.ts: ### Dev watch mode never activates in build script

**Medium Severity**

<!--...
Explains reasoning for dismissed issues inline in code
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

queueState.timers.shared = setTimeout(() => {
if (!queueState.started) return;
checkQueues(queueState);
}, delayInMs);
Copy link

Choose a reason for hiding this comment

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

Duplicate queue chains after rapid stop-start cycle

Low Severity

If stopQueues runs while checkQueues is awaiting an in-flight request (between inFlight = true and the post-await code), then startQueues is called before the old await completes, the old checkQueues invocation resumes and finds queueState.started === true (set by the new startQueues). It skips the early-return at line 246 and schedules a new timeout, creating a second concurrent checkQueues chain alongside the one from the new startQueues. Both chains persist indefinitely. The inFlight and nextRequestAt guards mostly prevent concurrent API calls, but having two polling loops wastes resources and could cause subtle timing issues under load.

Additional Locations (2)

Fix in Cursor Fix in Web

Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### PR review tool comments committed as code

**Low Severity**

<!-- DESCRIP...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### Automated review comments left in production code

**Low Severity**

<!--...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- build.ts: The `if (true) { // Always generate .d.ts } else { ... }` block is dead code ...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- build.ts: ### Dead else branch due to `if (true)` conditional

**Low Severity**

<!-- D...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- build.ts: ### Build succeeds after declaration failures

**Medium Severity**

<!-- DESC...
- build.ts: _⚠️ Potential issue_ | _🟠 Major_

**Silently continuing after declaration ge...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### PR review tool comments committed as code

**Low Severity**

<!-- DESCRIP...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### Automated review comments left in production code

**Low Severity**

<!--...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
- build.ts: ### Dev watch mode never activates in build script

**Medium Severity**

<!--...
Explains reasoning for dismissed issues inline in code
Explains reasoning for dismissed issues inline in code
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

- Fix for src/service.ts:679 - The diff renamed getCurrentPrices to getHistoricalPrices but didn't preserve a getCurrentPrices method—must add new method instead of renaming existing one.
- Fix for src/service.ts:679 - The diff must show the OLD broken implementation at lines 650-679 being replaced/removed, not just ADD a new method elsewhere.
- Fix for src/service.ts:679 - The new throwing method was added but the old broken implementation at lines 669-690 wasn't removed — need to replace the existing method body, not add a duplicate method definition below it.
- Fix for src/service.ts:695 - The review asks to fix the bug in `getHistoricalPrices` (lines 614-625), not replace it with a stub that throws an error.
Copy link

Choose a reason for hiding this comment

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

Auto-generated review tool state committed to repo

Low Severity

The .prr/lessons.md file contains auto-generated debugging notes from the PRR review tool, describing specific failed fix attempts with line numbers and review interactions (e.g., "The new throwing method was added but the old broken implementation at lines 669-690 wasn't removed"). These context-specific tool outputs are confusing to future developers and add noise to the repository.

Fix in Cursor Fix in Web

Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- build.ts: The `if (true) { // Always generate .d.ts } else { ... }` block is dead code ...
- build.ts: build.ts invokes `tsc --project tsconfig.build.json`, but `typescript` is not...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- build.ts: ### Dead else branch due to `if (true)` conditional

**Low Severity**

<!-- D...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- build.ts: ### Build succeeds after declaration failures

**Medium Severity**

<!-- DESC...
- build.ts: _⚠️ Potential issue_ | _🟠 Major_

**Silently continuing after declaration ge...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### PR review tool comments committed as code

**Low Severity**

<!-- DESCRIP...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### Automated review comments left in production code

**Low Severity**

<!--...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
- build.ts: ### Dev watch mode never activates in build script

**Medium Severity**

<!--...
Changes:
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Module-level `jupiterApiKey` is shared a...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`routeCache` grows without bound — poten...
- service.ts: If `JUPITER_API_KEY` is missing, start() only logs a warning and continues, b...
- service.ts: ### API key not reset when service starts without key

**Low Severity**

<!--...
- service.ts: ### Route cache key omits slippageBps causing stale results

**Medium Severit...
- service.ts: ### Token search with concatenated mints returns no results

**High Severity*...
- service.ts: ### Missing API key silently deadlocks all queued requests

**High Severity**...
- service.ts: ### Token search matches wrong field

**Medium Severity**

<!-- DESCRIPTION S...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Token and price fetches bypass the rate-...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**Queue timers are never cancelled on `sto...
- service.ts: _⚠️ Potential issue_ | _🟡 Minor_

**`parseInt(String(amount))` is fragile fo...
- service.ts: ### Global queue shutdown breaks active instances

**Medium Severity**

<!-- ...
- service.ts: ### Queue workers restart after service stop

**Medium Severity**

<!-- DESCR...
- service.ts: ### Queue timers can restart after service stop

**Medium Severity**

<!-- DE...
- service.ts: _⚠️ Potential issue_ | _🟠 Major_

**`stopQueues()` leaves enqueued items wit...
- service.ts: ### Public price API contract was broken

**Medium Severity**

<!-- DESCRIPTI...
- service.ts: ### Stop leaves queued requests unresolved

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Rate limiting no longer global

**Medium Severity**

<!-- DESCRIPTION STA...
- service.ts: ### Requests can hang when service is stopped

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair metrics are no longer pair-specific

**Medium Severity**

<!--...
- service.ts: ### Historical price endpoint no longer supported

**Medium Severity**

<!-- ...
- service.ts: ### Token volume field parsed incorrectly

**Low Severity**

<!-- DESCRIPTION...
- service.ts: ### Historical price endpoint path is invalid

**Medium Severity**

<!-- DESC...
- service.ts: ### Unsupported markets endpoint breaks pair lookup

**Medium Severity**

<!-...
- service.ts: ### Historical price path is not valid

**Medium Severity**

<!-- DESCRIPTION...
- service.ts: ### Token pair silently hides API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair response keys unexpectedly renamed

**Medium Severity**

<!-- ...
- service.ts: ### Historical prices return shape was broken

**Medium Severity**

<!-- DESC...
- service.ts: ### Token pair silently masks API failures

**Medium Severity**

<!-- DESCRIP...
- service.ts: ### Token pair failures are silently masked

**Medium Severity**

<!-- DESCRI...
- service.ts: ### Three independent queues exceed combined API rate limit

**Medium Severit...
- service.ts: ### Metadata queue infrastructure duplicates quote queue logic

**Medium Seve...
- service.ts: ### Sequential metadata queue makes `getTokenPair` very slow

**Medium Severi...
- service.ts: ### PR review tool comments left in production code

**Low Severity**

<!-- D...
- service.ts: ### Three queue checker functions are unreachable dead code

**Medium Severit...
- service.ts: ### PR review tool comments committed as code

**Low Severity**

<!-- DESCRIP...
- service.ts: ### Dead per-queue processor functions never called

**Medium Severity**

<!-...
- service.ts: ### Automated review comments left in production code

**Low Severity**

<!--...
- service.ts: ### `getTokenPair` bypasses rate-limiting queue with concurrent requests

**H...
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

});
// Keep the process running
await new Promise(() => {});
}
Copy link

Choose a reason for hiding this comment

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

Watch mode creates exponentially growing duplicate watchers

Medium Severity

When watch mode is active, the fs.watch callback calls build() recursively. Since isWatch is recomputed from the same process.argv each time, it's always true in the recursive call, causing another fs.watch watcher to be registered on the same src/ directory. After N file changes, there are 2^N watchers — each subsequent change triggers exponentially many concurrent full rebuilds and eventually exhausts system resources.

Additional Locations (1)

Fix in Cursor Fix in Web

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.

1 participant