diff --git a/packages/api-evm/source/actions/index.ts b/packages/api-evm/source/actions/index.ts index de43571b0..4f0690810 100644 --- a/packages/api-evm/source/actions/index.ts +++ b/packages/api-evm/source/actions/index.ts @@ -13,3 +13,4 @@ export * from "./eth-get-uncle-count-by-block-number.js"; export * from "./net-listening.js"; export * from "./net-peer-count.js"; export * from "./web3-client-version.js"; +export * from "./web3-sha3.js"; diff --git a/packages/api-evm/source/actions/web3-sha3.test.ts b/packages/api-evm/source/actions/web3-sha3.test.ts new file mode 100644 index 000000000..659f46ab0 --- /dev/null +++ b/packages/api-evm/source/actions/web3-sha3.test.ts @@ -0,0 +1,57 @@ +import { Identifiers } from "@mainsail/contracts"; +import { Validator } from "@mainsail/validation"; + +import { describe, Sandbox } from "../../../test-framework/source"; +import { Web3Sha3 } from "./index.js"; + +describe<{ + sandbox: Sandbox; + action: Web3Sha3; + validator: Validator; +}>("Web3Sha3", ({ beforeEach, it, assert }) => { + const version = "0.0.1"; + + beforeEach(async (context) => { + context.sandbox = new Sandbox(); + + context.sandbox.app.bind(Identifiers.Application.Version).toConstantValue(version); + + context.action = context.sandbox.app.resolve(Web3Sha3); + context.validator = context.sandbox.app.resolve(Validator); + }); + + it("should have a name", ({ action }) => { + assert.equal(action.name, "web3_sha3"); + }); + + it("schema should be ok", ({ action, validator }) => { + validator.addSchema({ + $id: "prefixedHex", + pattern: "^0x[0-9a-f]+$", + type: "string", + }); + + assert.equal(action.schema, { + $id: `jsonRpc_web3_sha3`, + maxItems: 1, + minItems: 1, + + prefixItems: [{ $ref: "prefixedHex" }], + type: "array", + }); + + validator.addSchema(action.schema); + + assert.undefined(validator.validate("jsonRpc_web3_sha3", ["0x0"]).errors); + assert.defined(validator.validate("jsonRpc_web3_sha3", ["0x0", ""]).errors); + assert.defined(validator.validate("jsonRpc_web3_sha3", [1]).errors); + assert.defined(validator.validate("jsonRpc_web3_sha3", {}).errors); + }); + + it("should return the keccak256 of provided data", async ({ action }) => { + assert.equal( + await action.handle(["0x68656c6c6f20776f726c64"]), + "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad", + ); + }); +}); diff --git a/packages/api-evm/source/actions/web3-sha3.ts b/packages/api-evm/source/actions/web3-sha3.ts new file mode 100644 index 000000000..870bac356 --- /dev/null +++ b/packages/api-evm/source/actions/web3-sha3.ts @@ -0,0 +1,21 @@ +import { injectable } from "@mainsail/container"; +import { Contracts } from "@mainsail/contracts"; +import { keccak256 } from "ethers"; + +@injectable() +export class Web3Sha3 implements Contracts.Api.RPC.Action { + public readonly name: string = "web3_sha3"; + + public readonly schema = { + $id: `jsonRpc_${this.name}`, + maxItems: 1, + minItems: 1, + + prefixItems: [{ $ref: "prefixedHex" }], + type: "array", + }; + + public async handle(parameters: [string]): Promise { + return `0x${keccak256(parameters[0]).slice(2)}`; + } +} diff --git a/packages/api-evm/source/service-provider.ts b/packages/api-evm/source/service-provider.ts index c05d3ea8d..cfea7f2fa 100644 --- a/packages/api-evm/source/service-provider.ts +++ b/packages/api-evm/source/service-provider.ts @@ -18,6 +18,7 @@ import { NetListeningAction, NetPeerCountAction, Web3ClientVersionAction, + Web3Sha3, } from "./actions/index.js"; import Handlers from "./handlers.js"; import { Server } from "./server.js"; @@ -83,6 +84,7 @@ export class ServiceProvider extends AbstractServiceProvider { this.app.resolve(NetListeningAction), this.app.resolve(NetPeerCountAction), this.app.resolve(Web3ClientVersionAction), + this.app.resolve(Web3Sha3), ]; }