import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { RateLimitStore } from '@task-stream/api/tracker/application'; /** Proposals from one address within the window. */ const LIMIT = 5; const WINDOW_MS = 15 * 60_000; /** * Keeps one address from flooding a project with proposals. Counted in * Redis, so the limit holds across every instance of the API. */ @Injectable() export class ProposalLimiter { constructor(private readonly store: RateLimitStore) {} async take(address: string): Promise { const count = await this.store.hit(`proposals:${address}`, WINDOW_MS); if (count > LIMIT) throw new HttpException( 'Too many proposals from here; try again in a few minutes', HttpStatus.TOO_MANY_REQUESTS, ); } }