diff --git a/packages/api-evm/source/actions/eth-get-block-by-number.ts b/packages/api-evm/source/actions/eth-get-block-by-number.ts new file mode 100644 index 000000000..d212cc7a7 --- /dev/null +++ b/packages/api-evm/source/actions/eth-get-block-by-number.ts @@ -0,0 +1,45 @@ +import { inject, injectable } from "@mainsail/container"; +import { Contracts, Identifiers } from "@mainsail/contracts"; + +import { BlockResource } from "../resources/index.js"; + +@injectable() +export class EthGetBlockByNumberAction implements Contracts.Api.RPC.Action { + public readonly name: string = "eth_getBlockByNumber"; + + @inject(Identifiers.Application.Instance) + private readonly app!: Contracts.Kernel.Application; + + @inject(Identifiers.State.Store) + private readonly stateStore!: Contracts.State.Store; + + @inject(Identifiers.Database.Service) + private readonly databaseService!: Contracts.Database.DatabaseService; + + public readonly schema = { + $id: `jsonRpc_${this.name}`, + + maxItems: 2, + minItems: 2, + + prefixItems: [ + { oneOf: [{ $ref: "prefixedHex" }, { enum: ["latest", "finalized", "safe"], type: "string" }] }, // TODO: Extract block tag + { type: "boolean" }, + ], + type: "array", + }; + + public async handle(parameters: [string, boolean]): Promise { + const height = parameters[0].startsWith("0x") ? Number.parseInt(parameters[0]) : this.stateStore.getHeight(); + const transactionObject = parameters[1]; + + const commit = await this.databaseService.getCommit(height); + + if (!commit) { + // eslint-disable-next-line unicorn/no-null + return null; + } + + return this.app.resolve(BlockResource).transform(commit.block, transactionObject); + } +} diff --git a/packages/api-evm/source/actions/index.ts b/packages/api-evm/source/actions/index.ts index ad045e221..81419f858 100644 --- a/packages/api-evm/source/actions/index.ts +++ b/packages/api-evm/source/actions/index.ts @@ -1,6 +1,7 @@ export * from "./eth-block-number.js"; export * from "./eth-call.js"; export * from "./eth-get-balance.js"; +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"; diff --git a/packages/api-evm/source/resources/block.ts b/packages/api-evm/source/resources/block.ts new file mode 100644 index 000000000..49184e664 --- /dev/null +++ b/packages/api-evm/source/resources/block.ts @@ -0,0 +1,40 @@ +import { inject, injectable } from "@mainsail/container"; +import { Contracts, Identifiers } from "@mainsail/contracts"; + +@injectable() +export class BlockResource { + @inject(Identifiers.Cryptography.Configuration) + private readonly configuration!: Contracts.Crypto.Configuration; + + public async transform(block: Contracts.Crypto.Block, transactionObject: boolean): Promise { + const blockData: Contracts.Crypto.BlockData = block.data; + + const milestone = this.configuration.getMilestone(blockData.height); + + /* eslint-disable sort-keys-fix/sort-keys-fix */ + return { + number: `0x${blockData.height.toString(16)}`, + hash: `0x${blockData.id}`, + parentHash: `0x${blockData.previousBlock}`, + nonce: "0x0", + sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad4e2a311b82e5872087ed76f0f1ccf8f", // No uncles in ARK, this is hash of empty list + logsBloom: "", // TODO: Implement logs bloom, + transactionsRoot: `0x${blockData.stateHash}`, + stateRoot: `0x${blockData.stateHash}`, + receiptsRoot: `0x${blockData.stateHash}`, + miner: blockData.generatorAddress, + difficulty: "0x0", + totalDifficulty: "0x0", + extraData: "0x", + size: `0x${blockData.payloadLength.toString(16)}`, // TODO: Implement block size + gasLimit: `0x${milestone.block.maxGasLimit.toString(16)}`, + gasUsed: `0x${blockData.totalGasUsed.toString(16)}`, + timestamp: `0x${blockData.timestamp.toString(16)}`, + transactions: transactionObject + ? block.transactions.map((transaction) => transaction.data) + : block.transactions.map((transaction) => transaction.id), + uncles: [], + }; + /* eslint-enable sort-keys-fix/sort-keys-fix */ + } +} diff --git a/packages/api-evm/source/resources/index.ts b/packages/api-evm/source/resources/index.ts new file mode 100644 index 000000000..ef890cf9e --- /dev/null +++ b/packages/api-evm/source/resources/index.ts @@ -0,0 +1 @@ +export * from "./block.js"; diff --git a/packages/api-evm/source/service-provider.ts b/packages/api-evm/source/service-provider.ts index a875fc17b..3c0171dc4 100644 --- a/packages/api-evm/source/service-provider.ts +++ b/packages/api-evm/source/service-provider.ts @@ -6,6 +6,7 @@ import { CallAction, EthBlockNumberAction, EthGetBalanceAction, + EthGetBlockByNumberAction, EthGetCodeAction, EthGetStorageAtAction, EthGetTransactionCount, @@ -65,6 +66,7 @@ export class ServiceProvider extends AbstractServiceProvider { this.app.resolve(CallAction), this.app.resolve(EthBlockNumberAction), this.app.resolve(EthGetBalanceAction), + this.app.resolve(EthGetBlockByNumberAction), this.app.resolve(EthGetCodeAction), this.app.resolve(EthGetStorageAtAction), this.app.resolve(EthGetTransactionCount), diff --git a/packages/core/bin/config/testnet/core/app.json b/packages/core/bin/config/testnet/core/app.json index 685b94114..1f57a32cc 100644 --- a/packages/core/bin/config/testnet/core/app.json +++ b/packages/core/bin/config/testnet/core/app.json @@ -200,13 +200,7 @@ "package": "@mainsail/transactions" }, { - "package": "@mainsail/state", - "options": { - "snapshots": { - "enabled": false, - "skipUnknownAttributes": true - } - } + "package": "@mainsail/state" }, { "package": "@mainsail/transaction-pool-service" @@ -258,6 +252,12 @@ { "package": "@mainsail/crypto-block" }, + { + "package": "@mainsail/crypto-messages" + }, + { + "package": "@mainsail/crypto-commit" + }, { "package": "@mainsail/crypto-transaction" }, @@ -268,13 +268,10 @@ "package": "@mainsail/transactions" }, { - "package": "@mainsail/state", - "options": { - "snapshots": { - "enabled": false, - "skipUnknownAttributes": true - } - } + "package": "@mainsail/state" + }, + { + "package": "@mainsail/database" }, { "package": "@mainsail/evm-service"