How Mycelium is built, in technical detail
Developer docs, version 1.0, September 2026
The engineering companion to the whitepaper: ingestion, the deterministic strategy engine, the quality gate, sizing and trade management, non-custodial execution and routing, the shared journal, access control and the secured background jobs.
Mycelium is a single React application on TanStack Start, rendered on the server and hydrated in the browser, with a Postgres backend behind row level security. All app-internal backend logic is exposed as typed server functions; only webhooks and scheduled jobs are raw HTTP routes.
There is no trading backend in the classic sense. The server reads the chain, scores it, and stores metrics. Every transaction that moves value is built in the browser and signed by the member's wallet.
- Client: React with TanStack Router and TanStack Query. Server state is fetched through query options and reused across pages, so a refresh invalidates one cache and every surface updates.
- Server: server functions for reads and mutations, plus file routes under the api path for the background jobs.
- Database: Postgres with row level security. Chain and market tables are server-only: the anonymous and authenticated roles have no access, the service role reads and writes them from server code.
- Determinism: the strategy layer is pure TypeScript with unit tests. Given the same rows it always produces the same idea. The language model never invents a number.
A continuous reader walks Robinhood Chain (chain id 4663). Blocks are pulled in ranges, receipts are fetched in batch, and logs are decoded into typed events. Nothing is read from an external index or a third-party feed.
- Decoded events: ERC-20 transfers, Uniswap V3 swaps, pool creation and liquidity changes, contract creation, and NFT transfers for the membership check.
- Derived per token: last price, volume, swap count, unique buyers and sellers, holder count and holder delta, pool depth, buy versus sell pressure, and an hourly UTC activity profile.
- Contract facts: verified source, mint authority, transfer or sell blocking, deployer share, supply concentration and contract age. These become hard filters, not soft scores.
- Cursors and job state are persisted, so a restart resumes where it stopped instead of replaying the chain.
Each strategy is an independent scorer. It takes token metrics plus contract facts and returns either nothing or a complete, actionable trade idea: asset, direction, entry, stop, target, suggested size, conviction, the evidence behind it, the warnings against it and what would prove it wrong. Before an idea is shown, the token is checked against live pools and recent swaps, so every idea on the board has a route you can actually trade.
Strategies never read each other and never read what members did. They read chain rows only, which is what keeps the tool from chasing its own crowd.
- Momentum and breakout: level reclaim on real volume with a widening buyer set.
- Launch radar: contract creation, first liquidity, first buyers, with hard safety screening and tiny size.
- Value dips: measured solidity plus deep drawdown plus signs of stabilisation, with an honest recovery band rather than a date.
- Pool watch: opening commitment, depth trend, turnover and pull risk derived from pool state.
- Flush reversion: a healthy intraday flush with relative volume, stabilisation, buy pressure and a liquidity floor.
- Smart money: clustering of wallets with a measurable on-chain record.
- Chain strength: breadth, median move and tape regime, used both as a standalone read and as a filter on everything else.
One shared module decides what is good enough for the central Trading ideas board, so every surface applies the same bar. Weaker candidates are never deleted; they stay on their own page, labelled and explained, available to a member who accepts the risk.
- Round-trip cost model first: estimated gas, fees and slippage are subtracted before anything is judged. An idea whose costs exceed a third of its target is rejected.
- Expectancy and break-even win rate must clear the measured record of that playbook.
- Minimum reward to risk of 1.8, plus liquidity and depth floors.
- Conviction of at least 80 to reach the central board, with per-source caps so one strategy cannot flood it.
- Autopilot only ever sees ideas at or above the same bar.
Size is derived, never guessed: bankroll, a member-set risk percentage per trade defaulting to one percent, the stop distance, conviction and pool depth produce a suggested amount. It is a suggestion. The member sets the final amount, stop and target on every idea.
Once a position is open, management rules run in the browser and are mirrored in a backend watchtower. The watchtower can detect an exit level while the laptop is closed, but the sale waits until the app reopens because the signing key stays on that device.
Robinhood Chain pools have no native stop order, so an exit is always a swap that has to be signed. Three layers reduce that gap: a stop safety margin that fires slightly early, an arm switch that lets a position request the exit signature by itself while the app is open, and a proximity warning before price reaches the level.
- Break-even shift after a defined gain, trailing stop, partial profit taking with persisted peak and scale-out state, and a time stop for dead trades.
- Effective stop = stop adjusted by stopBufferPct, default 0.5 percent, applied on the correct side for long and short. alertNearPct, default 3 percent, drives the approach warning and is deduplicated per position.
- Armed positions may trigger the exit swap themselves; unarmed positions only warn and wait for a manual close. Rule values are validated again server side in the watchtower.
- Wallet protection: a rolling 24 hour spend budget and a rolling 24 hour realised loss limit, checked by one shared risk check for manual and autopilot. Manual can override a single block after an explicit warning, autopilot cannot; protective exits are never blocked.
- Global protections: per-trade cap, total exposure cap, loss-streak breaker and a cooldown against revenge trading.
- Settlement maths uses bigint basis-point arithmetic, so partial closes do not drift.
- Any position can be closed at any moment: sell back into USDG, keep the coin and close the record, or force-close the record if the on-chain sale fails.
Execution is direct and non-custodial. The app quotes against Uniswap V3 QuoterV2 and submits through SwapRouter02 on Robinhood Chain. No aggregator, no third-party sign-in, no relayer holding an order.
Routing compares every direct fee tier against two-hop routes through hub tokens derived from recent indexed swaps and stable or wrapped-native rows, quotes the full encoded path, and executes the best one. When a conversion is routed through a middle token the interface says so.
- Manual mode: the connected browser wallet signs each swap.
- Autopilot: a burner wallet created in the member's browser signs inside the limits the member set. The key never leaves the device and is never sent to the server.
- Slippage bounds and minimum received are enforced in the transaction itself.
- The server can never move funds. It has no key for any member wallet.
Every finished trade is written to one journal with its outcome, its playbook and, when available, its transaction hash. That journal calibrates trust in strategies. It never becomes a signal source for idea generation.
Members are identified by the Mnode NFT they hold, for example Mnode #412. Wallet addresses are mapped to token numbers server-side only and are never exposed to other members.
- Per-member influence is capped at ten recent trades per asset, so no wallet can bend what the network learns.
- Standing, playbook leaderboard, pulse, seasons, streaks and pods are all computed from journal rows, never from anything typed by a member.
- Trades carrying a verifiable transaction hash weigh more than unverified ones: full weight when checkable on chain, roughly a third when not.
- Evidence decays: a finished trade keeps half its learning weight after about 21 days, so recent behaviour outranks old behaviour.
- Every journal row stores the market regime it closed in, rising, mixed or falling, read from live chain data. Playbook trust for today blends the all-time record with the record in today's regime.
- Member-inspired ideas are repriced drafts, clearly labelled, and are never signed automatically.
Membership is an on-chain NFT balance check performed server-side against the configured collection, repeated on each visit. There is no email, no password and no bypass, and the collection address is configuration rather than a hard-coded constant.
- Row level security is on for every public table. Journal reads run through privileged server code; the anonymous role gets nothing.
- Market, chain, pool, timing and radar tables are service-role only.
- Personal positions, balances and settings live in the member's browser with optional encrypted cloud backup.
- Secrets are server-side only and read inside handlers, never at module scope and never in client code.
Ingestion, launch radar, pool watch, token intelligence, NFT indexing, the cron dispatcher and the watchtower run as HTTP endpoints called on a schedule. All of them require a bearer token, compared in constant time against a private table the service role alone can read. Without it they answer 401.
The in-app refresh button does not call those endpoints. It calls a server function that takes a short lease, so many taps produce one pass, and it invalidates the active queries when the pass completes.
- Watchtower runs every minute; the data refresh runs every two minutes.
- Job state and last error are persisted, so a stalled job is visible rather than silent.
- Everything is idempotent: a repeated run re-reads and overwrites rather than double-counting.
A new strategy is a pure function plus a test, and then three wires. Nothing about the board, the gate or the UI needs to change for it to appear.
- Write a scorer that takes stored metrics and returns a complete idea or nothing, with evidence and warnings filled in. No network calls inside it.
- Add unit tests covering the qualifying case, the rejecting case and the edge case that would be dangerous to get wrong.
- Register it in the idea aggregation, give it a source badge, and let the shared quality gate decide whether it reaches the central board.
- If it needs new chain data, extend the ingestion writer and the server-only table, never a client-side fetch of a third-party feed.
A short list of rules that hold everywhere in the codebase. Breaking one of them is a bug, not a style preference.
- On-chain only. No social, news, sentiment or hype input anywhere, including in assistant answers.
- No number reaches a member unless a deterministic function or a tool call produced it.
- No automatic signing. Every value-moving transaction is a deliberate member action.
- Every idea shown carries its conviction, its evidence, its warnings and the reminder that this is not advice.
- Server-only modules never enter the client bundle; the client talks to server functions.
- A coin with no provable liquidity route is never offered as a trade. The interface shows that state instead of a button that would fail at execution.
Privacy is enforced by the schema, not by policy text. The rules below are what an implementer has to preserve.
- Personal scope: a wallet address, member settings, member trade records, assistant messages and technical logs. Nothing else about a person is collected, and no identity fields exist in the schema.
- Row level security on every member table, scoped to the authenticated member. Chain and market tables are server-only, reachable by the service role from server code.
- Keys never leave the browser. The autopilot key is generated and stored client side; no endpoint accepts or returns one, and no log may ever print one.
- Publication to the shared network uses the Mnode number as the identifier. A wallet address must not be written into any member-visible record.
- Deletion requests remove member rows; finished trades that already calibrated a strategy are anonymised so aggregate statistics stay intact.
- Logs must never contain addresses joined to personal settings, secrets, or assistant content beyond what is needed to debug a failure.
The non-technical version of all of this is in the whitepaper, and the trading lessons are on the Soil.
