Concepts
Meta-aggregation
How one LayerHop quote fans out to every eligible provider in parallel, and what you get back.
One request, many providers#
LayerHop does not own liquidity. Each provider — Jupiter, Relay, deBridge, 0x, LI.FI — is a full routing engine with its own liquidity, bridges or solver network. LayerHop sits one level above them: it is an aggregator of aggregators.
When you call GET /v1/quote, the API:
- Resolves the chains (id or slug) and tokens (symbol from the token list, or a raw address / mint).
- Filters providers with
supports(request). For example, Jupiter only handles Solana → Solana; 0x only handles same-chain EVM swaps. See Providers for the full matrix. - Asks every eligible provider in parallel, each with its own timeout (8 s by default).
- Keeps the successes and ranks them best-for-the-user first (see Providers & ranking).
- Stores each quote under its own
quoteIdand returns them.
{
"best": { "quoteId": "q_…", "provider": "relay", "dstAmount": "612345678", "...": "..." },
"quotes": [ { "provider": "relay", "...": "..." }, { "provider": "debridge", "...": "..." } ],
"errors": [ { "provider": "lifi", "code": "PROVIDER_TIMEOUT", "message": "Timed out: li.quest" } ]
}Partial failure is normal#
A provider that errors or times out does not fail your request; it shows up in errors with a stable error code. Only when no provider returns a quote does the API answer 404 NO_ROUTE.
This means you can show the user a price even while a provider is degraded, and you can show why a provider is missing (for example UNSUPPORTED_TOKEN from one provider while another still routes the token).
Every quote is executable#
quotes is not just a price comparison. Every entry has its own quoteId, so you can let the user pick a slower-but-cheaper or faster route and build that one with POST /v1/orders.
The RouteProvider interface#
Internally, every provider implements the same interface (packages/shared/src/types.ts):
| Method | Purpose |
|---|---|
supports(req) |
Can this provider serve the chain/token pair at all? |
quote(req, ctx) |
Price the trade with LayerHop's fee for the channel. |
buildTx(quote, ctx) |
Return the transaction to sign (or the one already returned with the quote). |
status(id, ctx) |
Report pending / filled / refunded / failed / unknown. |
submit?(quote, signedTx, ctx) |
Only for submitViaApi transactions. |
New liquidity sources — including LayerHop's own solver later — plug in as just another provider. Nothing changes for API clients.
Quote storage#
Quotes are held in memory by the API instance that produced them, and dropped five minutes after they expire. A quoteId is therefore only valid on the same API instance and only for a short time: build the order promptly and treat QUOTE_NOT_FOUND and QUOTE_EXPIRED as "get a fresh quote".
Coming soon
a shared quote store (Redis) so a hosted, multi-instance API can build any quote it issued.