Skip to content

Commit

Permalink
improve(any): remove implicit any (#1734)
Browse files Browse the repository at this point in the history
* improve(any): remove implicit any

Signed-off-by: james-a-morris <[email protected]>

* chore: resolve internal subtypes

Signed-off-by: james-a-morris <[email protected]>

* nit: use more robust naming

Signed-off-by: james-a-morris <[email protected]>

---------

Signed-off-by: james-a-morris <[email protected]>
  • Loading branch information
james-a-morris authored Aug 7, 2024
1 parent 1707420 commit 8f0b3ea
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 34 deletions.
14 changes: 9 additions & 5 deletions src/utils/ObjectUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export function count3DDictionaryValues(
* @param obj
* @returns Objects with ignored keys removed
*/
function deleteIgnoredKeys(ignoredKeys: string[], obj: any) {
function deleteIgnoredKeys(ignoredKeys: string[], obj: Record<string, unknown>) {
if (!isDefined(obj)) {
return;
}
Expand All @@ -111,7 +111,11 @@ function deleteIgnoredKeys(ignoredKeys: string[], obj: any) {
return newObj;
}

export function compareResultsAndFilterIgnoredKeys(ignoredKeys: string[], _objA: any, _objB: any): boolean {
export function compareResultsAndFilterIgnoredKeys(
ignoredKeys: string[],
_objA: Record<string, unknown>,
_objB: Record<string, unknown>
): boolean {
// Remove ignored keys from copied objects.
const filteredA = deleteIgnoredKeys(ignoredKeys, _objA);
const filteredB = deleteIgnoredKeys(ignoredKeys, _objB);
Expand All @@ -120,10 +124,10 @@ export function compareResultsAndFilterIgnoredKeys(ignoredKeys: string[], _objA:
return lodash.isEqual(filteredA, filteredB);
}

export function compareArrayResultsWithIgnoredKeys(ignoredKeys: string[], objA: any[], objB: any[]): boolean {
export function compareArrayResultsWithIgnoredKeys(ignoredKeys: string[], objA: unknown[], objB: unknown[]): boolean {
// Remove ignored keys from each element of copied arrays.
const filteredA = objA?.map((obj) => deleteIgnoredKeys(ignoredKeys, obj));
const filteredB = objB?.map((obj) => deleteIgnoredKeys(ignoredKeys, obj));
const filteredA = objA?.map((obj) => deleteIgnoredKeys(ignoredKeys, obj as Record<string, unknown>));
const filteredB = objB?.map((obj) => deleteIgnoredKeys(ignoredKeys, obj as Record<string, unknown>));

// Compare objects without the ignored keys.
return isDefined(filteredA) && isDefined(filteredB) && lodash.isEqual(filteredA, filteredB);
Expand Down
57 changes: 28 additions & 29 deletions src/utils/ProviderUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ethers } from "ethers";
import lodash from "lodash";
import winston from "winston";
Expand Down Expand Up @@ -26,8 +25,8 @@ interface RateLimitTask {

// These are the promise callbacks that will cause the initial send call made by the user to either return a result
// or fail.
resolve: (result: any) => void;
reject: (err: any) => void;
resolve: (result: unknown) => void;
reject: (err: unknown) => void;
}

// StaticJsonRpcProvider is used in place of JsonRpcProvider to avoid redundant eth_chainId queries prior to each
Expand Down Expand Up @@ -59,7 +58,7 @@ class RateLimitedProvider extends ethers.providers.StaticJsonRpcProvider {
}, maxConcurrency);
}

async wrapSendWithLog(method: string, params: Array<any>) {
async wrapSendWithLog(method: string, params: Array<unknown>) {
if (this.pctRpcCallsLogged <= 0 || Math.random() > this.pctRpcCallsLogged / 100) {
// Non sample path: no logging or timing, just issue the request.
return super.send(method, params);
Expand Down Expand Up @@ -99,9 +98,9 @@ class RateLimitedProvider extends ethers.providers.StaticJsonRpcProvider {
}
}

override async send(method: string, params: Array<any>): Promise<any> {
override async send(method: string, params: Array<unknown>): Promise<unknown> {
// This simply creates a promise and adds the arguments and resolve and reject handlers to the task.
return new Promise<any>((resolve, reject) => {
return new Promise<unknown>((resolve, reject) => {
const task: RateLimitTask = {
sendArgs: [method, params],
resolve,
Expand All @@ -118,12 +117,12 @@ function formatProviderError(provider: ethers.providers.StaticJsonRpcProvider, r
return `Provider ${provider.connection.url} failed with error: ${rawErrorText}`;
}

function createSendErrorWithMessage(message: string, sendError: any) {
function createSendErrorWithMessage(message: string, sendError: Record<string, unknown>) {
const error = new Error(message);
return { ...sendError, ...error };
}

function compareRpcResults(method: string, rpcResultA: any, rpcResultB: any): boolean {
function compareRpcResults(method: string, rpcResultA: unknown, rpcResultB: unknown): boolean {
if (method === "eth_getBlockByNumber") {
// We've seen RPC's disagree on the miner field, for example when Polygon nodes updated software that
// led alchemy and quicknode to disagree on the miner field's value.
Expand All @@ -135,8 +134,8 @@ function compareRpcResults(method: string, rpcResultA: any, rpcResultB: any): bo
"size", // Alchemy/Arbitrum (temporary)
"totalDifficulty", // Quicknode/Alchemy (sometimes)
],
rpcResultA,
rpcResultB
rpcResultA as Record<string, unknown>,
rpcResultB as Record<string, unknown>
);
} else if (method === "eth_getLogs") {
// We've seen some RPC's like QuickNode add in transactionLogIndex which isn't in the
Expand All @@ -147,8 +146,8 @@ function compareRpcResults(method: string, rpcResultA: any, rpcResultB: any): bo
// 2024-07-11 Added blockTimestamp after zkSync rolled out a new node release.
return compareArrayResultsWithIgnoredKeys(
["blockTimestamp", "transactionLogIndex", "l1BatchNumber", "logType"],
rpcResultA,
rpcResultB
rpcResultA as unknown[],
rpcResultB as unknown[]
);
} else {
return lodash.isEqual(rpcResultA, rpcResultB);
Expand Down Expand Up @@ -193,7 +192,7 @@ class CacheProvider extends RateLimitedProvider {
}
this.baseTTL = _ttl;
}
override async send(method: string, params: Array<any>): Promise<any> {
override async send(method: string, params: Array<unknown>): Promise<unknown> {
const cacheType = this.redisClient ? await this.cacheType(method, params) : CacheType.NONE;

if (cacheType !== CacheType.NONE) {
Expand Down Expand Up @@ -233,7 +232,7 @@ class CacheProvider extends RateLimitedProvider {
return await super.send(method, params);
}

private buildRedisKey(method: string, params: Array<any>) {
private buildRedisKey(method: string, params: Array<unknown>) {
// Only handles eth_getLogs and eth_call right now.
switch (method) {
case "eth_getBlockByNumber":
Expand All @@ -247,15 +246,15 @@ class CacheProvider extends RateLimitedProvider {
}
}

private async cacheType(method: string, params: Array<any>): Promise<CacheType> {
private async cacheType(method: string, params: Array<unknown>): Promise<CacheType> {
// Today, we only cache eth_getLogs and eth_call.
if (method === "eth_getLogs") {
const [{ fromBlock, toBlock }] = params;
const [{ fromBlock, toBlock }] = params as { toBlock: number; fromBlock: number }[];

// Handle odd cases where the ordering is flipped, etc.
// toBlock/fromBlock is in hex, so it must be parsed before being compared to the first unsafe block.
const fromBlockNumber = parseInt(fromBlock, 16);
const toBlockNumber = parseInt(toBlock, 16);
const fromBlockNumber = parseInt(String(fromBlock), 16);
const toBlockNumber = parseInt(String(toBlock), 16);

// Handle cases where the input block numbers are not hex values ("latest", "pending", etc).
// This would result in the result of the above being NaN.
Expand All @@ -272,7 +271,7 @@ class CacheProvider extends RateLimitedProvider {
// Pull out the block tag from params. Its position in params is dependent on the method.
// We are only interested in numeric block tags, which would be hex-encoded strings.
const idx = method === "eth_getBlockByNumber" ? 0 : 1;
const blockNumber = parseInt(params[idx], 16);
const blockNumber = parseInt(String(params[idx]), 16);

// If the block number isn't present or is a text string, this will be NaN and we return false.
if (Number.isNaN(blockNumber)) {
Expand Down Expand Up @@ -358,7 +357,7 @@ export class RetryProvider extends ethers.providers.StaticJsonRpcProvider {
}
}

override async send(method: string, params: Array<any>): Promise<any> {
override async send(method: string, params: Array<unknown>): Promise<unknown> {
const quorumThreshold = this._getQuorum(method, params);
const requiredProviders = this.providers.slice(0, quorumThreshold);
const fallbackProviders = this.providers.slice(quorumThreshold);
Expand All @@ -370,9 +369,9 @@ export class RetryProvider extends ethers.providers.StaticJsonRpcProvider {
// considered responses come from unique providers.
const tryWithFallback = (
provider: ethers.providers.StaticJsonRpcProvider
): Promise<[ethers.providers.StaticJsonRpcProvider, any]> => {
): Promise<[ethers.providers.StaticJsonRpcProvider, unknown]> => {
return this._trySend(provider, method, params)
.then((result): [ethers.providers.StaticJsonRpcProvider, any] => [provider, result])
.then((result): [ethers.providers.StaticJsonRpcProvider, unknown] => [provider, result])
.catch((err) => {
// Append the provider and error to the error array.
errors.push([provider, err?.stack || err?.toString()]);
Expand Down Expand Up @@ -433,7 +432,7 @@ export class RetryProvider extends ethers.providers.StaticJsonRpcProvider {
const fallbackResults = await Promise.allSettled(
fallbackProviders.map((provider) =>
this._trySend(provider, method, params)
.then((result): [ethers.providers.StaticJsonRpcProvider, any] => [provider, result])
.then((result): [ethers.providers.StaticJsonRpcProvider, unknown] => [provider, result])
.catch((err) => {
errors.push([provider, err?.stack || err?.toString()]);
throw new Error("No fallbacks during quorum search");
Expand Down Expand Up @@ -462,7 +461,7 @@ export class RetryProvider extends ethers.providers.StaticJsonRpcProvider {
// Return the same acc object because it was modified in place.
return acc;
},
[[undefined, 0]] as [any, number][] // Initialize with [undefined, 0] as the first element so something is always returned.
[[undefined, 0]] as [unknown, number][] // Initialize with [undefined, 0] as the first element so something is always returned.
);

// Sort so the result with the highest count is first.
Expand Down Expand Up @@ -501,7 +500,7 @@ export class RetryProvider extends ethers.providers.StaticJsonRpcProvider {
return quorumResult;
}

_validateResponse(method: string, params: Array<any>, response: any): boolean {
_validateResponse(method: string, params: Array<unknown>, response: unknown): boolean {
// Basic validation logic to start.
// Note: eth_getTransactionReceipt is ignored here because null responses are expected in the case that ethers is
// polling for the transaction receipt and receiving null until it does.
Expand All @@ -511,8 +510,8 @@ export class RetryProvider extends ethers.providers.StaticJsonRpcProvider {
async _sendAndValidate(
provider: ethers.providers.StaticJsonRpcProvider,
method: string,
params: Array<any>
): Promise<any> {
params: Array<unknown>
): Promise<unknown> {
const response = await provider.send(method, params);
if (!this._validateResponse(method, params, response)) {
// Not a warning to avoid spam since this could trigger a lot.
Expand All @@ -529,15 +528,15 @@ export class RetryProvider extends ethers.providers.StaticJsonRpcProvider {
return response;
}

_trySend(provider: ethers.providers.StaticJsonRpcProvider, method: string, params: Array<any>): Promise<any> {
_trySend(provider: ethers.providers.StaticJsonRpcProvider, method: string, params: Array<unknown>): Promise<unknown> {
let promise = this._sendAndValidate(provider, method, params);
for (let i = 0; i < this.retries; i++) {
promise = promise.catch(() => delay(this.delay).then(() => this._sendAndValidate(provider, method, params)));
}
return promise;
}

_getQuorum(method: string, params: Array<any>): number {
_getQuorum(method: string, params: Array<unknown>): number {
// Only use quorum if this is a historical query that doesn't depend on the current block number.

// All logs queries should use quorum.
Expand Down

0 comments on commit 8f0b3ea

Please sign in to comment.