Skip to content

Commit

Permalink
Merge branch 'main' into add-transaction-error
Browse files Browse the repository at this point in the history
  • Loading branch information
Romsters authored Dec 5, 2023
2 parents 7cbe178 + bb89707 commit a42d8e5
Show file tree
Hide file tree
Showing 29 changed files with 381 additions and 122 deletions.
4 changes: 2 additions & 2 deletions packages/api/src/api/account/account.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { mock } from "jest-mock-extended";
import { BadRequestException, Logger } from "@nestjs/common";
import { L2_ETH_TOKEN_ADDRESS } from "../../common/constants";
import { BlockService } from "../../block/block.service";
import { BlockDetail } from "../../block/blockDetail.entity";
import { BlockDetails } from "../../block/blockDetails.entity";
import { TransactionService } from "../../transaction/transaction.service";
import { BalanceService } from "../../balance/balance.service";
import { TransactionStatus } from "../../transaction/entities/transaction.entity";
Expand Down Expand Up @@ -629,7 +629,7 @@ describe("AccountController", () => {
it("returns blocks list response when block by miner are found", async () => {
jest
.spyOn(blockServiceMock, "findMany")
.mockResolvedValue([{ number: 1, timestamp: new Date("2023-03-03") } as BlockDetail]);
.mockResolvedValue([{ number: 1, timestamp: new Date("2023-03-03") } as BlockDetails]);
const response = await controller.getAccountMinedBlocks(address, {
page: 1,
offset: 10,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { mock } from "jest-mock-extended";
import { Logger } from "@nestjs/common";
import { TransactionService } from "../../transaction/transaction.service";
import { TransactionReceiptService } from "../../transaction/transactionReceipt.service";
import { TransactionStatus, Transaction } from "../../transaction/entities/transaction.entity";
import { TransactionStatus } from "../../transaction/entities/transaction.entity";
import { TransactionDetails } from "../../transaction/entities/transactionDetails.entity";
import { TransactionReceipt } from "../../transaction/entities/transactionReceipt.entity";
import { ResponseStatus, ResponseMessage } from "../dtos/common/responseBase.dto";
import { TransactionController } from "./transaction.controller";
Expand Down Expand Up @@ -56,7 +57,7 @@ describe("TransactionController", () => {
it("returns isError as 0 when transaction is successful", async () => {
jest
.spyOn(transactionServiceMock, "findOne")
.mockResolvedValue({ status: TransactionStatus.Included } as Transaction);
.mockResolvedValue({ status: TransactionStatus.Included } as TransactionDetails);

const response = await controller.getTransactionStatus(transactionHash);
expect(response).toEqual({
Expand All @@ -72,7 +73,7 @@ describe("TransactionController", () => {
it("returns isError as 1 when transaction is failed", async () => {
jest
.spyOn(transactionServiceMock, "findOne")
.mockResolvedValue({ status: TransactionStatus.Failed } as Transaction);
.mockResolvedValue({ status: TransactionStatus.Failed } as TransactionDetails);

const response = await controller.getTransactionStatus(transactionHash);
expect(response).toEqual({
Expand Down
6 changes: 3 additions & 3 deletions packages/api/src/block/block.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { PagingOptionsDto, ListFiltersDto } from "../common/dtos";
import { ApiListPageOkResponse } from "../common/decorators/apiListPageOkResponse";
import { BlockService } from "./block.service";
import { BlockDto } from "./block.dto";
import { BlockDetailDto } from "./blockDetail.dto";
import { BlockDetailsDto } from "./blockDetails.dto";
import { swagger } from "../config/featureFlags";

const entityName = "blocks";
Expand Down Expand Up @@ -48,12 +48,12 @@ export class BlockController {
example: "1",
description: "Block number",
})
@ApiOkResponse({ description: "Block was returned successfully", type: BlockDetailDto })
@ApiOkResponse({ description: "Block was returned successfully", type: BlockDetailsDto })
@ApiBadRequestResponse({ description: "Block number is invalid" })
@ApiNotFoundResponse({ description: "Block with the specified number does not exist" })
public async getBlock(
@Param("blockNumber", new ParseLimitedIntPipe({ min: 0 })) blockNumber: number
): Promise<BlockDetailDto> {
): Promise<BlockDetailsDto> {
const block = await this.blockService.findOne(blockNumber);
if (!block) {
throw new NotFoundException();
Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/block/block.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { TypeOrmModule } from "@nestjs/typeorm";
import { BlockService } from "../block/block.service";
import { BlockController } from "./block.controller";
import { Block } from "./block.entity";
import { BlockDetail } from "./blockDetail.entity";
import { BlockDetails } from "./blockDetails.entity";

@Module({
imports: [TypeOrmModule.forFeature([Block, BlockDetail])],
imports: [TypeOrmModule.forFeature([Block, BlockDetails])],
controllers: [BlockController],
providers: [BlockService],
exports: [BlockService],
Expand Down
10 changes: 5 additions & 5 deletions packages/api/src/block/block.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import { Pagination, IPaginationMeta } from "nestjs-typeorm-paginate";
import * as utils from "../common/utils";
import { BlockService, FindManyOptions } from "./block.service";
import { Block } from "./block.entity";
import { BlockDetail } from "./blockDetail.entity";
import { BlockDetails } from "./blockDetails.entity";

jest.mock("../common/utils");

describe("BlockService", () => {
let blockRecord;
let service: BlockService;
let repositoryMock: Repository<Block>;
let blockDetailRepositoryMock: Repository<BlockDetail>;
let blockDetailRepositoryMock: Repository<BlockDetails>;

beforeEach(async () => {
repositoryMock = mock<Repository<Block>>();
blockDetailRepositoryMock = mock<Repository<BlockDetail>>();
blockDetailRepositoryMock = mock<Repository<BlockDetails>>();

blockRecord = {
number: 123,
Expand All @@ -32,7 +32,7 @@ describe("BlockService", () => {
useValue: repositoryMock,
},
{
provide: getRepositoryToken(BlockDetail),
provide: getRepositoryToken(BlockDetails),
useValue: blockDetailRepositoryMock,
},
],
Expand Down Expand Up @@ -305,7 +305,7 @@ describe("BlockService", () => {
let filterOptions: FindManyOptions;

beforeEach(() => {
queryBuilderMock = mock<SelectQueryBuilder<BlockDetail>>({
queryBuilderMock = mock<SelectQueryBuilder<BlockDetails>>({
getMany: jest.fn().mockResolvedValue([
{
number: 1,
Expand Down
16 changes: 8 additions & 8 deletions packages/api/src/block/block.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ import { Pagination } from "nestjs-typeorm-paginate";
import { paginate } from "../common/utils";
import { IPaginationOptions } from "../common/types";
import { Block } from "./block.entity";
import { BlockDetail } from "./blockDetail.entity";
import { BlockDetails } from "./blockDetails.entity";

export interface FindManyOptions {
miner?: string;
page?: number;
offset?: number;
selectFields?: (keyof BlockDetail)[];
selectFields?: (keyof BlockDetails)[];
}

@Injectable()
export class BlockService {
public constructor(
@InjectRepository(Block)
private readonly blocksRepository: Repository<Block>,
@InjectRepository(BlockDetail)
private readonly blockDetailsRepository: Repository<BlockDetail>
@InjectRepository(BlockDetails)
private readonly blockDetailsRepository: Repository<BlockDetails>
) {}

private getBlock(filterOptions: FindOptionsWhere<Block>, orderOptions: FindOptionsOrder<Block>): Promise<Block> {
Expand Down Expand Up @@ -50,9 +50,9 @@ export class BlockService {

public async findOne(
number: number,
selectFields?: (keyof BlockDetail)[],
relations: FindOptionsRelations<BlockDetail> = { batch: true }
): Promise<BlockDetail> {
selectFields?: (keyof BlockDetails)[],
relations: FindOptionsRelations<BlockDetails> = { batch: true }
): Promise<BlockDetails> {
return await this.blockDetailsRepository.findOne({
where: { number },
relations: relations,
Expand Down Expand Up @@ -90,7 +90,7 @@ export class BlockService {
return await paginate<Block>(queryBuilder, paginationOptions, () => this.count(filterOptions));
}

public async findMany({ miner, page = 1, offset = 10, selectFields }: FindManyOptions): Promise<BlockDetail[]> {
public async findMany({ miner, page = 1, offset = 10, selectFields }: FindManyOptions): Promise<BlockDetails[]> {
const queryBuilder = this.blockDetailsRepository.createQueryBuilder("block");
queryBuilder.addSelect(selectFields);
if (miner) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiProperty } from "@nestjs/swagger";
import { BlockDto } from "./block.dto";

export class BlockDetailDto extends BlockDto {
export class BlockDetailsDto extends BlockDto {
@ApiProperty({
type: String,
description: "The hash of the previous block",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Block } from "./block.entity";
import { hexTransformer } from "../common/transformers/hex.transformer";

@Entity({ name: "blocks" })
export class BlockDetail extends Block {
export class BlockDetails extends Block {
@Column({ type: "bytea", transformer: hexTransformer, nullable: true })
public readonly parentHash?: string;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { hexToDecimalNumberTransformer } from "./hexToDecimalNumber.transformer";

describe("hexToDecimalNumberTransformer", () => {
describe("to", () => {
it("returns null for null input", () => {
const result = hexToDecimalNumberTransformer.to(null);
expect(result).toBeNull();
});

it("returns hex representation of the decimal number string", () => {
const result = hexToDecimalNumberTransformer.to("800");
expect(result).toBe("0x0320");
});
});

describe("from", () => {
it("returns null for null input", () => {
const result = hexToDecimalNumberTransformer.from(null);
expect(result).toBeNull();
});

it("returns decimal representation of the hex number string", () => {
const result = hexToDecimalNumberTransformer.from("0x320");
expect(result).toBe("800");
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { BigNumber } from "ethers";
import { ValueTransformer } from "typeorm";

export const hexToDecimalNumberTransformer: ValueTransformer = {
to(decimalNumberStr: string | null): string | null {
if (!decimalNumberStr) {
return null;
}
return BigNumber.from(decimalNumberStr).toHexString();
},
from(hexNumberStr: string | null): string | null {
if (!hexNumberStr) {
return null;
}
return BigNumber.from(hexNumberStr).toString();
},
};
43 changes: 42 additions & 1 deletion packages/api/src/transaction/dtos/transaction.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class TransactionDto {
@ApiProperty({
type: String,
description: "The amount this transaction sent",
example: "0x2386f26fc10000",
example: "100000000",
})
public readonly value: string;

Expand All @@ -58,6 +58,47 @@ export class TransactionDto {
})
public readonly nonce: number;

@ApiProperty({
type: String,
description: "Gas price",
example: "100000000",
})
public readonly gasPrice: string;

@ApiProperty({
type: String,
description: "Gas limit",
example: "100000000",
})
public readonly gasLimit: string;

@ApiProperty({
type: String,
description: "Gas per pubdata limit",
example: "100000000",
examples: ["100000000", null],
required: false,
})
public readonly gasPerPubdata?: string;

@ApiProperty({
type: String,
description: "Max fee per gas",
example: "100000000",
examples: ["100000000", null],
required: false,
})
public readonly maxFeePerGas?: string;

@ApiProperty({
type: String,
description: "Max priority fee per gas",
example: "100000000",
examples: ["100000000", null],
required: false,
})
public readonly maxPriorityFeePerGas?: string;

@ApiProperty({
type: Number,
description: "The number (height) of the block this transaction was mined in",
Expand Down
11 changes: 11 additions & 0 deletions packages/api/src/transaction/dtos/transactionDetails.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ApiProperty } from "@nestjs/swagger";
import { TransactionDto } from "./transaction.dto";

export class TransactionDetailsDto extends TransactionDto {
@ApiProperty({
type: String,
description: "Gas used by the transaction",
example: "50000000",
})
public readonly gasUsed: string;
}
10 changes: 10 additions & 0 deletions packages/api/src/transaction/entities/transaction.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BaseEntity } from "../../common/entities/base.entity";
import { normalizeAddressTransformer } from "../../common/transformers/normalizeAddress.transformer";
import { bigIntNumberTransformer } from "../../common/transformers/bigIntNumber.transformer";
import { hexTransformer } from "../../common/transformers/hex.transformer";
import { hexToDecimalNumberTransformer } from "../../common/transformers/hexToDecimalNumber.transformer";
import { TransactionReceipt } from "./transactionReceipt.entity";
import { Transfer } from "../../transfer/transfer.entity";
import { Block } from "../../block/block.entity";
Expand Down Expand Up @@ -61,6 +62,15 @@ export class Transaction extends BaseEntity {
@Column({ type: "varchar", length: 128 })
public readonly gasPrice: string;

@Column({ type: "varchar", length: 128, nullable: true, transformer: hexToDecimalNumberTransformer })
public readonly gasPerPubdata?: string;

@Column({ type: "varchar", length: 128, nullable: true })
public readonly maxFeePerGas?: string;

@Column({ type: "varchar", length: 128, nullable: true })
public readonly maxPriorityFeePerGas?: string;

@ManyToOne(() => Block)
@JoinColumn({ name: "blockNumber" })
public readonly block: Block;
Expand Down
18 changes: 18 additions & 0 deletions packages/api/src/transaction/entities/transactionDetails.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Entity } from "typeorm";
import { Transaction } from "./transaction.entity";

@Entity({ name: "transactions" })
export class TransactionDetails extends Transaction {
public get gasUsed(): string {
return this.transactionReceipt ? this.transactionReceipt.gasUsed : null;
}

toJSON(): any {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { transactionReceipt, ...restFields } = super.toJSON();
return {
...restFields,
gasUsed: this.gasUsed,
};
}
}
9 changes: 5 additions & 4 deletions packages/api/src/transaction/transaction.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { buildDateFilter } from "../common/utils";
import { FilterTransactionsOptionsDto } from "./dtos/filterTransactionsOptions.dto";
import { TransferDto } from "../transfer/transfer.dto";
import { TransactionDto } from "./dtos/transaction.dto";
import { TransactionDetailsDto } from "./dtos/transactionDetails.dto";
import { TransferService } from "../transfer/transfer.service";
import { LogDto } from "../log/log.dto";
import { LogService } from "../log/log.service";
Expand Down Expand Up @@ -72,12 +73,12 @@ export class TransactionController {
@ApiNotFoundResponse({ description: "Transaction with the specified hash does not exist" })
public async getTransaction(
@Param("transactionHash", new ParseTransactionHashPipe()) transactionHash: string
): Promise<TransactionDto> {
const transaction = await this.transactionService.findOne(transactionHash);
if (!transaction) {
): Promise<TransactionDetailsDto> {
const transactionDetail = await this.transactionService.findOne(transactionHash);
if (!transactionDetail) {
throw new NotFoundException();
}
return transaction;
return transactionDetail;
}

@Get(":transactionHash/transfers")
Expand Down
3 changes: 2 additions & 1 deletion packages/api/src/transaction/transaction.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TransactionController } from "./transaction.controller";
import { TransactionService } from "./transaction.service";
import { TransactionReceiptService } from "./transactionReceipt.service";
import { Transaction } from "./entities/transaction.entity";
import { TransactionDetails } from "./entities/transactionDetails.entity";
import { AddressTransaction } from "./entities/addressTransaction.entity";
import { TransactionReceipt } from "./entities/transactionReceipt.entity";
import { Batch } from "../batch/batch.entity";
Expand All @@ -13,7 +14,7 @@ import { LogModule } from "../log/log.module";

@Module({
imports: [
TypeOrmModule.forFeature([Transaction, AddressTransaction, TransactionReceipt, Batch]),
TypeOrmModule.forFeature([Transaction, TransactionDetails, AddressTransaction, TransactionReceipt, Batch]),
TransferModule,
LogModule,
CounterModule,
Expand Down
Loading

0 comments on commit a42d8e5

Please sign in to comment.