diff --git a/CHANGELOG.md b/CHANGELOG.md index f50346f6..15b6551e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,7 +84,10 @@ and this project adheres to @cosmjs/launchpad. They are re-exported in @cosmjs/launchpad for backwards compatibility. - @cosmjs/stargate: Add `GasPrice.toString`. +- @cosmjs/faucet: Added a new functionality to faucet: Each address is only + allowed to get credits once every 24h to prevent draining. ([#962])) +[#962]: https://github.com/cosmos/cosmjs/issues/962 [#938]: https://github.com/cosmos/cosmjs/issues/938 [#932]: https://github.com/cosmos/cosmjs/issues/932 [#878]: https://github.com/cosmos/cosmjs/issues/878 diff --git a/packages/faucet/src/api/webserver.ts b/packages/faucet/src/api/webserver.ts index 4a000531..ae17951f 100644 --- a/packages/faucet/src/api/webserver.ts +++ b/packages/faucet/src/api/webserver.ts @@ -16,6 +16,7 @@ export interface ChainConstants { export class Webserver { private readonly api = new Koa(); + private readonly addressCounter = new Map(); public constructor(faucet: Faucet, chainConstants: ChainConstants) { this.api.use(cors()); @@ -58,13 +59,22 @@ export class Webserver { // context.request.body is set by the bodyParser() plugin const requestBody = context.request.body; const creditBody = RequestParser.parseCreditBody(requestBody); - const { address, denom } = creditBody; if (!isValidAddress(address, constants.addressPrefix)) { throw new HttpError(400, "Address is not in the expected format for this chain."); } + const entry = this.addressCounter.get(address); + if (entry !== undefined) { + if (entry.getTime() + 24 * 3600 > Date.now()) { + throw new HttpError( + 405, + "Too many request from the same address. Blocked to prevent draining. Please wait 24h and try it again!", + ); + } + } + const availableTokens = await faucet.availableTokens(); const matchingDenom = availableTokens.find((availableDenom) => availableDenom === denom); if (matchingDenom === undefined) { @@ -73,6 +83,8 @@ export class Webserver { try { await faucet.credit(address, matchingDenom); + // Count addresses to prevent draining + this.addressCounter.set(address, new Date()); } catch (e) { console.error(e); throw new HttpError(500, "Sending tokens failed");