Skip to content

Commit

Permalink
Implement error module
Browse files Browse the repository at this point in the history
  • Loading branch information
pablomendezroyo committed Sep 19, 2024
1 parent f162d7d commit 3e5bcd3
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 93 deletions.
8 changes: 8 additions & 0 deletions packages/brain/src/modules/apiClients/beaconchain/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ApiError } from "../../errors/index.js";

export class BeaconchainApiError extends ApiError {
constructor(message: string, stack?: string) {
super({ message, stack });
this.name = "BeaconchainApiError"; // Override the name if needed
}
}
29 changes: 15 additions & 14 deletions packages/brain/src/modules/apiClients/beaconchain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { StandardApi } from "../standard.js";
import path from "path";
import { ApiParams } from "../types.js";
import { Network } from "@stakingbrain/common";
import { BeaconchainApiError } from "./error.js";

// TODO: BlockId can also be a simple slot in the form of a string. Is this type still necessary?
type BlockId = "head" | "genesis" | "finalized" | string | `0x${string}`;
Expand Down Expand Up @@ -68,7 +69,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error posting (POST) voluntary exits to beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -85,7 +86,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) genesis from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -107,7 +108,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) fork from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -129,7 +130,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) state finality checkpoints from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -154,7 +155,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) validator from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand Down Expand Up @@ -182,7 +183,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (POST) state validators from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand Down Expand Up @@ -214,7 +215,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) block attestations from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -240,7 +241,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (POST) attestation rewards from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -266,7 +267,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (POST) sync committee rewards from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -285,7 +286,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) proposer duties from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -303,7 +304,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) block rewards from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand Down Expand Up @@ -333,7 +334,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (POST) liveness from validator. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -350,7 +351,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) syncing status from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand All @@ -369,7 +370,7 @@ export class BeaconchainApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) block header from beaconchain. `;
throw e;
throw new BeaconchainApiError({ ...e });
}
}

Expand Down
8 changes: 8 additions & 0 deletions packages/brain/src/modules/apiClients/blockExplorer/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ApiError } from "../../errors/index.js";

export class BlockExplorerApiError extends ApiError {
constructor(message: string, stack?: string) {
super({ message, stack });
this.name = "BlockExplorerApiError"; // Override the name if needed
}
}
3 changes: 2 additions & 1 deletion packages/brain/src/modules/apiClients/blockExplorer/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { StandardApi } from "../standard.js";
import { BeaconchaGetResponse } from "./types.js";
import { BlockExplorerApiError } from "./error.js";

const maxValidatorsPerRequest = 100; //For beaconcha.in --> TODO: is it the same for Gnosis?

Expand Down Expand Up @@ -44,7 +45,7 @@ export class BlockExplorerApi extends StandardApi {
})) as BeaconchaGetResponse;
} catch (e) {
e.message += "Error on getting indexes for validator public keys";
throw e;
throw new BlockExplorerApiError({ ...e });
}
}
}
1 change: 0 additions & 1 deletion packages/brain/src/modules/apiClients/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ export { StandardApi } from "./standard.js";
export { Web3SignerApi } from "./signer/index.js";
export { PostgresClient } from "./postgres/index.js";
export { DappnodeSignatureVerifier } from "./signatureVerifier/index.js";
export { ApiError } from "./error.js";
8 changes: 8 additions & 0 deletions packages/brain/src/modules/apiClients/postgres/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ApiError } from "../../errors/index.js";

export class PostgresApiError extends ApiError {
constructor(message: string, stack?: string) {
super({ message, stack });
this.name = "PostgresApiError"; // Override the name if needed
}
}
3 changes: 2 additions & 1 deletion packages/brain/src/modules/apiClients/postgres/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import postgres from "postgres";
import logger from "../../logger/index.js";
import { BlockProposalStatus, ValidatorPerformance } from "./types.js";
import { PostgresApiError } from "./error.js";

export class PostgresClient {
private readonly tableName = "validators_performance";
Expand Down Expand Up @@ -32,7 +33,7 @@ SELECT pg_total_relation_size('${this.tableName}');
return result[0].pg_total_relation_size;
} catch (err) {
err.message = "Error getting table size: " + err.message;
throw err;
throw new PostgresApiError({ ...err });
}
}

Expand Down
8 changes: 8 additions & 0 deletions packages/brain/src/modules/apiClients/signer/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ApiError } from "../../errors/index.js";

export class SignerApiError extends ApiError {
constructor(message: string, stack?: string) {
super({ message, stack });
this.name = "SignerApiError"; // Override the name if needed
}
}
13 changes: 7 additions & 6 deletions packages/brain/src/modules/apiClients/signer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { StandardApi } from "../standard.js";
import path from "node:path";
import { prefix0xPubkey } from "../prefix0xPubkey.js";
import { SignerApiError } from "./error.js";

/**
* Key Manager API standard
Expand Down Expand Up @@ -72,7 +73,7 @@ export class Web3SignerApi extends StandardApi {
});
} catch (e) {
e.message += `Error signing (POST) voluntary exit for validator index ${signerVoluntaryExitRequest.voluntary_exit.validator_index}. `;
throw e;
throw new SignerApiError({ ...e });
}
}

Expand All @@ -99,7 +100,7 @@ export class Web3SignerApi extends StandardApi {
});
} catch (e) {
e.message += `Error signing (POST) proof of validation for validator ${pubkey}. `;
throw e;
throw new SignerApiError({ ...e });
}
}

Expand All @@ -118,7 +119,7 @@ export class Web3SignerApi extends StandardApi {
});
} catch (e) {
e.message += `Error importing (POST) keystores to remote signer. `;
throw e;
throw new SignerApiError({ ...e });
}
}

Expand All @@ -141,7 +142,7 @@ export class Web3SignerApi extends StandardApi {
});
} catch (e) {
e.message += `Error deleting (DELETE) keystores from remote signer. `;
throw e;
throw new SignerApiError({ ...e });
}
}

Expand All @@ -158,7 +159,7 @@ export class Web3SignerApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) keystores from remote signer. `;
throw e;
throw new SignerApiError({ ...e });
}
}

Expand All @@ -175,7 +176,7 @@ export class Web3SignerApi extends StandardApi {
});
} catch (e) {
e.message += `Error getting (GET) server status. Is Web3Signer running? `;
throw e;
throw new SignerApiError({ ...e });
}
}
}
57 changes: 19 additions & 38 deletions packages/brain/src/modules/apiClients/standard.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import https from "node:https";
import http from "node:http";
import { ApiError } from "./error.js";
import { ApiError } from "../errors/index.js";
import logger from "../logger/index.js";
import type { ApiParams, AllowedMethods, ErrnoException } from "./types.js";
import type { Network } from "@stakingbrain/common";
Expand Down Expand Up @@ -73,13 +73,7 @@ export class StandardApi {
if (timeout) {
req.setTimeout(timeout, () => {
const error = new ApiError({
name: "TimeoutError",
message: `Request to ${endpoint} timed out.`,
errno: -1,
code: "ETIMEDOUT",
path: endpoint,
syscall: method,
hostname: this.requestOptions.hostname || undefined
message: `Request to ${endpoint} timed out`
});
req.destroy(error);
});
Expand All @@ -103,23 +97,12 @@ export class StandardApi {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
resolve: (data?: any) => void | string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
reject: (error: any) => void | ApiError
reject: (error: any) => void | typeof ApiError
) => {
req.on("error", (e: ErrnoException) => {
// an error might have the following format
// {"bytesParsed":0,"code":"HPE_INVALID_CONSTANT","reason":"Expected HTTP/","rawPacket":{"type":"Buffer","data":[21,3,3,0,2,2,80]}}

reject(
new ApiError({
name: e.name || "Standard ApiError",
message: `Request to ${endpoint} failed with status code ${e.code}: ${e.message}. `,
errno: e.errno || -1,
code: e.code || "UNKNOWN",
path: endpoint,
syscall: method,
hostname: this.requestOptions.hostname || undefined,
address: e.address,
port: e.port
message: `Request to ${endpoint} failed with status code ${e.code}: ${e.message}. `
})
);
});
Expand All @@ -141,7 +124,7 @@ export class StandardApi {
else resolve(Buffer.concat(data).toString());
} catch (e) {
logger.error(
`Error parsing response from ${this.requestOptions.hostname} ${endpoint} ${e.message}`,
`Error parsing response from ${this.requestOptions.hostname} ${endpoint} ${e.message}. Considering the response as text`,
e
);
resolve(Buffer.concat(data).toString());
Expand All @@ -164,29 +147,15 @@ export class StandardApi {

reject(
new ApiError({
name: "Standard ApiError",
message: `Request to ${endpoint} failed with status code ${res.statusCode}: ${errorMessage}. `,
errno: res.statusCode,
code: "ERR_HTTP",
path: endpoint,
syscall: method,
hostname: this.requestOptions.hostname || undefined
message: `Request to ${endpoint} failed with status code ${res.statusCode}: ${errorMessage}. `
})
);
}
});
res.on("error", (e: ErrnoException) => {
reject(
new ApiError({
name: e.name || "Standard ApiError",
message: `${e.message}. `,
errno: e.errno || -1,
code: e.code || "UNKNOWN",
path: endpoint,
syscall: method,
hostname: this.requestOptions.hostname || undefined,
address: e.address,
port: e.port
message: `${e.message}. `
})
);
});
Expand All @@ -195,3 +164,15 @@ export class StandardApi {
);
}
}

// Utility to append help message to error depending on error code
export function appendHelpMessage(errorMessage: string, errorCode: string, errno?: string, hostname?: string): string {
if (errorCode === "ECONNREFUSED")
errorMessage += `Connection refused by the server ${hostname}. Make sure the port is open and the server is running`;
else if (errorCode === "ECONNRESET") errorMessage += `Connection reset by the server ${hostname}, check server logs`;
else if (errorCode === "ENOTFOUND")
errorMessage += `Host ${hostname} not found. Make sure the server is running and the hostname is correct`;
else if (errorCode === "ERR_HTTP") errorMessage += `HTTP error code ${errno}`;

return errorMessage;
}
8 changes: 8 additions & 0 deletions packages/brain/src/modules/apiClients/validator/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ApiError } from "../../errors/index.js";

export class ValidatorApiError extends ApiError {
constructor(message: string, stack?: string) {
super({ message, stack });
this.name = "ValidatorApiError"; // Override the name if needed
}
}
Loading

0 comments on commit 3e5bcd3

Please sign in to comment.