Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .claude/CODEBASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Key properties:
| Crate | Location | Description |
|---|---|---|
| `fynd` | root (`src/`) | CLI binary and library crate: parses args, sets up observability, runs `FyndRPCBuilder`. `lib.rs` re-exports `fynd_core` and `fynd_rpc` as a single dependency |
| [`fynd-core`](../fynd-core/CLAUDE.md) | `fynd-core/` | Pure solving logic: algorithms, worker pools, graph, feed, derived data, encoding. No HTTP deps |
| [`fynd-core`](../fynd-core/CLAUDE.md) | `fynd-core/` | Pure solving logic: algorithms, worker pools, graph, feed, derived data, encoding, layered config. No HTTP deps |
| [`fynd-rpc`](../fynd-rpc/CLAUDE.md) | `fynd-rpc/` | HTTP RPC server builder (Actix Web): API handlers, middleware, `FyndRPCBuilder` |
| [`fynd-rpc-types`](../fynd-rpc-types/CLAUDE.md) | `fynd-rpc-types/` | Shared DTO types for the RPC API (request/response wire format) |
| `fynd-test-fixtures` | `test-fixtures/` | Shared types for recorded-market test fixtures: `MarketRecording`, expected outputs, test scenarios. Not published |
Expand Down Expand Up @@ -102,7 +102,8 @@ See `docs/ARCHITECTURE.md` for the full architecture diagram and detailed compon
| `TYCHO_URL` | Tycho endpoint (chain-specific default) |
| `HTTP_HOST` | HTTP bind address (default: `0.0.0.0`) |
| `HTTP_PORT` | API port (default: `3000`) |
| `WORKER_POOLS_CONFIG` | Worker pools config file (default: `worker_pools.toml`) |
| `CONFIG_FILE` | Solver config file (default: `fynd.toml` if present) |
| `WORKER_POOLS_CONFIG` | Deprecated legacy pools-only config file; its pools override the config file's |
| `BLOCKLIST_CONFIG` | Blocklist config file |
| `RUST_LOG` | Tracing filter (e.g. `info,fynd=debug`) |
| `METRICS_PORT` | Prometheus metrics server port (default: `9898`, requires `metrics` feature) |
Expand All @@ -111,15 +112,16 @@ See `docs/ARCHITECTURE.md` for the full architecture diagram and detailed compon

| Command | Purpose |
|---|---|
| `serve` | Run the solver: Tycho feed + HTTP RPC server. Notable flags: `--enable-price-guard` (default `false`), `--partial-blocks` (enable flashblock/partial-block updates from Tycho stream) |
| `serve` | Run the solver: Tycho feed + HTTP RPC server. Notable flags: `--config-file` (default `fynd.toml`), `--enable-price-guard` (default `false`), `--partial-blocks` (enable flashblock/partial-block updates from Tycho stream) |
| `openapi` | Print the OpenAPI spec JSON to stdout |
| `derive-connector-tokens` | Derive and print connector token lists for configured protocols |

### Config Files

| File | Purpose |
|---|---|
| `worker_pools.toml` | Worker pool definitions: algorithm, num_workers, hop limits, timeout. Optional — binary falls back to embedded defaults if not found |
| `fynd.toml` | Full solver config: any subset of tuning fields + `[pools]`. Resolved field-by-field: CLI > file > embedded default (`fynd-core/src/config/default_config.toml`) |
| `worker_pools.toml` | Deprecated legacy pools-only file, still honored (its pools override the config file's) |
| `blocklist.toml` | Component IDs to exclude from the Tycho stream. Optional — falls back to tycho-simulation defaults if not found |

## Testing
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ services:
- "3000:3000"
- "9898:9898"
volumes:
- ./worker_pools.toml:/etc/fynd/worker_pools.toml:ro
- ./fynd.toml:/etc/fynd/fynd.toml:ro
- ./blocklist.toml:/etc/fynd/blocklist.toml:ro
environment:
- RPC_URL=${RPC_URL}
- TYCHO_API_KEY=${TYCHO_API_KEY:-}
- TYCHO_URL=${TYCHO_URL:-tycho-fynd-ethereum.propellerheads.xyz}
- WORKER_POOLS_CONFIG=/etc/fynd/worker_pools.toml
- CONFIG_FILE=/etc/fynd/fynd.toml
- BLOCKLIST_CONFIG=/etc/fynd/blocklist.toml
- RUST_LOG=fynd=info
- OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317
Expand Down
2 changes: 1 addition & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Manages dedicated OS threads for CPU-bound route finding. Each pool has:
* A bounded `TaskQueue` (via `async_channel`)
* N `SolverWorker` instances on separate threads

Pools can use either a built-in algorithm by name (e.g., `"most_liquid"`) or a custom `Algorithm` implementation via `WorkerPoolBuilder::with_algorithm`. Pools are configured via `worker_pools.toml` for built-in algorithms, or programmatically via the builder for custom algorithms. Multiple pools can use the same algorithm with different parameters (e.g., fast 2-hop vs deep 3-hop).
Pools can use either a built-in algorithm by name (e.g., `"most_liquid"`) or a custom `Algorithm` implementation via `WorkerPoolBuilder::with_algorithm`. Pools are configured via the `[pools]` section of the config file (`fynd.toml`) for built-in algorithms, or programmatically via the builder for custom algorithms. Multiple pools can use the same algorithm with different parameters (e.g., fast 2-hop vs deep 3-hop).

***

Expand Down
2 changes: 1 addition & 1 deletion docs/algorithms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ See [Architecture](../ARCHITECTURE.md) for the full system design and [Custom Al
| **Approach** | Enumerate paths, score by heuristic, simulate top-N | Simulate every reachable edge, keep best amounts | Bellman-Ford based multi-path discovery + Frank-Wolfe split optimisation |
| **Strengths** | Fast; good at common, high-liquidity pairs | Finds non-obvious routes; no heuristic blind spots | Reduces price impact by splitting flow across parallel paths |
| **Weaknesses** | Path count explodes at high hop counts; heuristic can misjudge | Single path only; suboptimal for large trades | More simulation work per request; overkill for small trades |
| **Default config** | _(not in default `worker_pools.toml`)_ | 2 hops, 3 workers (see `worker_pools.toml`) | _(not in default `worker_pools.toml`)_ |
| **Default config** | _(not in default `fynd.toml`)_ | 2 hops, 3 workers (see `fynd.toml`) | _(not in default `fynd.toml`)_ |
| **Derived data needs** | Spot prices + pool depths (scoring), token gas prices (gas ranking) | Token gas prices (optional, for gas-aware mode) | Token gas prices + spot prices (price impact, probe amount, gas cost) |
2 changes: 1 addition & 1 deletion docs/algorithms/bellman-ford.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,4 @@ The Bellman-Ford routing approach in Fynd was inspired by the work of [János Ta
| `fynd-core/src/algorithm/mod.rs` | `Algorithm` trait definition |
| `fynd-core/src/graph/petgraph.rs` | Graph implementation (petgraph::StableDiGraph) |
| `fynd-core/src/worker_pool/registry.rs` | Maps `"bellman_ford"` to `BellmanFordAlgorithm` |
| `worker_pools.toml` | Worker pool configuration |
| `fynd.toml` | Worker pool configuration |
2 changes: 1 addition & 1 deletion docs/algorithms/most-liquid.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,4 @@ The path with the highest `net_output` wins.
| `fynd-core/src/algorithm/mod.rs` | `Algorithm` trait definition |
| `fynd-core/src/graph/petgraph.rs` | Graph implementation (petgraph::StableDiGraph) |
| `fynd-core/src/worker_pool/registry.rs` | Maps `"most_liquid"` to `MostLiquidAlgorithm` |
| `worker_pools.toml` | Worker pool configuration |
| `fynd.toml` | Worker pool configuration |
4 changes: 2 additions & 2 deletions docs/algorithms/path-frank-wolfe.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ max_hops = 3
timeout_ms = 500
```

The PFW-specific tuning parameters are not currently exposed in `worker_pools.toml`; they use defaults:
The PFW-specific tuning parameters are not currently exposed in `fynd.toml`; they use defaults:

| Parameter | Default | Description |
| --- | --- | --- |
Expand Down Expand Up @@ -149,4 +149,4 @@ The Frank-Wolfe loop checks elapsed time at the start of each iteration. If the
| `fynd-core/src/algorithm/bellman_ford.rs` | Inner BF solver used for path discovery |
| `fynd-core/src/algorithm/mod.rs` | `Algorithm` trait definition |
| `fynd-core/src/worker_pool/registry.rs` | Maps `"path_frank_wolfe"` to `PathFrankWolfeAlgorithm` |
| `worker_pools.toml` | Worker pool configuration (add a `path_frank_wolfe` pool to enable) |
| `fynd.toml` | Worker pool configuration (add a `path_frank_wolfe` pool to enable) |
14 changes: 10 additions & 4 deletions docs/guides/server-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ Run `fynd serve --help` for the full list.
| `--traded-n-days-ago` | — | `3` | Only include tokens traded within this many days. |
| `--worker-router-timeout-ms` | — | `100` | Default solve timeout (ms) |
| `--worker-router-min-responses` | — | `0` | Early return threshold (0 = wait for all pools) |
| `-w, --worker-pools-config` | `WORKER_POOLS_CONFIG` | `worker_pools.toml` | Worker pools config file path |
| `--config-file` | `CONFIG_FILE` | `fynd.toml` (if present) | TOML config file overriding the embedded defaults (see [Config file](#config-file-fyndtoml)). |
| `-w, --worker-pools-config` | `WORKER_POOLS_CONFIG` | `worker_pools.toml` (if present) | **Deprecated** — legacy pools-only config file; move the `[pools]` section into `fynd.toml`. Still honored: its pools override the config file's. |
| `--blocklist-config` | `BLOCKLIST_CONFIG` | [tycho-simulation default](https://github.com/propeller-heads/tycho-simulation/blob/main/blocklist.toml) | Path to blocklist TOML config file. Components listed here are excluded from the Tycho stream. |
| `--disable-tls` | — | `false` | Disable TLS for Tycho connection |
| `--min-token-quality` | — | `100` | Minimum [token quality](https://docs.propellerheads.xyz/tycho/overview/concepts#token) filter |
Expand All @@ -101,12 +102,17 @@ Run `fynd serve --help` for the full list.
| `--price-guard-fail-on-token-price-not-found`| — | `false` | Reject quotes when no provider lists the token. |
| `--metrics-port` | `METRICS_PORT` | `9898` | Port for the Prometheus metrics HTTP server. Requires the `metrics` feature (enabled by default). |

## Worker pools (`worker_pools.toml`)
## Config file (`fynd.toml`)

Every solver-tuning flag above resolves field-by-field through three layers, highest priority
first: **CLI flags > config file > embedded defaults**. The config file may set any subset of
the fields (same names as the flags) plus the worker pools; `./fynd.toml` is picked up
automatically, or pass `--config-file`.

Worker pools control solver thread count and routing strategies. The default config ships with one pool:

```toml
# worker_pools.toml
# fynd.toml
[pools.bellman_ford_2_hops]
algorithm = "bellman_ford"
num_workers = 3
Expand Down Expand Up @@ -164,7 +170,7 @@ The command scores every token by pool count and outputs a ready-to-paste TOML s
To use a custom config file:

```bash
fynd serve -w my_worker_pools.toml
fynd serve --config-file my_fynd.toml
```

## Blocklist config
Expand Down
5 changes: 5 additions & 0 deletions fynd-core/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ applications.
|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `algorithm/` | `Algorithm` trait + built-in `MostLiquidAlgorithm`, `BellmanFordAlgorithm`, `PathFrankWolfeAlgorithm`. Pluggable via associated graph types. `AlgorithmConfig` shared by all |
| `solver.rs` | `FyndBuilder` assembles the full pipeline (feed + gas + computations + pools + encoder + router). `Solver` runs it |
| `config/` | Layered solver config: `embedded_default()` parses `default_config.toml` (single source of truth for all tuning defaults) into a complete `Config`; `PartialConfig` layers overlay via `Config::apply` (CLI/file > embedded); `Config::validate` range-checks the result |
| `worker_pool/` | `WorkerPool` manages dedicated OS threads. `SolverWorker` runs a prioritized select loop (shutdown > market events > derived events > tasks). `TaskQueue` is `async_channel`-based |
| `worker_pool_router/` | `WorkerPoolRouter` fans out orders to all pools, ranks candidates by `amount_out_net_gas` descending; price guard (if enabled) validates in rank order; optionally encodes |
| `feed/` | `TychoFeed` (WebSocket → MarketState), `GasPriceFetcher`, `MarketEvent` broadcasting, `ProtocolRegistry` |
Expand Down Expand Up @@ -55,6 +56,10 @@ pub trait EdgeWeightUpdaterWithDerived {
**`FyndBuilder`** (`solver.rs`): Assembles feed + gas + computations + pools + encoder + router.
Returns a `Solver` that can `quote()` directly. For standalone (non-HTTP) use.

Defaults come from the embedded default config (`config/default_config.toml`); apply a resolved
`config::Config` in one call with `apply_config(&config)` (validates internally). Exception: the
worker router timeout defaults to a generous 10s standalone value.

Price guard methods: `price_guard_enabled(bool)`, `register_price_provider(Box<dyn PriceProvider>)`,
`add_default_price_providers()` (registers Binance WS + Hyperliquid providers).

Expand Down
2 changes: 1 addition & 1 deletion fynd-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ typetag.workspace = true
tycho-execution.workspace = true
reqwest.workspace = true
tokio-tungstenite.workspace = true
toml.workspace = true
alloy = { workspace = true, features = ["sol-types"] }

[features]
Expand All @@ -48,6 +49,5 @@ experimental = []
[dev-dependencies]
rstest.workspace = true
tempfile.workspace = true
toml.workspace = true
fynd-test-fixtures.workspace = true
tracing-subscriber.workspace = true
27 changes: 27 additions & 0 deletions fynd-core/src/config/default_config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Embedded default solver configuration, compiled into the binary.
#
# This file is the single source of truth for all solver-tuning defaults:
# `FyndBuilder::new` seeds its initial values from it, and the fynd binary uses it as the
# base layer of config resolution (CLI flags > local config file > this file).
#
# `min_tvl` is intentionally absent: it falls back to a chain-specific default TVL
# threshold when no layer sets it. Every other field must be defined here — unit tests
# (`config::tests::test_embedded_default_is_complete_and_valid`) enforce completeness.

tvl_buffer_ratio = 1.1
min_token_quality = 100
traded_n_days_ago = 3
gas_refresh_interval_secs = 30
reconnect_delay_secs = 5
worker_router_timeout_ms = 100
worker_router_min_responses = 0
partial_blocks = false
protocols = ["all_onchain"]

[pools.bellman_ford_2_hops]
algorithm = "bellman_ford"
num_workers = 3
task_queue_capacity = 1000
min_hops = 1
max_hops = 2
timeout_ms = 500
Loading
Loading