The AI Newsroom That Trades Its Own Stories
An autonomous financial wire service that publishes AI-written market intelligence
from SoSoValue data, detects narrative regime shifts, and auto-executes trades on SoDEX.
Built in 96hrs for SosoValue Hackathon in last wave, Ranked 24th overall.
Features β’ Architecture β’ Getting Started β’ API Integration β’ Demo β’ License
Crypto traders face three compounding problems:
- Information overload β Thousands of data points (ETF flows, sector performance, news) arrive every hour. No human can process it all.
- Narrative blindness β Markets move on stories, not just numbers. "AI rotation," "institutional accumulation," "regulatory fear" β these narratives drive price before indicators catch up. But detecting narrative shifts requires reading hundreds of articles.
- Execution delay β Even when a trader spots a shift, the manual process of analysis β decision β execution takes hours or days. By then, the move has happened.
Cinder solves all three by combining an AI financial wire service with a narrative regime detection engine and an automated trading executor:
| Layer | What It Does | How |
|---|---|---|
| π° Wire Layer | Publishes institutional-grade market reports 24/7 | AI generates stories from SoSoValue's ETF flow, sector, and AI news data |
| π§ Narrative Layer | Detects when the dominant market story is changing | NLP pipeline classifies narrative regimes and tracks temperature shifts |
| β‘ Execution Layer | Trades the narrative shift before the crowd | Auto-executes on SoDEX with risk controls, stop-losses, and human override |
The key insight: The published news articles are the trade rationale. Every trade Cinder makes has a corresponding article explaining exactly why. Full transparency β no black-box trading.
- Market Pulse reports published every 4 hours with ETF flow summaries, sector movers, and AI-generated analysis
- Daily Deep Dives β long-form institutional reports with charts, data tables, and trade recommendations
- Breaking Alerts β published immediately when a narrative regime shift is detected
- All stories auto-generated from live SoSoValue API data β zero human writers
- Embedded interactive charts (ETF flow trends, sector heatmaps, narrative timelines)
- Telegram alerts for subscribers
- Real-time Narrative Temperature tracking (0β100Β°) for 8+ recurring crypto narrative archetypes
- Multi-signal detection using three independent SoSoValue data streams:
- News NLP: Topic extraction and keyword frequency analysis from SoSoValue's AI news feed
- Flow Analysis: ETF inflow/outflow trend direction and acceleration
- Sector Rotation: SSI index relative performance and cross-sector correlation
- Narrative Shift Detection β triggers when a dominant narrative cools while an emerging one heats up
- Confidence Scoring β requires β₯80% confidence and 2+ signal agreement before any trade action
- Interactive Narrative Bubble Map visualization showing all tracked narratives and their temperatures in real-time
- Historical Narrative Timeline β scrollable view of past regime shifts with portfolio performance overlay
- Auto-executes portfolio rebalancing on SoDEX when narrative shift confidence exceeds threshold
- Risk Controls:
- Maximum 30% portfolio allocation per narrative trade
- Trailing stop-loss at -8% from entry
- 48-hour cooldown between consecutive narrative trades
- Multi-signal confirmation required (no single-signal trades)
- One-click human override to pause auto-trading
- Trade confirmation published as a "Breaking" story with full reasoning
- Real-time portfolio dashboard with positions, PnL, and allocation breakdown
- Trade history linked to the stories that triggered each trade
- Connect any EIP-1193 browser wallet (MetaMask, Rabby, Coinbase Wallet, etc.); account switches are followed live
- Users trade with their own USDC on their own SoDEX account. Cinder never holds funds.
- "Enable trading" asks the wallet for two gas-free signatures: a trading key kept in the browser (places and cancels orders for 7 days, can never withdraw or transfer), and approval of Cinder's builder fee
- Orders are signed in the browser and sent straight to SoDEX; the portfolio reads balances, open orders and fills from SoDEX
- Cinder earns through SoDEX Builder Codes: a small fee on users' spot sells, paid to Cinder's account in USDC
- One setting picks the network for the whole deployment:
NEXT_PUBLIC_SODEX_NETWORK=testnetormainnet
- Restricts dApp routes
/dashboardand/portfolioto connected wallet sessions only - Automatically intercepts disconnected users using Next.js
useRouterredirects and pushes them back to/ - Render-gated home page feed showing a compact, blurred teaser story card with backdrop-filter blur and exact border alignment if disconnected
- Telegram bot for real-time narrative shift alerts and trade notifications
- Configurable alert thresholds (notify at 60Β°, trade at 80Β°)
- Daily Telegram digest with performance summary
For detailed technical architecture, see docs/ARCHITECTURE.md
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CINDER SYSTEM β
β β
β ββββββββββββββββ βββββββββββββββββ ββββββββββββββββββββ β
β β DATA LAYER ββββΆβ BRAIN LAYER ββββΆβ OUTPUT LAYER β β
β β β β β β β β
β β β’ SoSoValue β β β’ Wire Gen β β β’ News Website β β
β β ETF API β β β’ Narrative β β β’ Dashboard β β
β β β’ SoSoValue β β Detection β β β’ Telegram Bot β β
β β AI News β β β’ Trade β β β’ SoDEX Trades β β
β β β’ SoSoValue β β Execution β β β β
β β Sector API β β β β β β
β ββββββββββββββββ βββββββββββββββββ ββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Component | Technology | Rationale |
|---|---|---|
| Frontend | Next.js 14 (App Router) | SSR for SEO, API routes for backend logic |
| Styling | Vanilla CSS + CSS Variables | Dark theme, obsidian clay-glass layout, no framework overhead |
| Web3 Wallet | EIP-1193 / window.ethereum RPC | Connection to real wallets (MetaMask, Rabby) and fetching native balances |
| Charts | Recharts + D3.js | Recharts for story charts, D3 for narrative bubble map |
| Animation | Framer Motion | Smooth narrative transitions and live updates |
| AI/LLM | OpenAI-compatible API (default model mimo-v2.5) |
Story generation, news classification and refinement |
| Database | Turso (libSQL) via @libsql/client |
Hosted SQLite in production, local local.db file in development; stores stories, narrative history, trades |
| Real-time | Server-Sent Events (SSE) | Live story updates on the news feed |
| Testing | Vitest | App tests with database, LLM and SoDEX mocks; SoDEX signing checked against known signers |
| Trading | SoDEX REST API | Cinder's own orders from the server; users' orders signed in the browser with EIP-712 |
| Data | SoSoValue REST API | ETF flows, AI news feed, sector/index data |
| Alerts | Telegram Bot API | Narrative shift + trade notifications |
For detailed API integration guide, see docs/API_INTEGRATION.md
Cinder uses three SoSoValue API endpoint categories:
| Endpoint Category | Used For | Update Frequency |
|---|---|---|
| ETF Flow Data | Daily inflows/outflows for BTC, ETH, SOL ETFs | Every 4 hours |
| AI News Feed | Real-time AI-summarized crypto news | Continuous (streaming) |
| Sector/Index Data | SSI protocol index performance + composition | Every 4 hours |
Cinder uses four SoDEX API capabilities:
| Capability | Used For | Auth Required |
|---|---|---|
| Market Data (REST) | Asset pricing for portfolio valuation | No |
| Order Placement (REST) | Executing narrative-driven trades | Yes (EIP-712) |
| Order Cancellation (REST) | Stop-loss management | Yes (EIP-712) |
| Account State (REST) | Portfolio balances and positions | Yes (EIP-712) |
- Node.js β₯ 18 (CI uses Node 20)
- SoSoValue API Key: register here, then apply via the Buildathon form
- An OpenAI-compatible LLM endpoint and key: OpenAI or any provider exposing the same API (default model:
mimo-v2.5) - SoDEX account + API key (optional): register here; testnet is available without a rank requirement. Without it, Cinder runs in demo mode with simulated fills.
- Turso database for production. Local development falls back to a
local.dbSQLite file.
git clone https://github.com/Turnless/Cinder.git
cd Cinder
npm install
cp .env.example .env # then fill in your keys.env.example lists every variable with comments. The main ones:
| Variable | Needed for | Purpose |
|---|---|---|
SOSOVALUE_API_KEY |
Always | ETF flows, AI news feed, sector data |
OPENAI_API_KEY |
Always | Story generation, news classification and refinement |
OPENAI_BASE_URL, OPENAI_MODEL |
Optional | Use any OpenAI-compatible provider and model (defaults: OpenAI URL, mimo-v2.5) |
TURSO_DATABASE_URL, TURSO_AUTH_TOKEN |
Production | libSQL database; the app refuses to start in production without it |
INTERNAL_API_SECRET |
Always | Protects POST /api/stories, POST /api/narrative and trusted calls to POST /api/trade |
SODEX_API_KEY_NAME, SODEX_API_KEY_PRIVATE_KEY, USER_WALLET_ADDRESS |
Automatic trading | Cinder's own SoDEX account. Without them, Cinder's trades are simulated. Users never use these. |
SODEX_MASTER_PRIVATE_KEY |
Setup only, on your own computer | Registering Cinder's SoDEX API key with scripts/register-sodex-api-key.js. Never put it on the server. |
NEXT_PUBLIC_SODEX_NETWORK |
User trading | testnet or mainnet for the whole deployment; anything else means testnet |
NEXT_PUBLIC_SODEX_BUILDER_ID, NEXT_PUBLIC_SODEX_BUILDER_FEE |
Builder fee | Cinder's SoDEX account ID and the fee on users' sells in tenths of a basis point (50 = 0.05%). Leave the ID empty to charge nothing. |
TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, TELEGRAM_BOT_USERNAME |
Telegram alerts | Bot alerts; TELEGRAM_CHAT_ID is the admin chat |
TELEGRAM_WEBHOOK_SECRET |
Telegram alerts | Webhook authentication; must match the value used with scripts/set-telegram-webhook.js |
AUTO_TRADE_ENABLED, MAX_ALLOCATION_PER_TRADE, STOP_LOSS_PERCENTAGE, COOLDOWN_HOURS, QTY_DECIMALS |
Optional | Risk settings. Auto-trading is off unless AUTO_TRADE_ENABLED=true. |
EDGE_CONFIG, KILL_SWITCH_FAIL_CLOSED |
Optional | Vercel Edge Config kill switch (trading_paused); pauses trading if Edge Config can't be read |
NEWS_TTL_HOURS, ETF_FLOWS_TTL_HOURS |
Optional | Data retention for cached news and ETF flows |
npm run devThe app runs at http://localhost:3000. In development, the first request to /api/stories also starts the background scheduler in the same process: the hourly news and narrative cycle (including shift detection and trading), Market Pulse every 4 hours, the daily Deep Dive, stop-loss checks every 5 minutes and nightly data pruning.
To run the scheduler on its own (Node 22+):
npm run workerProduction note: Vercel doesn't keep a process running, so the scheduler doesn't run there. The live site serves stories already in the database and refreshes the news feed when people visit (at most every 5 minutes). Autonomous publishing and trading need the worker running on an always-on host: see docs/WORKER.md for setup, safe start-up and pausing.
NEXT_PUBLIC_SODEX_NETWORK picks SoDEX testnet (the default) or mainnet for the site, the users' trades and the worker together. Auto-trading stays off unless AUTO_TRADE_ENABLED=true, and every automated trade still has to pass the risk gates: cooldown, max open positions, daily loss limit, kill switch, and a guard that blocks mainnet outside production.
npm test # app tests (Vitest); database, LLM and SoDEX calls are mocked
npm run lintGitHub Actions (.github/workflows/ci.yml) runs lint, the app tests and a production build on every pull request to main.
cinder/
βββ README.md
βββ .env.example
βββ .github/workflows/ci.yml # Lint, tests, build
βββ docs/
β βββ ARCHITECTURE.md
β βββ API_INTEGRATION.md
β βββ WORKER.md # Running the scheduler on an always-on host
βββ migrations/
β βββ 0001_init.sql
β βββ 0002_add_user_address.sql
β βββ 0003_trade_replay_protection.sql
β βββ 0004_app_settings.sql # Shared trading_paused flag
βββ scripts/
β βββ worker.js # Scheduler for an always-on host (npm run worker)
β βββ db-init.js
β βββ register-sodex-api-key.js
β βββ set-telegram-webhook.js
β βββ seed-more-stories.js
β βββ test-*.js / test-*.mjs # Manual end-to-end checks
βββ src/
βββ app/
β βββ page.js, layout.js
β βββ feed/, story/[id]/, dashboard/, portfolio/
β βββ api/
β βββ stories/ # GET feed (+ throttled refresh), POST requires internal secret
β βββ stories/stream/ # Server-Sent Events
β βββ narrative/ # GET temperatures, POST requires internal secret
β βββ trade/ # Cinder's own account: GET positions/prices, POST internal trades only
β βββ telegram-auth/ # Wallet-signed Telegram linking
β βββ webhook/ # Telegram webhook (secret required)
β βββ market-update/
βββ components/
β βββ wire/ # StoryCard (escaped markdown), StoryFeed, charts
β βββ narrative/ # BubbleMap, Timeline, TemperatureGauge, ShiftAlert
β βββ trading/ # QuickTrade, PortfolioView, OpenOrders, TradeHistory, RiskDashboard
β βββ shared/
βββ context/WalletContext.js # Wallet, the user's SoDEX account, Enable trading
βββ engine/
β βββ narrative.js # Narrative temperatures
β βββ shift-detector.js # Regime shift detection
β βββ trade-engine.js # Risk gates, sizing, execution, stop-losses
βββ lib/
β βββ sosovalue.js, sodex.js, openai.js, telegram.js
β βββ sodex-network.js # Testnet or mainnet, builder settings
β βββ sodex-signing.js # EIP-712 payloads and signatures for SoDEX
β βββ sodex-browser.js # Browser client: account reads, trading key, orders
β βββ sodex-orders.js # Order sizing against market filters
β βββ secrets.js # Constant-time secret checks
β βββ validator.js # Fact-checks AI stories against the database
β βββ db.js, scheduler.js, rate-limiter.js, telegram-link.js
βββ styles/
Fixes applied during the post-hackathon review.
POST /api/stories, POST /api/narrative and POST /api/trade require an x-internal-api-secret header matching INTERNAL_API_SECRET, compared in constant time. POST /api/trade only trades Cinder's own account.
- No custody: users' funds stay in their own SoDEX accounts. Orders are signed in the browser and go straight to SoDEX; Cinder's server never sees a user's key or order.
- Limited keys: the browser's trading key can place and cancel orders only. Withdraw and transfer are disabled on SoDEX, and the key expires after 7 days.
- Exact fee approval: users approve exactly the builder fee Cinder asks for, so the approval can't be used to charge more.
- Server-side pricing: fills use the server's SoDEX price, never the price in the request. Live mode refuses to trade on fallback prices.
- No fake fills: if a live SoDEX order fails, the trade is recorded and shown as simulated, not filled.
Linking Telegram requires a wallet signature, link tokens expire after 15 minutes, and the webhook only accepts requests carrying TELEGRAM_WEBHOOK_SECRET.
The admin's Telegram /pause is stored in the database (app_settings.trading_paused), so it stops both autonomous trades and stop-loss sells in the worker process, not just in the server that received the message.
If the Edge Config lookup fails (network error, timeout, misconfigured client), the kill-switch fails closed (trades paused). Set KILL_SWITCH_FAIL_CLOSED=false to revert to failing open. Stop-loss monitoring also respects the kill switch.
The SoDEX order nonce is a monotonic counter (not Date.now()), preventing nonce reuse under concurrent requests that could cause duplicate fills.
When TURSO_DATABASE_URL is unset in a production environment, the app fails immediately at startup rather than silently connecting to an in-memory database.
Story card markdown output is escaped via escapeHtml() before rendering, preventing injection via crafted story text.
The daily-loss circuit breaker also trips when portfolioValue <= 0; the cooldown checks the most recent buy; the open-position limit counts only positions that are still open.
Every feed visit asks for a news refresh; the SoSoValue fetch and AI refinement run at most once every 5 minutes per server instance.
π https://cinderhq.vercel.app (deployed during buildathon)
π₯ Watch the 2-minute walkthrough β (link to be added)
- Open the Wire β See live stories publishing with ETF flow data, sector analysis, and AI commentary
- Check the Narrative Dashboard β Watch the bubble map showing "Institutional Accumulation" cooling and "AI Token Rotation" heating
- See a Shift Alert β When confidence crosses 80%, a breaking story auto-publishes with the trade plan
- View the Trade β Portfolio page shows the executed SoDEX trade, linked to the story that triggered it
- Read the Transparency β Every trade has an article. Every article has data. Full audit trail.
| Criterion | How Cinder Addresses It | Status |
|---|---|---|
| β Genuine SoSoValue API integration | Uses ETF flows, AI news feed, and sector/index data as the sole data source for all intelligence | Core |
| β Clear use case | Autonomous financial wire service + narrative-driven portfolio management | Core |
| β Complete data β output flow | SoSoValue data β AI story + narrative detection β trade execution on SoDEX | Core |
| β SoDEX API integration | Auto-executes trades, manages positions, sets stop-losses via SoDEX | Implemented |
| β AI-enhanced functionality | AI generates stories, classifies narratives, detects shifts, and sizes trades | Implemented |
| β Opportunity discovery | Narrative shift detection surfaces opportunities before price catches up | Implemented |
| β Risk control + security | Stop-losses, max allocation caps, cooldowns, multi-signal confirmation, human override | Implemented |
| β Insight-to-action flow | Published story β embedded trade recommendation β one-click SoDEX execution | Implemented |
| β Product experience | Professional news site + interactive dashboard + Telegram alerts | Implemented |
This project was built for the SoSoValue Γ SoDEX Buildathon (Wave 3, July 2026).
MIT License β see LICENSE for details.
Built with β‘ by turnless for the SoSoValue Γ SoDEX Buildathon
"What if Bloomberg could trade its own stories?"