Skip to content

Commit

Permalink
feat(evm-api): implement eth_getBlockTransactionCountByHash (#796)
Browse files Browse the repository at this point in the history
* Add action

* Implement action

* Add test

* Enable tests
  • Loading branch information
sebastijankuzner authored Dec 4, 2024
1 parent 9c30dde commit ec14683
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Identifiers } from "@mainsail/contracts";
import { Validator } from "@mainsail/validation";

import { describe, Sandbox } from "../../../test-framework/source";
import { EthGetBlockTransactionCountByHash } from "./index.js";

describe<{
sandbox: Sandbox;
action: EthGetBlockTransactionCountByHash;
validator: Validator;
database: any;
}>("EthGetBlockTransactionCountByHash", ({ beforeEach, it, assert, stub }) => {
beforeEach(async (context) => {
context.database = {
getBlockHeaderById: async () => undefined,
};

context.sandbox = new Sandbox();

context.sandbox.app.bind(Identifiers.Database.Service).toConstantValue(context.database);

context.action = context.sandbox.app.resolve(EthGetBlockTransactionCountByHash);
context.validator = context.sandbox.app.resolve(Validator);
});

it("should have a name", ({ action }) => {
assert.equal(action.name, "eth_getBlockTransactionCountByHash");
});

it("schema should be array with 0 parameters", ({ action, validator }) => {
validator.addSchema({
$id: "prefixedHex",
pattern: "^0x[0-9a-f]+$",
type: "string",
});
validator.addSchema(action.schema);

assert.undefined(
validator.validate("jsonRpc_eth_getBlockTransactionCountByHash", [
"0x0000000000000000000000000000000000000000000000000000000000000000",
]).errors,
);
assert.defined(
validator.validate("jsonRpc_eth_getBlockTransactionCountByHash", [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"",
]).errors,
);
assert.defined(validator.validate("jsonRpc_eth_getBlockTransactionCountByHash", [1]).errors);
assert.defined(validator.validate("jsonRpc_eth_getBlockTransactionCountByHash", {}).errors);
});

it("should return null if block not found", async ({ action }) => {
assert.null(await action.handle(["0x0000000000000000000000000000000000000000000000000000000000000000"]));
});

it("should return 0x0", async ({ action, database }) => {
const spyGetBlockHeaderById = stub(database, "getBlockHeaderById").returnValue({ numberOfTransactions: 0 });

assert.equal(
await action.handle(["0x0000000000000000000000000000000000000000000000000000000000000000"]),
"0x0",
);

spyGetBlockHeaderById.calledOnce();
spyGetBlockHeaderById.calledWith("0000000000000000000000000000000000000000000000000000000000000000");
});

it("should return 0x14", async ({ action, database }) => {
const spyGetBlockHeaderById = stub(database, "getBlockHeaderById").returnValue({ numberOfTransactions: 20 });

assert.equal(
await action.handle(["0x0000000000000000000000000000000000000000000000000000000000000000"]),
"0x14",
);

spyGetBlockHeaderById.calledOnce();
spyGetBlockHeaderById.calledWith("0000000000000000000000000000000000000000000000000000000000000000");
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { inject, injectable } from "@mainsail/container";
import { Contracts, Identifiers } from "@mainsail/contracts";

@injectable()
export class EthGetBlockTransactionCountByHash implements Contracts.Api.RPC.Action {
public readonly name: string = "eth_getBlockTransactionCountByHash";

@inject(Identifiers.Database.Service)
private readonly databaseService!: Contracts.Database.DatabaseService;

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<string | null> {
const block = await this.databaseService.getBlockHeaderById(parameters[0].slice(2));

if (!block) {
// eslint-disable-next-line unicorn/no-null
return null;
}

return `0x${block.numberOfTransactions.toString(16)}`;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Identifiers } from "@mainsail/contracts";
import { Validator } from "@mainsail/validation";

import { describeSkip, Sandbox } from "../../../test-framework/source";
import { describe, Sandbox } from "../../../test-framework/source";
import { EthGetTransactionCount } from "./index.js";

describeSkip<{
describe<{
sandbox: Sandbox;
action: EthGetTransactionCount;
validator: Validator;
Expand Down
1 change: 1 addition & 0 deletions packages/api-evm/source/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from "./eth-call.js";
export * from "./eth-get-balance.js";
export * from "./eth-get-block-by-hash.js";
export * from "./eth-get-block-by-number.js";
export * from "./eth-get-block-transaction-count-by-hash.js";
export * from "./eth-get-code.js";
export * from "./eth-get-storage-at.js";
export * from "./eth-get-transaction-count.js";
Expand Down
2 changes: 2 additions & 0 deletions packages/api-evm/source/service-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
EthGetBalanceAction,
EthGetBlockByHashAction,
EthGetBlockByNumberAction,
EthGetBlockTransactionCountByHash,
EthGetCodeAction,
EthGetStorageAtAction,
EthGetTransactionCount,
Expand Down Expand Up @@ -75,6 +76,7 @@ export class ServiceProvider extends AbstractServiceProvider<Server> {
this.app.resolve(EthGetBalanceAction),
this.app.resolve(EthGetBlockByHashAction),
this.app.resolve(EthGetBlockByNumberAction),
this.app.resolve(EthGetBlockTransactionCountByHash),
this.app.resolve(EthGetCodeAction),
this.app.resolve(EthGetStorageAtAction),
this.app.resolve(EthGetTransactionCount),
Expand Down

0 comments on commit ec14683

Please sign in to comment.