Systems6 min read
One quote, every bridge
How BRDG asks every bridge that can serve a route, ranks quotes by what you actually receive, and the bugs that shaped its sanity checks and transfer tracking.
From Print.World · Aug 2025 – Present
At Print.World I've been building BRDG. The pitch is short: one request asks every bridge that can serve your route, ranks the answers by what you'll actually receive, and you sign the winner in your own wallet. It covers around 35 bridges across 73 chains.
Getting a quote from one bridge is easy. Getting honest, comparable quotes from 35 of them, and then tracking the transfer afterwards, is where the engineering lives.
Ranking by what you receive
The first decision was what to rank by. Dollars seem natural, but converting to dollars means depending on a price feed. If that feed goes down, every quote becomes unrankable at once, which is a bad failure mode for something whose whole job is ranking.
So quotes are ranked in the route's own token. For a fixed input, the best quote is the highest net output. For a fixed output ("I need exactly this much on the other side"), it's the lowest net input. No external price needed.
"Net" is doing a lot of work there. Bridges disagree about whether fees are already subtracted from the amount they report. So each quote marks which fees it has already accounted for, and the ranking subtracts only what's left. Without that, you double-count fees for some bridges and miss them for others, and the ranking quietly favours whoever reports most optimistically.
Quotes that expire too soon to realistically sign and send are dropped. A great price you can't use isn't a great price.
Guarding the ranking
Aggregating 35 integrations means trusting 35 different interpretations of "amount". Token decimals vary from 6 to 18 and beyond, so a unit mix-up isn't off by a little: it's off by a factor of 10^2 to 10^12, and a ranking that sorts by "best output" will put the most wrong quote at the top.
So I designed the ranking to distrust outliers from the start, with two independent guards:
- Relative to the crowd. Any quote more than 10x away from the median of the other quotes for the same route is excluded. On realistic transfer sizes, real price differences between bridges are measured in basis points, not multiples, so the threshold costs nothing for honest quotes. Tiny transfers are the exception, where a fixed gas fee can be a large share of the amount.
- Relative to itself. A median needs other quotes, and some routes only have one bridge. So there's a second rule that needs no comparison: if a quote's output looks like its input echoed back in different units, it's excluded.
A shared quote board
Many users look at the same popular routes. Polling every bridge separately for each viewer would be wasteful and would hit rate limits fast. Instead, each route and amount is refreshed once per interval and pushed to everyone watching. A hundred viewers cost the same as one.
Ranking without flicker
Live quotes wobble. If the top two bridges are within a hair of each other, the table would swap them on every refresh, which looks broken. So a bridge only overtakes the row above it if it beats it by a margin.
That rule has a subtle problem. "Beats by a margin" isn't a consistent ordering: A can be roughly equal to B, and B roughly equal to C, while A clearly beats C. Passing a comparator like that to Array.sort leaves the resulting order implementation-defined by the spec, and in practice the order can change between refreshes.
So I don't sort with it. Starting from the previous order, I look for adjacent pairs that are out of order by more than the margin and swap them one at a time until none are left. It's stable, predictable, and it only moves rows that genuinely should move.
A cache key that includes who you are
Quotes are cached. The obvious key is route and amount. But a bridge's quote often includes ready-to-sign calldata, and that calldata bakes in the sender and recipient addresses. With a key that ignored them, one user could be served calldata that sends their funds to another user's recipient.
So the cache key includes sender and recipient. It costs some hit rate. That's fine.
Tracking the transfer
Once you've signed, a bridge transfer can take seconds or much longer, and statuses come from many different APIs. Ours normalises them into ten statuses, split into terminal ones and ones we keep polling.
A few rules I designed in deliberately:
- a transfer that repeatedly comes back "not found" becomes
UNKNOWN, neverFAILED; we don't tell someone their money is gone because an API was slow to index - a transfer filled with the wrong token, or less than expected, becomes
PARTIAL, not success - we record the broadcast before sending it, and a sweep flags any record still missing a transaction hash, so nothing falls through the gap between "we sent it" and "we saw it"
Keeping the engine testable
The routing engine has no infrastructure dependencies. It talks to the outside world through five small injected interfaces, and lint rules enforce that it can't import anything else. That's what lets around 300 routing tests run with no Redis, no network, and no bridges.
Redis failure policy is decided per use, not globally. The routing state cache fails closed, because routing on stale state is worse than not routing. Rate limits fail open, because a limiter outage shouldn't stop users. And locks are released only by their holder, so a slow worker can't free a lock someone else now owns.
Docs that can't drift
The public docs at docs.brdg.now are generated from the live OpenAPI spec, so they can't fall out of date with the API. There's also a TypeScript SDK on GitHub.
What I took from it
Most of the interesting decisions here were about what to do when something is wrong or unknown: a price feed that's down, a bridge reporting nonsense, a status API that hasn't caught up. I keep relearning the lesson from the perps aggregator: pick the honest status, not the optimistic one.
Next on my list is making those failure policies visible on the board itself, so a user can see not just which bridge won, but which ones were excluded and why.