Skip to content

feat(nexus): run the Tycho market in fynd-nexus - #728

Open
carloszanella wants to merge 13 commits into
mainfrom
cz/feat/nexus-market
Open

carloszanella wants to merge 13 commits into
mainfrom
cz/feat/nexus-market

Conversation

@carloszanella

Copy link
Copy Markdown
Collaborator

Business logic

Feature

fynd-nexus can now run the Tycho client for its chain and keep fynd's market data and derived data (spot prices, pool depths, and token prices) up to date without worker pools. Nothing reads the market yet; it provides the foundation for serving derived data and for the component health monitor (#694).

Business decisions

  • The market runs when --tycho-url is set. It then requires --rpc-url, which FyndBuilder uses to read gas prices. It is configured through --tycho-api-key, --tycho-use-tls (default: true), and --min-tvl (default: the chain's low TVL threshold).
  • It tracks every on-chain protocol system that Tycho serves for the chain above the TVL floor, excluding those on the default blocklist.
  • The protocol list is fetched from Tycho before the HTTP server binds, so an incorrect Tycho URL causes startup to fail.
  • The market has 15 minutes to receive its first block and compute its derived data. After that, if the Tycho feed ends, the service stops with an error so the orchestrator restarts it.
  • Passing --venues with no value runs no venue, allowing a deployment to run the market alone. The service refuses to start if it has neither a venue nor the market.

Design

  • fynd-core: FyndBuilder::build_market starts the Tycho feed, market data, and derived data without worker pools and returns a MarketFeed. Market setup was separated from solver assembly so both paths share it.
  • fynd-nexus: the new market module contains MarketArgs and launch_market. launch_market returns a LaunchedMarket that holds a shared Arc<MarketFeed> and the task that watches the feed. fynd-nexus now depends on fynd-rpc for the protocol list.

For the reviewer

  • Most of the logic is in fynd-core/src/solver.rs (build_market and the shared market setup) and fynd-nexus/src/market/market_launch.rs.
  • The MarketFeed tasks are never shut down; the process exits when the feed ends.
  • No test starts a real market against Tycho.
    🤖 Generated with Claude Code

carloszanella and others added 13 commits November 9, 2026 09:26
WHY:
A service that only needs the market (Tycho feed, gas price, derived
data) has to start the same components the solver starts, with the same
settings. They were built inline in the solver assembly, next to the
worker pools, so a market-only start would have copied them.

HOW:
- Move the construction of the Tycho feed, gas price fetcher and
  computation manager into FyndBuilder::assemble_market, which returns a
  MarketParts value.
- assemble_components calls it and keeps the worker pool, encoder and
  router setup.

ADDITIONAL NOTES:
Pure refactor; the order of construction and the settings are unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
WHY:
A service that probes components on chain needs the live Tycho market
and its derived data (prices, depths) but no worker pools, encoder or
router. FyndBuilder could only start the whole solver.

HOW:
- FyndBuilder::build_market starts the Tycho feed, gas price fetcher,
  metrics sampler and computation manager with the builder's Tycho
  settings, and returns a MarketFeed.
- MarketFeed gives out the market data, the derived data and a market
  event receiver, and has wait_until_ready, feed_has_ended and shutdown.
- The task spawning and the readiness wait are shared with the solver
  build instead of copied.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Scenarios covered:
- the market starts with no worker pool and is not ready before a block
- an invalid RPC URL fails the market build

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
WHY:
The module guide of fynd-core did not mention the market-only build, so a
reader looking for how a service can run the market without a solver would
not find it.

HOW:
- Add build_market and MarketFeed to the solver row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WHY:
Nexus will run the Tycho client and keep the market up to date, so operators
need to point it at a Tycho server and a node.

HOW:
- add MarketArgs with --tycho-url, --tycho-api-key, --tycho-use-tls,
  --min-tvl and --rpc-url, each with an environment variable
- the market is on when --tycho-url is set, and --tycho-url requires
  --rpc-url, which the market reads gas prices from
- Debug shows whether a key or an RPC URL is set, not its value

ADDITIONAL NOTES:
The arguments are not read by the binary yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- the defaults leave the market off and TLS on
- --tycho-url turns the market on, --rpc-url alone does not
- --tycho-url without --rpc-url is rejected and names --rpc-url
- TLS can be turned off
- Debug hides the API key and the RPC URL

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WHY:
Nexus has to run the Tycho client and keep the market and its derived data
up to date, so that what it serves next can be built from them. Nothing
started the market yet.

HOW:
- add launch_market, which resolves every on-chain protocol system from
  Tycho, applies the TVL floor and the default blocklist, and starts
  fynd-core's market-only build
- it returns the market feed, shared, with a task that waits for the first
  block and the derived data (up to 15 minutes) and then ends with an error
  once the Tycho feed has ended
- add wait_until_market_ready so a reader of the market can wait the same way
- depend on fynd-rpc for the protocol system lookup

ADDITIONAL NOTES:
The service does not start the market yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WHY:
The service is about to run the market without any venue, but --venues could
not be emptied: an empty value was read as an unknown venue, so a
market-only deployment could not start.

HOW:
- --venues accepts zero values; the flag alone lists no venue

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WHY:
With --venues empty and the market on, the service stopped at startup with
"none of the listed venues supports the chain", although no venue was
listed. A market-only deployment could not start.

HOW:
- streams_to_serve returns no streams for an empty list of venues, and still
  fails when venues are listed and none supports the chain

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- an empty list of venues gives no streams and no error

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WHY:
The market could be started but nothing started it, so nexus still held no
Tycho state. Nexus should run the market whenever it is given a Tycho URL,
with or without venues.

HOW:
- add the market settings to the command line
- the service starts the market when --tycho-url is set
- the service stops, with the reason, when the market's task ends: the Tycho
  feed ended or the market did not become ready
- startup fails with "nothing to run" when no venue is listed and the market
  is off

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- --venues with no value and the market flags parse, and the market is off
  by default
- startup fails with "nothing to run" when there are no venues and no market

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WHY:
Operators need to know how to turn the market on and what it needs and
does.

HOW:
- README: the market flags, the --rpc-url requirement, --venues with no
  value, the readiness wait and the stop when the Tycho feed ends
- note the market in the codebase map

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown

Breaking API Changes Detected

This PR introduces breaking API changes, but the PR title does not declare them.
Either fix the breaking changes, or declare them:

  • Append ! to the PR title type (e.g. feat!: ...) and make sure a !-marked commit
    lands on main — release-plz bumps the minor version for breaking changes on 0.x.x.
semver-checks output
Checking fynd-bench-harness v0.122.0 -> v0.122.0 (no change; assume minor)
     Checked [   0.043s] 196 checks: 196 pass, 58 skip
     Summary no semver update required
    Finished [   0.093s] fynd-bench-harness
    Checking fynd-core v0.122.0 -> v0.122.0 (no change; assume minor)
     Checked [   0.909s] 196 checks: 196 pass, 58 skip
     Summary no semver update required
    Finished [   1.551s] fynd-core
    Checking fynd-test-fixtures v0.122.0 -> v0.122.0 (no change; assume minor)
     Checked [   0.063s] 196 checks: 196 pass, 58 skip
     Summary no semver update required
    Finished [   0.089s] fynd-test-fixtures
    Checking fynd-rpc v0.122.0 -> v0.122.0 (no change; assume minor)
     Checked [   0.078s] 196 checks: 196 pass, 58 skip
     Summary no semver update required
    Finished [   0.125s] fynd-rpc
    Checking fynd-rpc-types v0.122.0 -> v0.122.0 (no change; assume minor)
     Checked [   0.104s] 196 checks: 196 pass, 58 skip
     Summary no semver update required
    Finished [   0.155s] fynd-rpc-types
    Checking fynd-nexus v0.122.0 -> v0.122.0 (no change; assume minor)
     Checked [   0.058s] 196 checks: 195 pass, 1 fail, 0 warn, 58 skip

--- failure constructible_struct_adds_field: struct exhaustively constructible through public API adds field ---

Description:
A pub struct that could be exhaustively constructed with a literal using only public API has a new pub field, breaking existing exhaustive literals.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.50.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field Cli.market in fynd-nexus/src/cli.rs:42

     Summary semver requires new major version: 1 major and 0 minor checks failed
    Finished [   0.091s] fynd-nexus
    Checking fynd-client v0.122.0 -> v0.122.0 (no change; assume minor)
     Checked [   0.122s] 196 checks: 196 pass, 58 skip
     Summary no semver update required
    Finished [   0.198s] fynd-client
    Checking fynd-tools-common v0.122.0 -> v0.122.0 (no change; assume minor)
     Checked [   0.053s] 196 checks: 196 pass, 58 skip
     Summary no semver update required
    Finished [   0.078s] fynd-tools-common

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