From c22c697b1e0428b923c56b275c67419751618a34 Mon Sep 17 00:00:00 2001 From: Thomas Alvarenga Date: Thu, 2 Jan 2025 11:07:42 -0300 Subject: [PATCH] Fixed all build,lint and test errors --- .env.testnet | 1 - Dockerfile | 5 +- README.md | 2 - package.json | 14 ++-- .../CollectChainMetricsUsecase.ts | 12 +-- .../GivePointsToContractCreationUsecase.ts | 84 +++++++++++++------ src/application/abi/HelloWorldAbi.ts | 80 +++++++++--------- src/domain/base/DomainError.spec.ts | 24 +++--- src/domain/base/Entity.spec.ts | 38 ++++----- src/domain/base/Entity.ts | 2 +- src/domain/base/EntityHash.spec.ts | 27 +++--- src/domain/base/EntityHash.ts | 2 +- src/domain/base/ValueObject.spec.ts | 14 ++-- src/domain/entities/Block.ts | 4 +- src/domain/entities/ChainMetrics.ts | 2 +- src/domain/entities/File.ts | 2 +- src/domain/entities/Score.ts | 2 +- src/domain/entities/Transaction.ts | 2 +- src/domain/entities/TransactionReceipt.ts | 5 +- .../repositories/ChainMetricsRepository.ts | 2 +- src/domain/repositories/ChainRepository.ts | 17 ++-- src/domain/repositories/FileRepository.ts | 2 +- src/domain/repositories/ScoreRepository.ts | 2 +- src/domain/valueObjects/Address.spec.ts | 4 - src/domain/valueObjects/BlockNumber.spec.ts | 6 +- src/domain/valueObjects/FileContent.spec.ts | 6 +- src/domain/valueObjects/Filename.spec.ts | 4 - src/domain/valueObjects/Filename.ts | 2 +- src/domain/valueObjects/Hash.spec.ts | 7 +- src/domain/valueObjects/Metric.spec.ts | 4 - src/domain/valueObjects/Uuid.spec.ts | 20 ++--- src/domain/valueObjects/Uuid.ts | 2 +- .../repositories/AbsintheScoreRepository.ts | 22 +++-- .../repositories/FsFileRepository.ts | 8 +- .../ViemChainMetricsRepository.ts | 35 ++++---- .../repositories/ViemChainRepository.ts | 59 +++++++------ src/presentation/cli/CollectMetrics.ts | 2 +- src/presentation/cli/GivePoints.ts | 9 +- tsconfig.json | 4 +- 39 files changed, 282 insertions(+), 257 deletions(-) diff --git a/.env.testnet b/.env.testnet index 5d05067..b088e86 100644 --- a/.env.testnet +++ b/.env.testnet @@ -3,5 +3,4 @@ ABSINTHE_API_KEY= ABSINTHE_EVENT_NAME= TESTNET= HOURS_INTERVAL= -BLOCK_EXPLORER_URL= METRICS_FOLDER_PATH= diff --git a/Dockerfile b/Dockerfile index 4970678..7be541f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,9 +5,12 @@ RUN mkdir -p /usr/src/app WORKDIR /usr/src/app +COPY package*.json . + +RUN npm ci --production + COPY . . -RUN npm install --production RUN npm run build CMD [ "npm", "run", "collect-metrics"] diff --git a/README.md b/README.md index d11cdf9..b0cc98c 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,6 @@ The environment variables are defined in the `.env` file. The following variable - `ABSINTHE_EVENT_NAME`: The Absinthe Event Name to send in the points requests - `TESTNET`: Boolean value to set if the scripts should run on testnet or no - `HOURS_INTERVAL`: Interval in hours to search for blocks/transactions that have smart contracts creation -- `BLOCK_EXPLORER_URL`: The Hemi Network's URL of the block explorer. - `METRICS_FOLDER_PATH`: Path to the folder to store the Website metrics(`metrics.json`) file. Example of the .env file @@ -89,7 +88,6 @@ ABSINTHE_API_KEY= ABSINTHE_EVENT_NAME= TESTNET= HOURS_INTERVAL= -BLOCK_EXPLORER_URL= METRICS_FOLDER_PATH= ``` diff --git a/package.json b/package.json index b94dd47..bbb6ec2 100644 --- a/package.json +++ b/package.json @@ -6,16 +6,16 @@ "types": "dist/index.d.ts", "private": true, "scripts": { - "lint": "eslint", - "lint:fix": "eslint --fix", - "test": "vitest run", - "test:cov": "vitest run --coverage", - "test:watch": "vitest watch", "build": "tsc -p ./tsconfig.build.json", "collect-metrics": "node dist/presentation/cli/CollectMetrics.js", - "give-points": "node ./src/presentation/cli/GivePoints.ts" + "give-points": "node ./src/presentation/cli/GivePoints.ts", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "test": "vitest run", + "test:cov": "vitest run --coverage", + "test:watch": "vitest watch" }, - "author": "Thomas Alvarenga (thomas@hemi.xyz)", + "author": "Thomas Alvarenga ", "license": "MIT", "dependencies": { "hemi-viem": "1.7.0", diff --git a/src/application/CollectChainMetrics/CollectChainMetricsUsecase.ts b/src/application/CollectChainMetrics/CollectChainMetricsUsecase.ts index 67fed7e..23d82ee 100644 --- a/src/application/CollectChainMetrics/CollectChainMetricsUsecase.ts +++ b/src/application/CollectChainMetrics/CollectChainMetricsUsecase.ts @@ -1,5 +1,7 @@ import { File } from '../../domain/entities/File' -import { ChainMetricsRepository } from '../../domain/repositories/ChainMetricsRepository' +import { + ChainMetricsRepository +} from '../../domain/repositories/ChainMetricsRepository' import { FileRepository } from '../../domain/repositories/FileRepository' import { FileContent } from '../../domain/valueObjects/FileContent' import { Filename } from '../../domain/valueObjects/Filename' @@ -17,17 +19,17 @@ export class CollectChainMetricsUsecase { } async execute(): Promise { - console.info(`Hemi Connector | Collecting chain metrics...`) + console.info('Hemi Connector | Collecting chain metrics...') const metrics = await this.chainMetricsRepository.collect() - console.info(`Hemi Connector | Creating metrics.json file`) - + console.info('Hemi Connector | Creating metrics.json file') + const file = this.createFile(metrics.toString()) await this.fileRepository.save(file) - console.info(`Hemi Connector | Metrics file created with success!`) + console.info('Hemi Connector | Metrics file created with success!') } private createFile(content: string): File { diff --git a/src/application/GivePointsToContractCreation/GivePointsToContractCreationUsecase.ts b/src/application/GivePointsToContractCreation/GivePointsToContractCreationUsecase.ts index 7a49ab8..0d4a1c2 100644 --- a/src/application/GivePointsToContractCreation/GivePointsToContractCreationUsecase.ts +++ b/src/application/GivePointsToContractCreation/GivePointsToContractCreationUsecase.ts @@ -1,5 +1,6 @@ import { Score } from '../../domain/entities/Score' import { Transaction } from '../../domain/entities/Transaction' +import { TransactionReceipt } from '../../domain/entities/TransactionReceipt' import { ChainRepository } from '../../domain/repositories/ChainRepository' import { ScoreRepository } from '../../domain/repositories/ScoreRepository' import { Address } from '../../domain/valueObjects/Address' @@ -24,23 +25,37 @@ export class GivePointsToContractCreationUsecase { async execute({ hours }: GivePointsToContractCreationDto): Promise { - console.info(`Hemi Connector | Searching for smart contracts created on the last ${hours} hours`) + console.info(`\ + Hemi Connector | \ + Searching for smart contracts created on the last ${hours} hours` + ) - const blockDiff = BigInt((hours * 60 * 60) / 12) // X hours worth of Hemi blocks + const blockDiff = + BigInt((hours * 60 * 60) / 12) // X hours worth of Hemi blocks const blockNumber = await this.chainRepository.getBlockNumber() const toBlock = blockNumber.value const fromBlock = toBlock - blockDiff - for (let currentBlock = fromBlock; currentBlock <= toBlock; currentBlock += BigInt(1)) { - console.info(`--------------------------------------------------------`) - console.info(`Hemi Connector | Current block number: ${currentBlock}`) + for ( + let currentBlock = fromBlock; + currentBlock <= toBlock; + currentBlock += BigInt(1) + ) { + console.info(`\ + -------------------------------------------------------- + Hemi Connector | \ + Current block number: ${currentBlock}` + ) const contractCreationTxs = await this.getContractCreationTransactions(currentBlock) - console.info(`Hemi Connector | ${contractCreationTxs.length} contract creation transactions found`) + console.info(`\ + Hemi Connector | \ + ${contractCreationTxs.length} contract creation transactions found` + ) - await this.checkTransactionsToEarnPoints(contractCreationTxs) + await this.checkTransactionsToEarnPoints(contractCreationTxs) } } @@ -62,22 +77,33 @@ export class GivePointsToContractCreationUsecase { transactions: Transaction[] ): Promise { for (const transaction of transactions) { - const receipt = + const receipt = await this.chainRepository.getTransactionReceipt(transaction.hash) - - if (receipt && receipt.contractAddress) { - const isHelloWorldContract = - await this.validateHelloWorldContract(receipt.contractAddress) - - if (isHelloWorldContract) { - console.info(`Hemi Connector | ${transaction.from.value} created a Hello World smart contract`) - await this.givePointsToTransaction(transaction) - } + const isHelloWorldContract = await this.isHelloWorldContract(receipt) + + if (isHelloWorldContract) { + console.info(`\ + Hemi Connector | \ + ${transaction.from.value} created a Hello World smart contract` + ) + await this.givePointsToTransaction(transaction) } } } - private async validateHelloWorldContract(contractAddress: Address): Promise { + private async isHelloWorldContract( + receipt: TransactionReceipt | null + ): Promise { + if (!receipt?.contractAddress) { + return false + } + + return await this.validateHelloWorldContract(receipt.contractAddress) + } + + private async validateHelloWorldContract( + contractAddress: Address + ): Promise { try { await this.chainRepository.callContractMethod( contractAddress, @@ -85,13 +111,14 @@ export class GivePointsToContractCreationUsecase { HelloWorldAbi ) return true - } - catch (error) { + } catch (error) { return false } } - private async givePointsToTransaction(transaction: Transaction): Promise { + private async givePointsToTransaction( + transaction: Transaction + ): Promise { const amount = 500 try { @@ -99,12 +126,17 @@ export class GivePointsToContractCreationUsecase { address: transaction.from, amount }, transaction.hash) - + await this.scoreRepository.givePoints(score) - console.info(`Hemi Connector | ${transaction.from.value} received ${amount} points on Absinthe`) - } - catch (error) { - console.error(`Hemi Connector | Error giving points to ${transaction.from.value}: ${error}`) + console.info(`\ + Hemi Connector | \ + ${transaction.from.value} received ${amount} points on Absinthe` + ) + } catch (error) { + console.error(`\ + Hemi Connector | \ + Error giving points to ${transaction.from.value}`, error + ) } } } diff --git a/src/application/abi/HelloWorldAbi.ts b/src/application/abi/HelloWorldAbi.ts index dc6404a..b225455 100644 --- a/src/application/abi/HelloWorldAbi.ts +++ b/src/application/abi/HelloWorldAbi.ts @@ -1,41 +1,41 @@ export const HelloWorldAbi = [ - { - "inputs": [], - "name": "getGreeting", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "greeting", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_greeting", - "type": "string" - } - ], - "name": "setGreeting", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -]; + { + inputs: [], + name: 'getGreeting', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string' + } + ], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'greeting', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string' + } + ], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [ + { + internalType: 'string', + name: '_greeting', + type: 'string' + } + ], + name: 'setGreeting', + outputs: [], + stateMutability: 'nonpayable', + type: 'function' + } +] diff --git a/src/domain/base/DomainError.spec.ts b/src/domain/base/DomainError.spec.ts index 254f0ff..b447434 100644 --- a/src/domain/base/DomainError.spec.ts +++ b/src/domain/base/DomainError.spec.ts @@ -1,26 +1,22 @@ -import { describe, it, expect } from "vitest" -import { DomainError } from "./DomainError" +import { describe, it, expect } from 'vitest' +import { DomainError } from './DomainError' -describe("src/domain/DomainError", () => { - it("should be defined", () => { - expect(DomainError).toBeDefined() +describe('src/domain/DomainError', () => { + it('should be instance of Error', () => { + expect(new DomainError('TEST_ERROR')).toBeInstanceOf(Error) }) - it("should be instance of Error", () => { - expect(new DomainError("TEST_ERROR")).toBeInstanceOf(Error) - }) - - describe("constructor", () => { - it("should accept a code parameter", () => { - const errorCode = "TEST_ERROR" + describe('constructor', () => { + it('should accept a code parameter', () => { + const errorCode = 'TEST_ERROR' const domainError = new DomainError(errorCode) expect(domainError.toObject().code).toBe(errorCode) }) - it("should accept a exposable parameter", () => { + it('should accept a exposable parameter', () => { const exposable = true - const domainError = new DomainError("TEST_ERROR", exposable) + const domainError = new DomainError('TEST_ERROR', exposable) expect(domainError.toObject().exposable).toBe(exposable) }) diff --git a/src/domain/base/Entity.spec.ts b/src/domain/base/Entity.spec.ts index 5bcfdb8..c16435f 100644 --- a/src/domain/base/Entity.spec.ts +++ b/src/domain/base/Entity.spec.ts @@ -1,15 +1,15 @@ -import { describe, it, expect } from "vitest" -import { Entity } from "./EntityHash" -import { ValueObject } from "./ValueObject" -import { Hash } from '../valueObjects/Hash' +import { describe, it, expect } from 'vitest' +import { Entity } from './Entity' +import { ValueObject } from './ValueObject' +import { Uuid } from '../valueObjects/Uuid' interface TestProps { value: string } class TestEntity extends Entity { - static create(props: TestProps, hash: Hash): TestEntity { - return new TestEntity(props, hash) + static create(props: TestProps, id: Uuid): TestEntity { + return new TestEntity(props, id) } get value(): string { @@ -17,29 +17,25 @@ class TestEntity extends Entity { } } -const hash = Hash.create('0x7304dc174aab2bc487b1befb9e35ba3632b9693f0c0548e138b4401f263910f1') +const id = Uuid.create() -describe("src/domain/Entity", () => { - it("should be defined", () => { - expect(Entity).toBeDefined() - }) - - it("should be instance of ValueObject", () => { - const entity = TestEntity.create({ value: "test" }, hash) +describe('src/domain/Entity', () => { + it('should be instance of ValueObject', () => { + const entity = TestEntity.create({ value: 'test' }, id) expect(entity).toBeInstanceOf(ValueObject) }) - it("should generate a new hash if none is passed to constructor", () => { - const entity = TestEntity.create({ value: "test" }, hash) + it('should generate a new id if none is passed to constructor', () => { + const entity = TestEntity.create({ value: 'test' }, id) - expect(entity.hash).toBeDefined() + expect(entity.id).toBeDefined() }) - it("should set the hash if it was passed to constructor", () => { - const expectedId = hash - const entity = TestEntity.create({ value: "test" }, expectedId) + it('should set the id if it was passed to constructor', () => { + const expectedId = id + const entity = TestEntity.create({ value: 'test' }, expectedId) - expect(entity.hash).toBe(expectedId) + expect(entity.id).toBe(expectedId) }) }) diff --git a/src/domain/base/Entity.ts b/src/domain/base/Entity.ts index 153cab8..ce5c4cb 100644 --- a/src/domain/base/Entity.ts +++ b/src/domain/base/Entity.ts @@ -1,5 +1,5 @@ import { Uuid } from '../valueObjects/Uuid' -import { ValueObject } from "./ValueObject" +import { ValueObject } from './ValueObject' export class Entity extends ValueObject { id: Uuid diff --git a/src/domain/base/EntityHash.spec.ts b/src/domain/base/EntityHash.spec.ts index 2318e94..6fe7a33 100644 --- a/src/domain/base/EntityHash.spec.ts +++ b/src/domain/base/EntityHash.spec.ts @@ -1,6 +1,6 @@ -import { describe, it, expect } from "vitest" -import { EntityHash } from "./EntityHash" -import { ValueObject } from "./ValueObject" +import { describe, it, expect } from 'vitest' +import { EntityHash } from './EntityHash' +import { ValueObject } from './ValueObject' import { Hash } from '../valueObjects/Hash' interface TestProps { @@ -17,28 +17,25 @@ class TestEntityHash extends EntityHash { } } -const hash = Hash.create('0x7304dc174aab2bc487b1befb9e35ba3632b9693f0c0548e138b4401f263910f1') +const hash = Hash + .create('0x7304dc174aab2bc487b1befb9e35ba3632b9693f0c0548e138b4401f263910f1') -describe("src/domain/EntityHash", () => { - it("should be defined", () => { - expect(EntityHash).toBeDefined() - }) - - it("should be instance of ValueObject", () => { - const entity = TestEntityHash.create({ value: "test" }, hash) +describe('src/domain/EntityHash', () => { + it('should be instance of ValueObject', () => { + const entity = TestEntityHash.create({ value: 'test' }, hash) expect(entity).toBeInstanceOf(ValueObject) }) - it("should generate a new hash if none is passed to constructor", () => { - const entity = TestEntityHash.create({ value: "test" }, hash) + it('should generate a new hash if none is passed to constructor', () => { + const entity = TestEntityHash.create({ value: 'test' }, hash) expect(entity.hash).toBeDefined() }) - it("should set the hash if it was passed to constructor", () => { + it('should set the hash if it was passed to constructor', () => { const expectedId = hash - const entity = TestEntityHash.create({ value: "test" }, expectedId) + const entity = TestEntityHash.create({ value: 'test' }, expectedId) expect(entity.hash).toBe(expectedId) }) diff --git a/src/domain/base/EntityHash.ts b/src/domain/base/EntityHash.ts index ab5ddb0..d13b672 100644 --- a/src/domain/base/EntityHash.ts +++ b/src/domain/base/EntityHash.ts @@ -1,5 +1,5 @@ import { Hash } from '../valueObjects/Hash' -import { ValueObject } from "./ValueObject" +import { ValueObject } from './ValueObject' export class EntityHash extends ValueObject { hash: Hash diff --git a/src/domain/base/ValueObject.spec.ts b/src/domain/base/ValueObject.spec.ts index 7630d50..59e0086 100644 --- a/src/domain/base/ValueObject.spec.ts +++ b/src/domain/base/ValueObject.spec.ts @@ -1,5 +1,5 @@ -import { describe, it, expect } from "vitest" -import { ValueObject } from "./ValueObject" +import { describe, it, expect } from 'vitest' +import { ValueObject } from './ValueObject' interface TestProps { value: string @@ -15,13 +15,9 @@ class TestValueObject extends ValueObject { } } -describe("src/domain/ValueObject", () => { - it("should be defined", () => { - expect(ValueObject).toBeDefined() - }) - - it("should set props attribute from the constructor", () => { - const expectedProps = { value: "test" } +describe('src/domain/ValueObject', () => { + it('should set props attribute from the constructor', () => { + const expectedProps = { value: 'test' } const entity = TestValueObject.create(expectedProps) expect(entity.value).toStrictEqual(expectedProps.value) diff --git a/src/domain/entities/Block.ts b/src/domain/entities/Block.ts index 671670c..b63dfe1 100644 --- a/src/domain/entities/Block.ts +++ b/src/domain/entities/Block.ts @@ -5,7 +5,7 @@ import { BlockNumber } from '../valueObjects/BlockNumber' interface BlockProps { blockNumber: BlockNumber - transactions: Array + transactions: Transaction[] } export class Block extends EntityHash { @@ -17,7 +17,7 @@ export class Block extends EntityHash { return new Block(props, hash) } - get transactions(): Array { + get transactions(): Transaction[] { return this.props.transactions } } diff --git a/src/domain/entities/ChainMetrics.ts b/src/domain/entities/ChainMetrics.ts index 2638596..f4c0c67 100644 --- a/src/domain/entities/ChainMetrics.ts +++ b/src/domain/entities/ChainMetrics.ts @@ -16,7 +16,7 @@ export class ChainMetrics extends Entity { static create(props: ChainMetricsProps): ChainMetrics { return new ChainMetrics(props) } - + get btcSecuredTransactions(): number { return this.props.btcSecuredTransactions.value } diff --git a/src/domain/entities/File.ts b/src/domain/entities/File.ts index e101ae3..8846e73 100644 --- a/src/domain/entities/File.ts +++ b/src/domain/entities/File.ts @@ -16,7 +16,7 @@ export class File extends Entity { static create(props: FileProps): File { return new File(props) } - + get name(): string { return this.props.name.value } diff --git a/src/domain/entities/Score.ts b/src/domain/entities/Score.ts index 57762a0..769ee6f 100644 --- a/src/domain/entities/Score.ts +++ b/src/domain/entities/Score.ts @@ -15,7 +15,7 @@ export class Score extends EntityHash { static create(props: ScoreProps, hash: Hash): Score { return new Score(props, hash) } - + get address(): Address { return this.props.address } diff --git a/src/domain/entities/Transaction.ts b/src/domain/entities/Transaction.ts index 786877a..68ee4e0 100644 --- a/src/domain/entities/Transaction.ts +++ b/src/domain/entities/Transaction.ts @@ -5,7 +5,7 @@ import { Hash } from '../valueObjects/Hash' interface TransactionProps { blockHash: Hash from: Address - to?: Address | undefined + to?: Address | undefined } export class Transaction extends EntityHash { diff --git a/src/domain/entities/TransactionReceipt.ts b/src/domain/entities/TransactionReceipt.ts index b739436..e7e8564 100644 --- a/src/domain/entities/TransactionReceipt.ts +++ b/src/domain/entities/TransactionReceipt.ts @@ -11,7 +11,10 @@ export class TransactionReceipt extends EntityHash { super(props, hash) } - static create(props: TransactionReceiptProps, hash: Hash): TransactionReceipt { + static create( + props: TransactionReceiptProps, + hash: Hash + ): TransactionReceipt { return new TransactionReceipt(props, hash) } diff --git a/src/domain/repositories/ChainMetricsRepository.ts b/src/domain/repositories/ChainMetricsRepository.ts index a96ceec..2a22f5f 100644 --- a/src/domain/repositories/ChainMetricsRepository.ts +++ b/src/domain/repositories/ChainMetricsRepository.ts @@ -1,5 +1,5 @@ import { ChainMetrics } from '../entities/ChainMetrics' export interface ChainMetricsRepository { - collect(): Promise + collect: () => Promise } diff --git a/src/domain/repositories/ChainRepository.ts b/src/domain/repositories/ChainRepository.ts index 7a884c4..33b1d53 100644 --- a/src/domain/repositories/ChainRepository.ts +++ b/src/domain/repositories/ChainRepository.ts @@ -5,13 +5,18 @@ import { BlockNumber } from '../valueObjects/BlockNumber' import { Hash } from '../valueObjects/Hash' export interface ChainRepository { - getBlockNumber(): Promise - getBlock(blockNumber: BlockNumber, includeTransactions: boolean): Promise - getTransactionReceipt(transactionHash: Hash): Promise - callContractMethod( + getBlockNumber: () => Promise + getBlock: ( + blockNumber: BlockNumber, + includeTransactions: boolean + ) => Promise + getTransactionReceipt: ( + transactionHash: Hash + ) => Promise + callContractMethod: ( address: Address, methodName: string, - abi: unknown, + abi: unknown, ...inputs: any[] - ): Promise + ) => Promise } diff --git a/src/domain/repositories/FileRepository.ts b/src/domain/repositories/FileRepository.ts index 84a3bc2..89ec37e 100644 --- a/src/domain/repositories/FileRepository.ts +++ b/src/domain/repositories/FileRepository.ts @@ -1,5 +1,5 @@ import { File } from '../entities/File' export interface FileRepository { - save(file: File): Promise + save: (file: File) => Promise } diff --git a/src/domain/repositories/ScoreRepository.ts b/src/domain/repositories/ScoreRepository.ts index 57065b6..8ade1d0 100644 --- a/src/domain/repositories/ScoreRepository.ts +++ b/src/domain/repositories/ScoreRepository.ts @@ -1,5 +1,5 @@ import { Score } from '../entities/Score' export interface ScoreRepository { - givePoints(score: Score): Promise + givePoints: (score: Score) => Promise } diff --git a/src/domain/valueObjects/Address.spec.ts b/src/domain/valueObjects/Address.spec.ts index 450426a..b753760 100644 --- a/src/domain/valueObjects/Address.spec.ts +++ b/src/domain/valueObjects/Address.spec.ts @@ -6,10 +6,6 @@ import { ValueObject } from '../base/ValueObject' describe('src/domain/valueObjects/Address', () => { const validAddress = '0x52908400098527886E0F7030069857D2E4169EE7' - it('should be defined', () => { - expect(Address).toBeDefined() - }) - it('should be an instance of ValueObject', () => { const address = Address.create(validAddress) diff --git a/src/domain/valueObjects/BlockNumber.spec.ts b/src/domain/valueObjects/BlockNumber.spec.ts index 9571da1..d854cdd 100644 --- a/src/domain/valueObjects/BlockNumber.spec.ts +++ b/src/domain/valueObjects/BlockNumber.spec.ts @@ -6,10 +6,6 @@ import { InvalidBlockNumberError } from '../errors/InvalidBlockNumberError' describe('src/domain/valueObjects/BlockNumber', () => { const validBlockNumber = BigInt(1857202) - it('should be defined', () => { - expect(BlockNumber).toBeDefined() - }) - it('should be an instance of ValueObject', () => { const blockNumber = BlockNumber.create(validBlockNumber) @@ -35,7 +31,7 @@ describe('src/domain/valueObjects/BlockNumber', () => { expect(test).toThrowError(InvalidBlockNumberError) }) - it('should return a new BlockNumber instance if the blockNumber is valid', () => { + it('should return new BlockNumber instance if blockNumber is valid', () => { const blockNumber = BlockNumber.create(validBlockNumber) expect(blockNumber).toBeInstanceOf(BlockNumber) diff --git a/src/domain/valueObjects/FileContent.spec.ts b/src/domain/valueObjects/FileContent.spec.ts index 2a1eab8..281ff0b 100644 --- a/src/domain/valueObjects/FileContent.spec.ts +++ b/src/domain/valueObjects/FileContent.spec.ts @@ -8,10 +8,6 @@ describe('src/domain/valueObjects/FileContent', () => { test: 'value' }) - it('should be defined', () => { - expect(FileContent).toBeDefined() - }) - it('should be an instance of ValueObject', () => { const content = FileContent.create(validFileContent) @@ -36,7 +32,7 @@ describe('src/domain/valueObjects/FileContent', () => { expect(test).toThrowError(InvalidFileContentError) }) - it('should return a new FileContent instance if the content is valid', () => { + it('should return a new FileContent instance if content is valid', () => { const content = FileContent.create(validFileContent) expect(content).toBeInstanceOf(FileContent) diff --git a/src/domain/valueObjects/Filename.spec.ts b/src/domain/valueObjects/Filename.spec.ts index 761ff5a..b9c1290 100644 --- a/src/domain/valueObjects/Filename.spec.ts +++ b/src/domain/valueObjects/Filename.spec.ts @@ -6,10 +6,6 @@ import { InvalidFilenameError } from '../errors/InvalidFilenameError' describe('src/domain/valueObjects/Filename', () => { const validFilename = 'metrics.json' - it('should be defined', () => { - expect(Filename).toBeDefined() - }) - it('should be an instance of ValueObject', () => { const filename = Filename.create(validFilename) diff --git a/src/domain/valueObjects/Filename.ts b/src/domain/valueObjects/Filename.ts index 22b64a8..3b6a586 100644 --- a/src/domain/valueObjects/Filename.ts +++ b/src/domain/valueObjects/Filename.ts @@ -5,7 +5,7 @@ interface FilenameProps { value: string } -const filenameRegex = /^[^.][A-z0-9\-\_\.]+[^.]$/ +const filenameRegex = /^[^.][A-Za-z0-9\-\\_\\.]+[^.]$/ export class Filename extends ValueObject { private constructor(filename: string) { diff --git a/src/domain/valueObjects/Hash.spec.ts b/src/domain/valueObjects/Hash.spec.ts index 770b763..e1af9e5 100644 --- a/src/domain/valueObjects/Hash.spec.ts +++ b/src/domain/valueObjects/Hash.spec.ts @@ -4,11 +4,8 @@ import { ValueObject } from '../base/ValueObject' import { InvalidHashError } from '../errors/InvalidHashError' describe('src/domain/valueObjects/Hash', () => { - const validHash = '0x7304dc174aab2bc487b1befb9e35ba3632b9693f0c0548e138b4401f263910f1' - - it('should be defined', () => { - expect(Hash).toBeDefined() - }) + const validHash = + '0x7304dc174aab2bc487b1befb9e35ba3632b9693f0c0548e138b4401f263910f1' it('should be an instance of ValueObject', () => { const hash = Hash.create(validHash) diff --git a/src/domain/valueObjects/Metric.spec.ts b/src/domain/valueObjects/Metric.spec.ts index a110c63..2c70c9d 100644 --- a/src/domain/valueObjects/Metric.spec.ts +++ b/src/domain/valueObjects/Metric.spec.ts @@ -6,10 +6,6 @@ import { InvalidMetricError } from '../errors/InvalidMetricError' describe('src/domain/valueObjects/Metric', () => { const validMetric = 1857202 - it('should be defined', () => { - expect(Metric).toBeDefined() - }) - it('should be an instance of ValueObject', () => { const metric = Metric.create(validMetric) diff --git a/src/domain/valueObjects/Uuid.spec.ts b/src/domain/valueObjects/Uuid.spec.ts index 31d8530..7a4486a 100644 --- a/src/domain/valueObjects/Uuid.spec.ts +++ b/src/domain/valueObjects/Uuid.spec.ts @@ -5,12 +5,8 @@ import { Uuid } from './Uuid' import { ValueObject } from '../base/ValueObject' describe('src/domain/valueObjects/Uuid', () => { - it('should be defined', () => { - expect(Uuid).toBeDefined() - }) - it('should be instance of ValueObject', () => { - expect(Uuid.create()).toBeInstanceOf(ValueObject) + expect(Uuid.create()).toBeInstanceOf(ValueObject) }) describe('create', () => { @@ -19,8 +15,8 @@ describe('src/domain/valueObjects/Uuid', () => { const uuid = Uuid.create() expect(validate(uuid.value)).toBeTruthy() - }); - }); + }) + }) describe('when a valid id is provided', () => { it('should set the id as value', () => { @@ -28,18 +24,18 @@ describe('src/domain/valueObjects/Uuid', () => { const uuid = Uuid.create(validId) expect(uuid.value).toEqual(validId) - }); - }); + }) + }) describe('when an invalid id is provided', () => { it('should set the id as value', () => { const invalidId = 'invalid-id' - const test = () => { + const test = (): void => { Uuid.create(invalidId) } expect(test).toThrowError(InvalidUuidError) - }); - }); + }) + }) }) }) diff --git a/src/domain/valueObjects/Uuid.ts b/src/domain/valueObjects/Uuid.ts index 3077244..8970417 100644 --- a/src/domain/valueObjects/Uuid.ts +++ b/src/domain/valueObjects/Uuid.ts @@ -15,7 +15,7 @@ export class Uuid extends ValueObject { throw new InvalidUuidError() } - return new Uuid(id || v4()) + return new Uuid(id ?? v4()) } get value(): string { diff --git a/src/infrastructure/repositories/AbsintheScoreRepository.ts b/src/infrastructure/repositories/AbsintheScoreRepository.ts index 2511635..d45db33 100644 --- a/src/infrastructure/repositories/AbsintheScoreRepository.ts +++ b/src/infrastructure/repositories/AbsintheScoreRepository.ts @@ -1,5 +1,5 @@ -import { Score } from '../../domain/entities/Score'; -import { ScoreRepository } from '../../domain/repositories/ScoreRepository'; +import { Score } from '../../domain/entities/Score' +import { ScoreRepository } from '../../domain/repositories/ScoreRepository' export class AbsintheScoreRepository implements ScoreRepository { url: string @@ -11,18 +11,26 @@ export class AbsintheScoreRepository implements ScoreRepository { this.headers.append( 'Authorization', - `Bearer ${process.env['ABSINTHE_API_KEY']}` + `Bearer ${process.env['ABSINTHE_API_KEY'] ?? ''}` ) this.headers.append('Content-Type', 'application/json') - this.url = process.env['ABSINTHE_API_URL'] || '' - this.eventName = process.env['ABSINTHE_EVENT_NAME'] || '' + this.url = process.env['ABSINTHE_API_URL'] ?? '' + this.eventName = process.env['ABSINTHE_EVENT_NAME'] ?? '' } async givePoints(score: Score): Promise { const graphql = JSON.stringify({ query: `mutation IssueOffChainPoints { - insert_api_points_one(object: {account_id: ${score.address.value}, identity_type: EVM_ADDRESS, amount: ${score.amount}, metadata: {transaction: ${score.hash.value}}}) { + insert_api_points_one( + object: { + account_id: ${score.address.value}, + identity_type: EVM_ADDRESS, + amount: ${score.amount}, + metadata: { + transaction: ${score.hash.value} + } + }) { id amount added_by @@ -34,7 +42,7 @@ export class AbsintheScoreRepository implements ScoreRepository { await fetch(this.url, { body: graphql, headers: this.headers, - method: "POST", + method: 'POST' }) } } diff --git a/src/infrastructure/repositories/FsFileRepository.ts b/src/infrastructure/repositories/FsFileRepository.ts index c838715..302c42b 100644 --- a/src/infrastructure/repositories/FsFileRepository.ts +++ b/src/infrastructure/repositories/FsFileRepository.ts @@ -4,16 +4,16 @@ import { FileRepository } from '../../domain/repositories/FileRepository' import { File } from '../../domain/entities/File' export class FsFileRepository implements FileRepository { - private folderPath: string + private readonly folderPath: string constructor() { - this.folderPath = process.env['METRICS_FOLDER_PATH'] || '' + this.folderPath = process.env['METRICS_FOLDER_PATH'] ?? '' } - save(file: File): Promise { + async save(file: File): Promise { const { name, content } = file - return fs.writeFile( + return await fs.writeFile( path.join(this.folderPath, name), content ) diff --git a/src/infrastructure/repositories/ViemChainMetricsRepository.ts b/src/infrastructure/repositories/ViemChainMetricsRepository.ts index da9a104..d2baca7 100644 --- a/src/infrastructure/repositories/ViemChainMetricsRepository.ts +++ b/src/infrastructure/repositories/ViemChainMetricsRepository.ts @@ -2,33 +2,36 @@ import { createPublicClient, http, PublicClient -} from "viem" -// @ts-ignore -import { hemiSepolia, hemi } from "hemi-viem" -// @ts-ignore -import { Hash } from '../../domain/valueObjects/Hash' -import { ChainMetricsRepository } from '../../domain/repositories/ChainMetricsRepository' +} from 'viem' +import { hemiSepolia, hemi } from 'hemi-viem' +import { + ChainMetricsRepository +} from '../../domain/repositories/ChainMetricsRepository' import { ChainMetrics } from '../../domain/entities/ChainMetrics' import { BlockNumber } from '../../domain/valueObjects/BlockNumber' import { Metric } from '../../domain/valueObjects/Metric' export class ViemChainMetricsRepository implements ChainMetricsRepository { - private client: PublicClient - private blockExplorerUrl: string + private readonly client: PublicClient + private readonly blockExplorerUrl: string constructor() { - const chain = !!process.env['TESTNET'] ? hemiSepolia : hemi - + const chain = process.env['TESTNET'] ? hemiSepolia : hemi + // @ts-expect-error + // TS don't recognize PublicClient type as createPublicClient return type this.client = createPublicClient({ chain, transport: http() }) - this.blockExplorerUrl = process.env['BLOCK_EXPLORER_URL'] || '' + this.blockExplorerUrl = chain.blockExplorers.default.url } async collect(): Promise { - const blockNumber = await this.client.getBlockNumber() - - const response = await fetch(`${this.blockExplorerUrl}/api/v2/stats`) - const stats = await response.json() + const [blockNumber, stats] = await Promise.all([ + this.client.getBlockNumber(), + fetch( + `${this.blockExplorerUrl}/api/v2/stats`) + .then(async response => await response.json()) + ]) + const totalTransactions = parseInt(stats.total_transactions) return ChainMetrics.create({ @@ -36,4 +39,4 @@ export class ViemChainMetricsRepository implements ChainMetricsRepository { btcSecuredTransactions: Metric.create(totalTransactions) }) } -} +} diff --git a/src/infrastructure/repositories/ViemChainRepository.ts b/src/infrastructure/repositories/ViemChainRepository.ts index 20db9d6..95c1046 100644 --- a/src/infrastructure/repositories/ViemChainRepository.ts +++ b/src/infrastructure/repositories/ViemChainRepository.ts @@ -5,11 +5,9 @@ import { PublicClient, Block as ViemBlock, Transaction as ViemTransaction, - TransactionReceipt as ViemTransactionReceipt, -} from "viem" -// @ts-ignore -import { hemiSepolia, hemi } from "hemi-viem" -// @ts-ignore + TransactionReceipt as ViemTransactionReceipt +} from 'viem' +import { hemiSepolia, hemi } from 'hemi-viem' import { Hash } from '../../domain/valueObjects/Hash' import { Address } from '../../domain/valueObjects/Address' import { Transaction } from '../../domain/entities/Transaction' @@ -18,10 +16,10 @@ import { Block } from '../../domain/entities/Block' import { TransactionReceipt } from '../../domain/entities/TransactionReceipt' export class ViemChainRepository implements ChainRepository { - private client: PublicClient + private readonly client: PublicClient constructor() { - const chain = !!process.env['TESTNET'] ? hemiSepolia : hemi + const chain = process.env['TESTNET'] ? hemiSepolia : hemi // @ts-expect-error this.client = createPublicClient({ chain, transport: http() }) } @@ -33,7 +31,10 @@ export class ViemChainRepository implements ChainRepository { return BlockNumber.create(blockNumber) } - async getBlock(blockNumber: BlockNumber, includeTransactions: boolean): Promise { + async getBlock( + blockNumber: BlockNumber, + includeTransactions: boolean + ): Promise { const block = await this.client.getBlock({ blockNumber: blockNumber.value, includeTransactions @@ -42,12 +43,13 @@ export class ViemChainRepository implements ChainRepository { return this.getEntityFromBlock(block) } - async getTransactionReceipt(transactionHash: Hash): Promise { + async getTransactionReceipt( + transactionHash: Hash + ): Promise { const receipt = await this.client - // @ts-ignore + // @ts-expect-error .getTransactionReceipt({ hash: transactionHash.value }) - if (receipt.contractAddress) { return this.getEntityFromTransactionReceipt(receipt) } @@ -55,10 +57,11 @@ export class ViemChainRepository implements ChainRepository { return this.getEntityFromTransactionReceipt(receipt) } + // eslint-disable-next-line max-params async callContractMethod( address: Address, methodName: string, - abi: unknown, + abi: unknown, ...inputs: any[] ): Promise { return await this.client.readContract({ @@ -71,13 +74,20 @@ export class ViemChainRepository implements ChainRepository { }) } - async listContractCreationTransactionsByHour(hours: number): Promise { - const result: Array = [] - const blockDiff = BigInt((hours * 60 * 60) / 12) // X hours worth of Hemi blocks + async listContractCreationTransactionsByHour( + hours: number + ): Promise { + const result: Transaction[] = [] + const blockDiff = + BigInt((hours * 60 * 60) / 12) // X hours worth of Hemi blocks const toBlock = await this.client.getBlockNumber() const fromBlock = toBlock - blockDiff - for (let currentBlock = fromBlock; currentBlock <= toBlock; currentBlock += BigInt(1)) { + for ( + let currentBlock = fromBlock; + currentBlock <= toBlock; + currentBlock += BigInt(1) + ) { const blockTransactions = await this.getContractCreationTransactionsByBlock(currentBlock) @@ -87,32 +97,33 @@ export class ViemChainRepository implements ChainRepository { result.push(...transactions) } - } return result } - private async getContractCreationTransactionsByBlock(blockNumber: bigint) { + private async getContractCreationTransactionsByBlock( + blockNumber: bigint + ): Promise { const block = await this.client.getBlock({ blockNumber, includeTransactions: true - }); + }) return block.transactions.filter(t => t.to == null) } private getEntityFromBlock(block: ViemBlock): Block { let transactions: Transaction[] = [] - + if (block.transactions.length > 0) { transactions = block.transactions - // @ts-ignore + // @ts-expect-error .map(t => this.getEntityFromTransaction(t)) } return Block.create({ - // @ts-ignore + // @ts-expect-error blockNumber: BlockNumber.create(block.number), transactions }, Hash.create(block.hash as string)) @@ -121,7 +132,7 @@ export class ViemChainRepository implements ChainRepository { private getEntityFromTransaction( transaction: ViemTransaction ): Transaction { - const to = transaction.to + const to = transaction.to ? Address.create(transaction.to as string) : undefined @@ -139,4 +150,4 @@ export class ViemChainRepository implements ChainRepository { contractAddress: Address.create(receipt.contractAddress as string) }, Hash.create(receipt.transactionHash)) } -} +} diff --git a/src/presentation/cli/CollectMetrics.ts b/src/presentation/cli/CollectMetrics.ts index 46fe7eb..0c4592f 100644 --- a/src/presentation/cli/CollectMetrics.ts +++ b/src/presentation/cli/CollectMetrics.ts @@ -16,4 +16,4 @@ const collectChainMetricsUsecase = new CollectChainMetricsUsecase( fileRepository ) -collectChainMetricsUsecase.execute() +void collectChainMetricsUsecase.execute() diff --git a/src/presentation/cli/GivePoints.ts b/src/presentation/cli/GivePoints.ts index daa4737..c037a45 100644 --- a/src/presentation/cli/GivePoints.ts +++ b/src/presentation/cli/GivePoints.ts @@ -1,4 +1,7 @@ -import { GivePointsToContractCreationUsecase } from '../../application/GivePointsToContractCreation/GivePointsToContractCreationUsecase' +import { + GivePointsToContractCreationUsecase +// eslint-disable-next-line max-len +} from '../../application/GivePointsToContractCreation/GivePointsToContractCreationUsecase' import { AbsintheScoreRepository } from '../../infrastructure/repositories/AbsintheScoreRepository' @@ -9,11 +12,11 @@ import { const chainRepository = new ViemChainRepository() const scoreRepository = new AbsintheScoreRepository() -const hours = parseInt(process.env['HOURS_INTERVAL'] || '') +const hours = parseInt(process.env['HOURS_INTERVAL'] ?? '') const givePointsUsecase = new GivePointsToContractCreationUsecase( chainRepository, scoreRepository ) -givePointsUsecase.execute({ hours }) +void givePointsUsecase.execute({ hours }) diff --git a/tsconfig.json b/tsconfig.json index fc3ad0f..695bc2f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,7 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "target": "ES2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ @@ -40,7 +40,7 @@ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ /* JavaScript Support */ - "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + "allowJs": false, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */