From 7f6c7d07257511e2f6e7daf1087c21e0e373d80e Mon Sep 17 00:00:00 2001 From: "Sebastijan K." <58827427+sebastijankuzner@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:37:06 +0100 Subject: [PATCH] feat(evm-api): implement `eth_getUncleCountByBlockHash` (#787) * Add EthGetUncleCountByBlockHash * Fix error handler * Add hasCommitById * Add block check * Slice block id * style: resolve style guide violations --------- Co-authored-by: sebastijankuzner --- packages/api-common/source/rcp/processor.ts | 8 ++++-- packages/api-common/source/rcp/utils.ts | 3 ++- .../eth-get-uncle-count-by-block-hash.ts | 27 +++++++++++++++++++ packages/api-evm/source/actions/index.ts | 1 + packages/api-evm/source/service-provider.ts | 2 ++ .../contracts/source/contracts/database.ts | 1 + packages/database/source/database-service.ts | 4 +++ 7 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 packages/api-evm/source/actions/eth-get-uncle-count-by-block-hash.ts diff --git a/packages/api-common/source/rcp/processor.ts b/packages/api-common/source/rcp/processor.ts index bcabb4371..652efd8b5 100644 --- a/packages/api-common/source/rcp/processor.ts +++ b/packages/api-common/source/rcp/processor.ts @@ -1,6 +1,6 @@ import Hapi from "@hapi/hapi"; import { inject, injectable } from "@mainsail/container"; -import { Contracts, Identifiers } from "@mainsail/contracts"; +import { Contracts, Exceptions, Identifiers } from "@mainsail/contracts"; import { getRcpId, prepareRcpError } from "./utils.js"; @@ -37,7 +37,11 @@ export class Processor implements Contracts.Api.RPC.Processor { jsonrpc: "2.0", result: await action.handle(payload.params), }; - } catch { + } catch (error) { + if (error instanceof Exceptions.RpcError) { + return prepareRcpError(getRcpId(request), error.code, error.message); + } + return prepareRcpError(getRcpId(request), Contracts.Api.RPC.ErrorCode.InternalError); } } diff --git a/packages/api-common/source/rcp/utils.ts b/packages/api-common/source/rcp/utils.ts index a943e118e..265f1357a 100644 --- a/packages/api-common/source/rcp/utils.ts +++ b/packages/api-common/source/rcp/utils.ts @@ -27,10 +27,11 @@ export const errorMessageMap = { export const prepareRcpError = ( id: Contracts.Api.RPC.Id, errorCode: Contracts.Api.RPC.ErrorCode, + message?: string, ): Contracts.Api.RPC.Error => ({ error: { code: errorCode, - message: errorMessageMap[errorCode], + message: message ?? errorMessageMap[errorCode], }, id, jsonrpc: "2.0", diff --git a/packages/api-evm/source/actions/eth-get-uncle-count-by-block-hash.ts b/packages/api-evm/source/actions/eth-get-uncle-count-by-block-hash.ts new file mode 100644 index 000000000..02c629550 --- /dev/null +++ b/packages/api-evm/source/actions/eth-get-uncle-count-by-block-hash.ts @@ -0,0 +1,27 @@ +import { inject, injectable } from "@mainsail/container"; +import { Contracts, Exceptions, Identifiers } from "@mainsail/contracts"; + +@injectable() +export class EthGetUncleCountByBlockHash implements Contracts.Api.RPC.Action { + @inject(Identifiers.Database.Service) + private readonly databaseService!: Contracts.Database.DatabaseService; + + public readonly name: string = "eth_getUncleCountByBlockHash"; + + public readonly schema = { + $id: `jsonRpc_${this.name}`, + maxItems: 1, + minItems: 1, + + prefixItems: [{ $ref: "prefixedHex" }], // TODO: Replace prefixedHex with prefixedBlockId + type: "array", + }; + + public async handle(parameters: [string]): Promise { + if (!this.databaseService.hasCommitById(parameters[0].slice(2))) { + throw new Exceptions.RpcError("Block not found"); + } + + return `0x0`; + } +} diff --git a/packages/api-evm/source/actions/index.ts b/packages/api-evm/source/actions/index.ts index c81b1f276..182e83c38 100644 --- a/packages/api-evm/source/actions/index.ts +++ b/packages/api-evm/source/actions/index.ts @@ -6,6 +6,7 @@ export * from "./eth-get-block-by-number.js"; export * from "./eth-get-code.js"; export * from "./eth-get-storage-at.js"; export * from "./eth-get-transaction-count.js"; +export * from "./eth-get-uncle-count-by-block-hash.js"; export * from "./net-listening.js"; export * from "./net-peer-count.js"; export * from "./web3-client-version.js"; diff --git a/packages/api-evm/source/service-provider.ts b/packages/api-evm/source/service-provider.ts index 7ff0734f0..596959a20 100644 --- a/packages/api-evm/source/service-provider.ts +++ b/packages/api-evm/source/service-provider.ts @@ -11,6 +11,7 @@ import { EthGetCodeAction, EthGetStorageAtAction, EthGetTransactionCount, + EthGetUncleCountByBlockHash, NetListeningAction, NetPeerCountAction, Web3ClientVersionAction, @@ -72,6 +73,7 @@ export class ServiceProvider extends AbstractServiceProvider { this.app.resolve(EthGetCodeAction), this.app.resolve(EthGetStorageAtAction), this.app.resolve(EthGetTransactionCount), + this.app.resolve(EthGetUncleCountByBlockHash), this.app.resolve(NetListeningAction), this.app.resolve(NetPeerCountAction), this.app.resolve(Web3ClientVersionAction), diff --git a/packages/contracts/source/contracts/database.ts b/packages/contracts/source/contracts/database.ts index a7bb9e1cd..90abe6f44 100644 --- a/packages/contracts/source/contracts/database.ts +++ b/packages/contracts/source/contracts/database.ts @@ -13,6 +13,7 @@ export interface DatabaseService { getState(): State; getCommit(height: number): Promise; getCommitById(id: string): Promise; + hasCommitById(id: string): boolean; findCommitBuffers(start: number, end: number): Promise; readCommits(start: number, end: number): AsyncGenerator; findBlocks(start: number, end: number): Promise; diff --git a/packages/database/source/database-service.ts b/packages/database/source/database-service.ts index 1a6688209..b67b6a1f5 100644 --- a/packages/database/source/database-service.ts +++ b/packages/database/source/database-service.ts @@ -67,6 +67,10 @@ export class DatabaseService implements Contracts.Database.DatabaseService { return undefined; } + public hasCommitById(id: string): boolean { + return this.#getHeightById(id) !== undefined; + } + public async findCommitBuffers(start: number, end: number): Promise { const heights: number[] = [];