1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//! Pure-Rust arbitrage pathfinding graph + depth-first search.
//!
//! This crate is a **zero-dependency leaf** — it has no `pyo3`, no `tokio`,
//! no `alloy`, no `degenbot-core`. The graph operates on plain `u64` token IDs
//! and pool IDs, making it independently testable without a Python
//! interpreter and reusable in non-Python Rust code. A standalone Rust
//! consumer can build a path graph and discover arbitrage cycles without
//! pulling the engine, the pump, or the RPC stack.
//!
//! # Design
//!
//! The graph is a multigraph: nodes are token IDs and edges are liquidity
//! pools, identified by `(pool_id, pool_kind)`. Parallel edges (multiple
//! pools connecting the same token pair) are naturally supported.
//! [`PathGraph`] remaps external `u64` token and pool IDs to compact `u32`
//! indices and stores the adjacency as flat CSR arrays
//! (`adj_offsets` / `adj_flat`), preserving edge insertion order for
//! deterministic DFS traversal. Parallel pools between the same unordered
//! token pair collapse into one bundle with a per-bundle use counter, and
//! yielded walks expand to concrete pool IDs lazily at yield time.
//!
//! The [`PathGraph::find_paths`] method performs an iterative depth-first
//! search for all valid cycles from a start token back to an end token,
//! honoring minimum/maximum depth bounds, per-depth pool-type filters, and
//! lookahead pruning via precomputed node valid-depth sets.
//!
//! # Relationship to the Python module
//!
//! The Python `degenbot.pathfinding` module handles database orchestration
//! (`SQLAlchemy` pool/token queries, address resolution) and calls into this
//! crate via the `PyO3` binding layer. Address resolution stays in Python
//! (where `SQLAlchemy` lives); the graph algorithm lives here.
pub use ;
pub use ;
pub use ;