📌 Description
QuoteService.quote is a pure, side-effect-free computation (it reads pool state and returns a projected route/fee without mutating anything), yet routes/quote.ts only exposes it via POST /api/v1/quote. Read-only client integrations that want to preview a quote (e.g. from a browser via a plain link, or cached by an intermediary) currently must construct a POST request body for what is semantically a read.
🧩 Requirements and context
- Add
GET /api/v1/quote?asset=&amount= as an alternative to the existing POST /api/v1/quote, both calling the same QuoteService.quote.
- Keep the existing
POST endpoint and its request-body shape completely unchanged.
- The stricter quote-specific rate limiter already mounted on
/api/v1/quote in app.ts should apply equally to GET — confirm rather than assume this, since the existing rateLimiter() middleware only gates MUTATING_METHODS, which a GET is not.
🛠️ Suggested execution
- Add a
GET / handler in src/routes/quote.ts that maps req.query.asset/req.query.amount into the same shape service.quote(...) expects.
- Because
rateLimiter() only limits mutating methods, add an explicit note/decision in app.ts and this issue's PR about whether the new GET route needs its own non-mutating-aware limiter, since the existing quote-specific limiter effectively won't apply to it.
- Update
src/openapi.ts to add the new GET /api/v1/quote operation.
- Add tests in
src/routes/quote.test.ts for the new GET route including invalid/missing query params.
✅ Acceptance criteria
🔒 Security notes
Because QuoteService.quote does real computation (sorting/aggregating pool entries) on every call, an unthrottled GET alias could reintroduce the same abuse risk the quote-specific POST rate limiter was added to prevent — this must be resolved as part of the same change, not left as a follow-up.
📋 Guidelines
- Minimum 95% test coverage
- Clear documentation
- Timeframe: 96 hours
📌 Description
QuoteService.quoteis a pure, side-effect-free computation (it reads pool state and returns a projected route/fee without mutating anything), yetroutes/quote.tsonly exposes it viaPOST /api/v1/quote. Read-only client integrations that want to preview a quote (e.g. from a browser via a plain link, or cached by an intermediary) currently must construct aPOSTrequest body for what is semantically a read.🧩 Requirements and context
GET /api/v1/quote?asset=&amount=as an alternative to the existingPOST /api/v1/quote, both calling the sameQuoteService.quote.POSTendpoint and its request-body shape completely unchanged./api/v1/quoteinapp.tsshould apply equally toGET— confirm rather than assume this, since the existingrateLimiter()middleware only gatesMUTATING_METHODS, which aGETis not.🛠️ Suggested execution
GET /handler insrc/routes/quote.tsthat mapsreq.query.asset/req.query.amountinto the same shapeservice.quote(...)expects.rateLimiter()only limits mutating methods, add an explicit note/decision inapp.tsand this issue's PR about whether the newGETroute needs its own non-mutating-aware limiter, since the existing quote-specific limiter effectively won't apply to it.src/openapi.tsto add the newGET /api/v1/quoteoperation.src/routes/quote.test.tsfor the newGETroute including invalid/missing query params.✅ Acceptance criteria
GET /api/v1/quote?asset=USDC&amount=100returns the same result shape as the equivalentPOSTbody.POST /api/v1/quotebehavior and tests are unchanged.GETroute for a compute-bearing endpoint is explicitly addressed (either a limiter is added, or the decision not to is documented).🔒 Security notes
Because
QuoteService.quotedoes real computation (sorting/aggregating pool entries) on every call, an unthrottledGETalias could reintroduce the same abuse risk the quote-specificPOSTrate limiter was added to prevent — this must be resolved as part of the same change, not left as a follow-up.📋 Guidelines