MAS
MAS is the meta-aggregator service. It fans out a quote request to configured sources, normalizes their executable routes, and returns a best route with source telemetry.
MAS is not a signer, wallet, or broadcaster. It does not sign or broadcast transactions. A response contains quote data and, when requested, executable calldata; the caller decides whether and how to submit it.
MAS and smart-router are different
Section titled “MAS and smart-router are different”| Need | Service | Host |
|---|---|---|
| Quote comparison | MAS | https://meta-api.agentswap.co |
| Token catalog | smart-router | https://api.agentswap.co |
| One MAS quote source | smart-router | called by MAS behind the MAS endpoint |
Call MAS for quote comparison. Call smart-router directly for its catalog. A smart-router route is one source route; MAS is the service that compares it with other sources.
Base URL
Section titled “Base URL”https://meta-api.agentswap.coPublic HTTP contract
Section titled “Public HTTP contract”The routes below are the caller-facing MAS contract. JSON fields use camelCase.
| Endpoint | Request | Response |
|---|---|---|
GET /health |
No body | {status: string} |
POST /quote |
JSON QuoteRequest |
JSON QuoteResponse |
POST /quote/stream |
JSON exact-input QuoteRequest |
text/event-stream |
GET /health
Section titled “GET /health”The response shape is:
{ "status": "ok" }The current handler reports ok. Treat a non-2xx response or an unreadable body as unavailable;
the handler does not expose a second health state.
POST /quote
Section titled “POST /quote”Core request shape:
{ "chainId": 8453, "tokenIn": "0xEvmTokenIn", "tokenOut": "0xEvmTokenOut", "amountIn": "decimal raw amount", "taker": "0xEvmTaker", "slippageBps": 50, "quoteType": "exactInput", "calldataPolicy": "strict", "dryRun": false}Exact-input is the default. For exact-output, send quoteType: "exactOutput", targetOut, and
maxIn instead of amountIn, and set calldataPolicy to strict.
The response shape is:
{ "best": { "provider": "source name", "amountIn": "decimal raw amount or null", "amountOut": "decimal raw amount", "target": "0xRouterTarget", "approveTarget": "0xAllowanceTarget or null", "calldata": "0x...", "value": "decimal raw value", "gasEstimate": 0, "taxInBps": 0, "taxOutBps": 0, "telemetry": {}, "simulation": {} }, "quotes": [], "failures": [{ "provider": "source name", "reason": "reason" }], "responses": [], "dispatched": 0, "elapsedMs": 0, "quoteType": "exactInput", "calldataPolicy": "strict", "tracking": { "dryRun": false, "clientId": null, "requestId": null }, "simulation": {}, "proxyTx": { "to": "0xProxy", "data": "0x...", "value": "decimal raw value", "minOut": "decimal raw amount" }}Optional proxyAddress adds proxyTx for the focal quote. It is a calldata bundle, not a signed
transaction. relaxedProviderMinReturn is for a caller that enforces its own outer output guard;
it lowers known provider-internal minimum-return guards and is only accepted for exact-input.
POST /quote/stream
Section titled “POST /quote/stream”The request body is the exact-input /quote body. keepAliveMs and refreshIntervalMs enable
repeated dispatch cycles; firstN and mustInclude affect when the initial event is emitted.
Exact-output streams are not supported.
Parse the SSE event name and then parse its JSON data:
| Event | Data shape | Caller action |
|---|---|---|
initial |
Initial QuoteResponse |
Start with the quotes available now. |
quote |
{quote, quoteType, calldataPolicy, tracking, proxyTx?} |
Add a late source quote. |
sim_update |
{provider, simulation, tracking} |
Update that provider’s simulation state. |
keep_alive |
{elapsedMs, refreshesDone} |
Keep the connection open. |
refresh |
{cycle, elapsedMs, tracking} |
Mark a new dispatch cycle. |
done |
{elapsedMs, quoteType, tracking} |
Stop reading the stream. |
proxyTx is a sibling of quote in a quote event. In single-shot mode, expect initial, late
quote and simulation updates as available, then done.
Caller states
Section titled “Caller states”- A successful HTTP response can contain both
quotesandfailures; a source failure does not imply that every source failed. - With
dryRun: true, each quote has a simulation state. Handlesuccess,reverted,slotNotFound,rpcError,notConfigured,disabled, andpendingrather than treating the field as a boolean. bestcan change to the provider named bysimulation.winnerProviderIdafter simulation.- Handle HTTP 400 for invalid input and HTTP 502 for provider or upstream failures, plus transport errors and timeouts.
- The stream is incremental. A late quote is not a duplicate of
initial; key updates by provider and finish ondone.
Implementation mapping
Section titled “Implementation mapping”| Endpoint | Verification |
|---|---|
GET /health |
Handler and response shape: meta-aggregator-service/src/app.rs:48,62-64. |
POST /quote |
Request/response DTOs: meta-aggregator-service/src/domain.rs:9-90; route: src/app.rs:50,82-85. |
POST /quote/stream |
Route: meta-aggregator-service/src/app.rs:51; SSE handler: src/app/stream.rs:34-104. |