diff --git a/pages/api/rpc.ts b/pages/api/rpc.ts index 8d2ac555..385f0efe 100644 --- a/pages/api/rpc.ts +++ b/pages/api/rpc.ts @@ -76,7 +76,7 @@ const rpc = rpcFactory({ allowedCallAddresses, allowedLogsAddresses, maxBatchCount: config.PROVIDER_MAX_BATCH, - disallowEmptyAddressGetLogs: false, + disallowEmptyAddressGetLogs: true, }); export default wrapNextRequest([ diff --git a/server.mjs b/server.mjs index 8734385a..070ed4ef 100644 --- a/server.mjs +++ b/server.mjs @@ -46,9 +46,7 @@ app.prepare().then(() => { }) .listen(port, () => { console.debug(`> Ready on http://${hostname}:${port}`); - }) - // hanging socket timeout - .setTimeout(10_000); + }); // prevents malicious client from slowly sending headers and rest of request server.headersTimeout = 10_000; server.requestTimeout = 30_000; diff --git a/shared/hooks/use-balance.ts b/shared/hooks/use-balance.ts index 77a79562..99a33f38 100644 --- a/shared/hooks/use-balance.ts +++ b/shared/hooks/use-balance.ts @@ -135,7 +135,7 @@ export const useTokenTransferSubscription = () => { [queryClient, subscriptions], ); - const shouldWatch = address && tokens.length > 0; + const shouldWatch = !!(address && tokens.length > 0); useWatchContractEvent({ abi: Erc20EventsAbi, diff --git a/utils/use-web3-transport.ts b/utils/use-web3-transport.ts index 7a22b453..78c906cd 100644 --- a/utils/use-web3-transport.ts +++ b/utils/use-web3-transport.ts @@ -60,8 +60,13 @@ const runtimeMutableTransport = ( if ( requestParams.method === 'eth_getLogs' && Array.isArray(requestParams?.params) && - requestParams.params[0]?.address?.length < 0 + // works for empty array, empty string and all falsish values + !requestParams.params[0]?.address?.length ) { + console.warn( + '[runtimeMutableTransport] Invalid empty getLogs', + requestParams, + ); const error = new InvalidParamsRpcError( new Error(`Empty address for eth_getLogs is not supported`), ); diff --git a/utilsApi/rpcFactory.ts b/utilsApi/rpcFactory.ts index 2142ac7c..def14b98 100644 --- a/utilsApi/rpcFactory.ts +++ b/utilsApi/rpcFactory.ts @@ -1,4 +1,4 @@ -import { Readable, Transform } from 'node:stream'; +import { Readable } from 'node:stream'; import { ReadableStream } from 'node:stream/web'; import type { NextApiRequest, NextApiResponse } from 'next'; import { Counter, Registry } from 'prom-client'; @@ -38,28 +38,6 @@ export class SizeTooLargeError extends ClientError { } } -const createSizeLogger = (MAX_SIZE: number) => { - let bytesWritten = 0; - const logSizeStream = new Transform({ - transform(chunk, _encoding, callback) { - bytesWritten += chunk.length; - if (bytesWritten > MAX_SIZE) { - // Emit an error if size exceeds MAX_SIZE - return callback( - new SizeTooLargeError( - `Stream size exceeds the maximum limit of ${MAX_SIZE} bytes`, - ), - ); - } - return callback(null, chunk); // Pass the chunk through - }, - flush(callback) { - callback(); - }, - }); - return logSizeStream; -}; - export type RPCFactoryParams = { metrics: { prefix: string; @@ -89,7 +67,6 @@ export const rpcFactory = ({ allowedCallAddresses = {}, allowedLogsAddresses = {}, maxBatchCount, - maxResponseSize = 1_000_000, // ~1MB, disallowEmptyAddressGetLogs = false, }: RPCFactoryParams) => { const rpcRequestBlocked = new Counter({ @@ -214,26 +191,7 @@ export const rpcFactory = ({ requested.headers.get('Content-Type') ?? 'application/json', ); if (requested.body) { - const sizeLimit = createSizeLogger(maxResponseSize); - const readableStream = Readable.fromWeb( - requested.body as ReadableStream, - ); - readableStream - .pipe(sizeLimit) - .on('error', (error) => { - if (error instanceof SizeTooLargeError) { - console.warn( - `[rpcFactory] RPC response too large: ${JSON.stringify(requests)}`, - ); - // Payload Too Large - res.status(413).end(); - } else { - res.statusCode = 500; - res.end(DEFAULT_API_ERROR_MESSAGE); - } - readableStream.destroy(); - }) - .pipe(res); + Readable.fromWeb(requested.body as ReadableStream).pipe(res); } else { res .status(requested.status)