Routing
Routing
The directed multigraph model and how a committed route runs to completion.
The routing graph is a directed multigraph. Its nodes are GraphNode values — a (chainId, token) pair — and its edges are GraphEdge values, each annotated with a bridge id and the current LiquidityInfo for that lane. Two nodes are connected by an edge when a bridge can move value between them; because multiple bridges may serve the same pair, the structure is a multigraph rather than a simple graph.
This model is defined in @arc-route/types as pure data, with no behavior attached. @arc-route/graph wraps it in the RoutingGraph class that owns the adjacency structure, deduplicates identical bridge edges between the same node pair, and exposes the queries the engine needs: outgoing edges from a node, the most-liquid edge directly connecting two nodes, and current liquidity reported by a given bridge at a given (chain, token).
A committed Route is not a single operation; it is an ordered sequence of hops, each a GraphEdge the engine has resolved into a RouteHop with concrete cost, latency, and reliability estimates. The Executor in @arc-route/execution walks this sequence in order, submitting each hop to its BridgeAdapter and propagating the moved amount forward as the input to the next hop.
Materializing the route as an ordered, dependent sequence makes execution explicit and observable. Every hop has a defined place in the order, a defined input, and a defined output. There are no implicit steps and no opportunistic reordering — the pipeline that runs after commitment is the same one that was scored before it.
Execution is atomic in spirit: if a hop fails after earlier hops have already settled, the Executor attempts a compensating refund of the already-moved funds and reports a terminal failed or refunded status. The true atomicity guarantee is ultimately a property of the adapters and the bridges they wrap; the execution layer enforces the protocol-level discipline and reports progress through an ExecutionListener callback.
Because execution is a sequence of hops rather than an opaque process, the state of a transfer is always expressible as the set of hops completed, in progress, and pending. That structure is what status surfaces report against, and what validators confirm as the transfer advances toward finality.