ED Rare Router
Last Updated: March 1, 2026
Author: R.W. Harper
LinkedIn: https://linkedin.com/in/rwhwrites
License: GNU General Public License v3.0
THIS IS A DEVELOPMENT/HOBBY PROJECT - USE AT YOUR OWN RISK
This software is provided "AS IS" without warranty of any kind, express or implied. No guarantees or warranties are given. The authors and contributors are not liable for any damages arising from use of this software. See the LICENSE file for full terms.
The dataset contains 142 rare commodities, but external references indicate 140 rare commodities. This 2-item discrepancy requires investigation.
Verification Results:
- Total entries in
src/data/rares.ts: 142 - Unique rare names: 142
- Duplicate rare names: 0
- Items appearing in multiple locations: 0
Conclusion: There are no duplicate entries in the dataset. All 142 items are unique rare commodities.
Some sources may count Onionhead variants as a single item:
OnionheadOnionhead Alpha StrainOnionhead Beta StrainLucan Onionhead(separate item, different location)
Note: These are distinct items with different names and locations, but some references may group the first three together.
Two related items from different systems:
Ophiuchi Exino(from 39 Tauri)Ophiuch Exino Artefacts(from 36 Ophiuchi)
Note: These are separate items from different systems, but the similar names might cause confusion in some references.
Some sources may exclude certain items from the "rare commodities" count:
- Items that are no longer available in-game
- Items that are considered "special" rather than standard rare commodities
- Items that require special conditions to obtain
The following items should be cross-referenced with authoritative sources to confirm they are standard rare commodities:
- Onionhead variants - Verify if all three strains should be counted separately
- Ophiuch items - Verify if both should be counted or if one is a variant
- Any items marked as "special" or "limited" - Check if these are excluded from standard counts
- Dataset count: 142 items
- Reference count: 140 items
- Discrepancy: 2 items
- Status: Still being verified
- Documentation: Updated to reflect "140-142 rare commodities (still being verified)"
- Compare dataset against authoritative reference (e.g., Inara.cz complete list)
- Identify which 2 items are the discrepancy
- Determine if discrepancy is due to:
- Counting methodology (variants vs. separate items)
- Items no longer in-game
- Special cases excluded from standard count
- Update documentation once verified
src/data/rares.ts- Main datasetREADME.md- Updated to show "140-142 (still being verified)"docs/data-appendix.md- Dataset statistics
EDSM API does not return market commodity data via public API endpoints.
Even when using showMarket=1 parameter, the EDSM API only returns:
haveMarket: true(indicates market exists)updateTime.market(last update timestamp)- No
market.commoditiesarray (commodity data is not included)
- EDSM's public API is designed for system/station information, not market data
- Market commodity data is not exposed via the public API
- Even if players have uploaded market data, it's not accessible via API
- Market data requires direct database access or EDDN integration
- EDDN Worker (Recommended) - Real-time market data via ZeroMQ
- Manual Price Curation - Add baseline prices via
/curate-pricesinterface - Accept Limited Results - Use EDDN worker for real-time data
docs/edsm-market-data-limitations.md- Detailed explanationdocs/bulk-market-data-fetch.md- Bulk fetch documentationworkers/eddn-worker.js- EDDN worker implementation
The application uses a priority system when displaying costs:
-
EDDN Live Market Data (Highest Priority)
- Real-time data from EDDN worker
- Shows:
"(Live)"label - Source:
data/eddnMarketCache.json - Updated: Real-time as EDDN messages are received
-
Curated Baseline Prices (Second Priority)
- Manually entered via
/curate-pricesinterface - Shows:
"(Est.)"label - Source:
data/curatedPrices.json - Updated: Manual curation in development mode
- Manually entered via
-
Static Costs from Base Data (Third Priority)
- Hardcoded in
src/data/rares.ts - Shows:
"(Est.)"label - Source: Static dataset
- Updated: Code changes only
- Hardcoded in
-
"N/A" (Fallback)
- Displayed when none of the above are available
- EDDN data is most accurate but requires worker to be running
- Curated prices provide fallback when EDDN data isn't available
- Static costs provide baseline for items without curated data
- "N/A" indicates no price information is available
src/lib/eddnMarketCache.ts- EDDN cache readersrc/lib/curatedPrices.ts- Price curation systemsrc/pages/api/rares-scan.ts- Price priority logicsrc/components/ResultsList.tsx- Price display logic
existsSync is not a function error in cache-status API endpoint.
existsSync was incorrectly imported from fs/promises instead of fs.
fs/promisescontains only async functions (returns Promises)existsSyncis a synchronous function and exists only infs- Mixing imports caused the function to be undefined
Changed from:
import { readFile, existsSync } from "fs/promises";To:
import { readFile } from "fs/promises";
import { existsSync } from "fs";src/pages/api/cache-status.ts- Fixed import
ZeroMQ v6 uses a different API than v5, causing zmq.socket is not a function errors.
ZeroMQ v6 changed from function-based API to class-based API.
-
Import Change:
// Old (v5) import zmq from 'zeromq'; // New (v6) import { Subscriber } from 'zeromq';
-
Socket Creation:
// Old (v5) const subscriber = zmq.socket('sub'); // New (v6) const subscriber = new Subscriber();
-
Connection:
// Old (v5) subscriber.connect(EDDN_RELAY); // New (v6) await subscriber.connect(EDDN_RELAY);
-
Message Handling:
// Old (v5) - Event-based subscriber.on('message', (topic, message) => { processMarketMessage(message); }); // New (v6) - Async iteration for await (const [topic, message] of subscriber) { await processMarketMessage(message); }
-
Shutdown:
// Old (v5) subscriber.close(); // New (v6) await subscriber.close();
- Message Decompression: EDDN messages are zlib-compressed and must be decompressed before parsing
- Frame Structure: ZeroMQ v6 returns frames differently - may be array or single value
- Error Handling: Socket closure errors should be handled gracefully
workers/eddn-worker.js- Updated to v6 APIpackage.json- Useszeromq@^6.0.0-beta.20
EDDN cache file has deeply nested structure: { _metadata: {...}, data: { _metadata: {...}, data: { _metadata: {...}, data: {} } } }
Worker's saveCache() function was saving marketCache which may have already contained nested structure from previous saves. The cache loading logic didn't properly unwrap nested structures.
-
Cache Loading (
workers/eddn-worker.js):- Added logic to detect and unwrap nested structures
- Ensures
marketCacheis always a flat object
-
Cache Reading (
src/lib/eddnMarketCache.ts):- Added recursive unwrapping logic
- Handles deeply nested structures
- Detects actual market data by checking for keys that look like "System|Station"
- Worker now ensures
marketCacheis always flat before saving - Cache reader handles nested structures gracefully
- Future saves will maintain correct structure
workers/eddn-worker.js- Cache save/load logicsrc/lib/eddnMarketCache.ts- Cache reader with unwrapping
- No Public API: No public API provides baseline purchase prices for rare goods
- EDDN Dependency: Real-time prices require EDDN worker to be running and receiving data
- Fallback Needed: Users need price information even when EDDN data isn't available
- Data Accuracy: Manual curation allows verification and correction of prices
- Development-Only Interface: Price curation is only available in development mode for security
- Separate from Legality: Price curation is separate from legality curation for clarity
- Fallback Priority: Curated prices are used as fallback, not primary source
- JSON Storage: Simple file-based storage for easy backup and version control
src/lib/curatedPrices.ts- Price curation librarysrc/pages/api/curated-prices.ts- Price curation APIsrc/components/PriceCurator.tsx- Price editor componentsrc/pages/curate-prices.astro- Price curation page
This document will be updated as new issues are discovered, analyzed, and resolved. When adding new entries:
- Date the entry - Include when the issue was discovered/resolved
- Explain the root cause - Not just the symptom
- Document the fix - Include code examples if applicable
- Link related files - Help future developers find relevant code
- Note prevention - How to avoid the issue in the future