From 81890ab49aa8c94f9d02748592b86e896a64d066 Mon Sep 17 00:00:00 2001 From: Vasyl Ivanchuk Date: Wed, 31 Jul 2024 19:35:13 +0300 Subject: [PATCH] fix: add l2 eth token configuration --- packages/api/.env.example | 10 +- packages/api/.env.test | 8 + .../src/api/stats/stats.controller.spec.ts | 17 +- .../api/src/api/stats/stats.controller.ts | 11 +- .../src/api/token/token.controller.spec.ts | 14 +- packages/api/src/balance/balance.entity.ts | 16 +- packages/api/src/config/index.spec.ts | 197 +++++++++++++----- packages/api/src/config/index.ts | 72 +++++-- .../api/src/health/health.controller.spec.ts | 3 +- packages/api/src/token/token.service.spec.ts | 5 +- packages/api/src/token/token.service.ts | 6 +- packages/api/src/transfer/transfer.entity.ts | 12 +- packages/api/test/address.e2e-spec.ts | 4 +- packages/api/test/stats-api.e2e-spec.ts | 4 +- packages/api/test/token-api.e2e-spec.ts | 36 ++-- packages/api/test/token.e2e-spec.ts | 4 +- packages/api/test/transaction.e2e-spec.ts | 4 +- 17 files changed, 296 insertions(+), 127 deletions(-) diff --git a/packages/api/.env.example b/packages/api/.env.example index ef63689663..447d6362a4 100644 --- a/packages/api/.env.example +++ b/packages/api/.env.example @@ -17,8 +17,16 @@ CONTRACT_VERIFICATION_API_URL=http://127.0.0.1:3070 NETWORK_NAME=testnet-sepolia BASE_TOKEN_SYMBOL=ETH BASE_TOKEN_DECIMALS=18 -BASE_TOKEN_L1_ADDRESS=0x8E9C82509488eD471A83824d20Dd474b8F534a0b +BASE_TOKEN_L1_ADDRESS=0x0000000000000000000000000000000000000000 BASE_TOKEN_ICON_URL=https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266 BASE_TOKEN_NAME=Ether BASE_TOKEN_LIQUIDITY=220000000000 BASE_TOKEN_USDPRICE=1800 + +ETH_TOKEN_SYMBOL=ETH +ETH_TOKEN_DECIMALS=18 +ETH_TOKEN_L2_ADDRESS=0x000000000000000000000000000000000000800A +ETH_TOKEN_ICON_URL=https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266 +ETH_TOKEN_NAME=Ether +ETH_TOKEN_LIQUIDITY=220000000000 +ETH_TOKEN_USDPRICE=1800 diff --git a/packages/api/.env.test b/packages/api/.env.test index d4d855e2d6..9dc9023c8c 100644 --- a/packages/api/.env.test +++ b/packages/api/.env.test @@ -4,3 +4,11 @@ PORT=3007 LIMITED_PAGINATION_MAX_ITEMS=15 API_LIMITED_PAGINATION_MAX_ITEMS=15 CONTRACT_VERIFICATION_API_URL=http://verification.api +BASE_TOKEN_SYMBOL=ETH +BASE_TOKEN_DECIMALS=18 +BASE_TOKEN_L1_ADDRESS=0x0000000000000000000000000000000000000000 +BASE_TOKEN_ICON_URL=https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266 +BASE_TOKEN_NAME=Ether +BASE_TOKEN_LIQUIDITY=220000000000 +BASE_TOKEN_USDPRICE=1800 +ETH_TOKEN_L2_ADDRESS=0x000000000000000000000000000000000000800A \ No newline at end of file diff --git a/packages/api/src/api/stats/stats.controller.spec.ts b/packages/api/src/api/stats/stats.controller.spec.ts index 18e88a9815..b4757a8cfa 100644 --- a/packages/api/src/api/stats/stats.controller.spec.ts +++ b/packages/api/src/api/stats/stats.controller.spec.ts @@ -1,19 +1,26 @@ import { Test } from "@nestjs/testing"; import { mock } from "jest-mock-extended"; +import { ConfigService } from "@nestjs/config"; import { Logger } from "@nestjs/common"; import { TokenService } from "../../token/token.service"; import { Token } from "../../token/token.entity"; import { StatsController } from "./stats.controller"; -import { baseTokenData } from "../../config"; +import { BASE_TOKEN_L2_ADDRESS } from "../../common/constants"; describe("StatsController", () => { let controller: StatsController; let tokenServiceMock: TokenService; + let configServiceMock: ConfigService; beforeEach(async () => { tokenServiceMock = mock({ findOne: jest.fn().mockResolvedValue(null), }); + configServiceMock = mock({ + get: jest.fn().mockResolvedValue({ + l2Address: BASE_TOKEN_L2_ADDRESS, + }), + }); const module = await Test.createTestingModule({ controllers: [StatsController], @@ -22,6 +29,10 @@ describe("StatsController", () => { provide: TokenService, useValue: tokenServiceMock, }, + { + provide: ConfigService, + useValue: configServiceMock, + }, ], }).compile(); module.useLogger(mock()); @@ -32,7 +43,7 @@ describe("StatsController", () => { describe("ethPrice", () => { it("returns ok response and ETH price when ETH token is found", async () => { jest.spyOn(tokenServiceMock, "findOne").mockResolvedValueOnce({ - usdPrice: baseTokenData.usdPrice, + usdPrice: 1000, offChainDataUpdatedAt: new Date("2023-03-03"), } as Token); @@ -41,7 +52,7 @@ describe("StatsController", () => { status: "1", message: "OK", result: { - ethusd: baseTokenData.usdPrice.toString(), + ethusd: "1000", ethusd_timestamp: Math.floor(new Date("2023-03-03").getTime() / 1000).toString(), }, }); diff --git a/packages/api/src/api/stats/stats.controller.ts b/packages/api/src/api/stats/stats.controller.ts index 04618357a5..a2706cf70f 100644 --- a/packages/api/src/api/stats/stats.controller.ts +++ b/packages/api/src/api/stats/stats.controller.ts @@ -1,11 +1,12 @@ import { Controller, Get, UseFilters } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; import { ApiTags, ApiExcludeController } from "@nestjs/swagger"; import { ResponseStatus, ResponseMessage } from "../dtos/common/responseBase.dto"; import { ApiExceptionFilter } from "../exceptionFilter"; import { EthPriceResponseDto } from "../dtos/stats/ethPrice.dto"; import { TokenService } from "../../token/token.service"; import { dateToTimestamp } from "../../common/utils"; -import { baseTokenData } from "../../config"; +import { type BaseToken } from "../../config"; const entityName = "stats"; @@ -14,11 +15,15 @@ const entityName = "stats"; @Controller(`api/${entityName}`) @UseFilters(ApiExceptionFilter) export class StatsController { - constructor(private readonly tokenService: TokenService) {} + private readonly ethTokenAddress: string; + + constructor(private readonly tokenService: TokenService, private readonly configService: ConfigService) { + this.ethTokenAddress = this.configService.get("ethToken").l2Address; + } @Get("/ethprice") public async ethPrice(): Promise { - const token = await this.tokenService.findOne(baseTokenData.l2Address, { + const token = await this.tokenService.findOne(this.ethTokenAddress, { usdPrice: true, offChainDataUpdatedAt: true, }); diff --git a/packages/api/src/api/token/token.controller.spec.ts b/packages/api/src/api/token/token.controller.spec.ts index b1b2b38919..1a4745b763 100644 --- a/packages/api/src/api/token/token.controller.spec.ts +++ b/packages/api/src/api/token/token.controller.spec.ts @@ -4,8 +4,7 @@ import { Logger } from "@nestjs/common"; import { TokenService } from "../../token/token.service"; import { Token } from "../../token/token.entity"; import { TokenController } from "./token.controller"; -import config from "../../config/index"; -const { baseTokenData } = config(); + describe("TokenController", () => { let controller: TokenController; let tokenServiceMock: TokenService; @@ -33,7 +32,16 @@ describe("TokenController", () => { describe("tokenInfo", () => { it("returns ok response and token info when token is found", async () => { - const baseToken = baseTokenData as Token; + const baseToken = { + l2Address: "l2Address", + l1Address: "l1Address", + symbol: "ETH", + name: "Ether", + decimals: 18, + liquidity: 10, + iconURL: "iconURL", + usdPrice: 20, + } as Token; jest.spyOn(tokenServiceMock, "findOne").mockResolvedValueOnce(baseToken); const response = await controller.tokenInfo(contractAddress); expect(response).toEqual({ diff --git a/packages/api/src/balance/balance.entity.ts b/packages/api/src/balance/balance.entity.ts index 34e3f7544c..761ec96074 100644 --- a/packages/api/src/balance/balance.entity.ts +++ b/packages/api/src/balance/balance.entity.ts @@ -3,7 +3,8 @@ import { BaseEntity } from "../common/entities/base.entity"; import { Token } from "../token/token.entity"; import { normalizeAddressTransformer } from "../common/transformers/normalizeAddress.transformer"; import { bigIntNumberTransformer } from "../common/transformers/bigIntNumber.transformer"; -import { baseTokenData } from "../config/index"; +import { baseToken, ethToken } from "../config"; + @Entity({ name: "balances" }) export class Balance extends BaseEntity { @PrimaryColumn({ type: "bytea", transformer: normalizeAddressTransformer }) @@ -25,11 +26,14 @@ export class Balance extends BaseEntity { @AfterLoad() populateBaseToken() { - if ( - !this.token && - (this.tokenAddress === undefined || this.tokenAddress.toLowerCase() === baseTokenData.l2Address.toLowerCase()) - ) { - this.token = baseTokenData as Token; + // tokenAddress might be empty when not all entity fields are requested from the DB + if (this.tokenAddress && !this.token) { + const tokenAddress = this.tokenAddress.toLowerCase(); + if (tokenAddress === baseToken.l2Address.toLowerCase()) { + this.token = baseToken as Token; + } else if (tokenAddress === ethToken.l2Address.toLowerCase()) { + this.token = ethToken as Token; + } } } } diff --git a/packages/api/src/config/index.spec.ts b/packages/api/src/config/index.spec.ts index d473c9215a..7581531965 100644 --- a/packages/api/src/config/index.spec.ts +++ b/packages/api/src/config/index.spec.ts @@ -1,4 +1,5 @@ import config from "../config"; + jest.mock("./featureFlags", () => ({ feature1Enabled: true, feature2Enabled: false, @@ -19,16 +20,22 @@ describe("config", () => { it("sets default values", () => { expect(config()).toEqual({ - baseTokenData: { + baseToken: { l2Address: "0x000000000000000000000000000000000000800A", l1Address: "0x0000000000000000000000000000000000000000", symbol: "ETH", name: "Ether", decimals: 18, - // Fallback data in case ETH token is not in the DB + // Fallback data incase ETH token is not in the DB + iconURL: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", + }, + ethToken: { + decimals: 18, iconURL: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", - liquidity: 220000000000, - usdPrice: 1800, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", }, NODE_ENV: "test", port: 3020, @@ -60,57 +67,141 @@ describe("config", () => { }); }); - it("sets default values with base ERC20", () => { - process.env = { - BASE_TOKEN_SYMBOL: "MTTL", - BASE_TOKEN_DECIMALS: "18", - BASE_TOKEN_L1_ADDRESS: "0xSomeAddress", - BASE_TOKEN_ICON_URL: "https://matter-labs.io", - BASE_TOKEN_NAME: "MatterLabs", - BASE_TOKEN_LIQUIDITY: "999999999999", - BASE_TOKEN_USDPRICE: "19", - NODE_ENV: "test", - }; + describe("when custom base token is defined", () => { + it("sets default values with base ERC20", () => { + process.env = { + BASE_TOKEN_SYMBOL: "MTTL", + BASE_TOKEN_DECIMALS: "18", + BASE_TOKEN_L1_ADDRESS: "0xSomeAddress", + BASE_TOKEN_ICON_URL: "https://matter-labs.io", + BASE_TOKEN_NAME: "MatterLabs", + BASE_TOKEN_LIQUIDITY: "999999999999", + BASE_TOKEN_USDPRICE: "19", + NODE_ENV: "test", - expect(config()).toEqual({ - baseTokenData: { - l2Address: "0x000000000000000000000000000000000000800A", - l1Address: "0xSomeAddress", - symbol: "MTTL", - name: "MatterLabs", - decimals: 18, - // Fallback data in case ETH token is not in the DB - iconURL: "https://matter-labs.io", - liquidity: 999999999999, - usdPrice: 19, - }, - NODE_ENV: "test", - port: 3020, - metrics: { - port: 3005, - collectDbConnectionPoolMetricsInterval: 10000, - }, - typeORM: { - type: "postgres", - url: "postgres://postgres:postgres@127.0.0.1:5432/block-explorer", - poolSize: 300, - extra: { - idleTimeoutMillis: 60000, - statement_timeout: 90000, + ETH_TOKEN_SYMBOL: "ETH1", + ETH_TOKEN_DECIMALS: "181", + ETH_TOKEN_L2_ADDRESS: "0x000000000000000000000000000000000000800A1", + ETH_TOKEN_ICON_URL: "iconUrl", + ETH_TOKEN_NAME: "Ether1", + ETH_TOKEN_LIQUIDITY: "2200000000001", + ETH_TOKEN_USDPRICE: "18001", + }; + + expect(config()).toEqual({ + baseToken: { + l2Address: "0x000000000000000000000000000000000000800A", + l1Address: "0xSomeAddress", + symbol: "MTTL", + name: "MatterLabs", + decimals: 18, + iconURL: "https://matter-labs.io", + liquidity: 999999999999, + usdPrice: 19, }, - synchronize: true, - logging: false, - autoLoadEntities: true, - retryAttempts: 10, - retryDelay: 3000, - applicationName: "block-explorer-api", - }, - contractVerificationApiUrl: "http://127.0.0.1:3070", - featureFlags: { - feature1Enabled: true, - feature2Enabled: false, - }, - gracefulShutdownTimeoutMs: 0, + ethToken: { + l2Address: "0x000000000000000000000000000000000000800A1", + l1Address: "0x0000000000000000000000000000000000000000", + symbol: "ETH1", + name: "Ether1", + decimals: 181, + iconURL: "iconUrl", + liquidity: 2200000000001, + usdPrice: 18001, + }, + NODE_ENV: "test", + port: 3020, + metrics: { + port: 3005, + collectDbConnectionPoolMetricsInterval: 10000, + }, + typeORM: { + type: "postgres", + url: "postgres://postgres:postgres@127.0.0.1:5432/block-explorer", + poolSize: 300, + extra: { + idleTimeoutMillis: 60000, + statement_timeout: 90000, + }, + synchronize: true, + logging: false, + autoLoadEntities: true, + retryAttempts: 10, + retryDelay: 3000, + applicationName: "block-explorer-api", + }, + contractVerificationApiUrl: "http://127.0.0.1:3070", + featureFlags: { + feature1Enabled: true, + feature2Enabled: false, + }, + gracefulShutdownTimeoutMs: 0, + }); + }); + + describe("and liquidity and price is not provided", () => { + it("sets default values with base ERC20", () => { + process.env = { + BASE_TOKEN_SYMBOL: "MTTL", + BASE_TOKEN_DECIMALS: "18", + BASE_TOKEN_L1_ADDRESS: "0xSomeAddress", + BASE_TOKEN_ICON_URL: "https://matter-labs.io", + BASE_TOKEN_NAME: "MatterLabs", + NODE_ENV: "test", + + ETH_TOKEN_SYMBOL: "ETH1", + ETH_TOKEN_DECIMALS: "181", + ETH_TOKEN_L2_ADDRESS: "0x000000000000000000000000000000000000800A1", + ETH_TOKEN_ICON_URL: "iconUrl", + ETH_TOKEN_NAME: "Ether1", + }; + + expect(config()).toEqual({ + baseToken: { + l2Address: "0x000000000000000000000000000000000000800A", + l1Address: "0xSomeAddress", + symbol: "MTTL", + name: "MatterLabs", + decimals: 18, + iconURL: "https://matter-labs.io", + }, + ethToken: { + l2Address: "0x000000000000000000000000000000000000800A1", + l1Address: "0x0000000000000000000000000000000000000000", + symbol: "ETH1", + name: "Ether1", + decimals: 181, + iconURL: "iconUrl", + }, + NODE_ENV: "test", + port: 3020, + metrics: { + port: 3005, + collectDbConnectionPoolMetricsInterval: 10000, + }, + typeORM: { + type: "postgres", + url: "postgres://postgres:postgres@127.0.0.1:5432/block-explorer", + poolSize: 300, + extra: { + idleTimeoutMillis: 60000, + statement_timeout: 90000, + }, + synchronize: true, + logging: false, + autoLoadEntities: true, + retryAttempts: 10, + retryDelay: 3000, + applicationName: "block-explorer-api", + }, + contractVerificationApiUrl: "http://127.0.0.1:3070", + featureFlags: { + feature1Enabled: true, + feature2Enabled: false, + }, + gracefulShutdownTimeoutMs: 0, + }); + }); }); }); diff --git a/packages/api/src/config/index.ts b/packages/api/src/config/index.ts index c31503a78f..e1c506ef96 100644 --- a/packages/api/src/config/index.ts +++ b/packages/api/src/config/index.ts @@ -1,17 +1,19 @@ import { TypeOrmModuleOptions } from "@nestjs/typeorm"; import * as featureFlags from "./featureFlags"; import { BASE_TOKEN_L1_ADDRESS, BASE_TOKEN_L2_ADDRESS } from "../common/constants"; -type BaseToken = { + +export type BaseToken = { + name: string; symbol: string; decimals: number; l1Address: string; l2Address: string; - liquidity: number; - iconURL: string; - name: string; - usdPrice: number; + liquidity?: number; + iconURL?: string; + usdPrice?: number; }; -const defaultEthBaseToken: BaseToken = { + +const defaultBaseToken: BaseToken = { l2Address: BASE_TOKEN_L2_ADDRESS, l1Address: BASE_TOKEN_L1_ADDRESS, symbol: "ETH", @@ -19,10 +21,9 @@ const defaultEthBaseToken: BaseToken = { decimals: 18, // Fallback data in case ETH token is not in the DB iconURL: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", - liquidity: 220000000000, - usdPrice: 1800, }; -const baseTokenFromEnv = (): BaseToken => { + +const getBaseToken = (): BaseToken => { const { BASE_TOKEN_SYMBOL, BASE_TOKEN_DECIMALS, @@ -32,25 +33,53 @@ const baseTokenFromEnv = (): BaseToken => { BASE_TOKEN_LIQUIDITY, BASE_TOKEN_USDPRICE, } = process.env; - const decimals = parseFloat(BASE_TOKEN_DECIMALS); - const liquidity = parseFloat(BASE_TOKEN_LIQUIDITY); - const usdPrice = parseFloat(BASE_TOKEN_USDPRICE); + if (BASE_TOKEN_L1_ADDRESS && BASE_TOKEN_SYMBOL) { return { + name: BASE_TOKEN_NAME, symbol: BASE_TOKEN_SYMBOL, - decimals, + decimals: parseInt(BASE_TOKEN_DECIMALS, 10), l1Address: BASE_TOKEN_L1_ADDRESS, l2Address: BASE_TOKEN_L2_ADDRESS, - liquidity, + liquidity: parseFloat(BASE_TOKEN_LIQUIDITY) || undefined, iconURL: BASE_TOKEN_ICON_URL, - usdPrice, - name: BASE_TOKEN_NAME, + usdPrice: parseFloat(BASE_TOKEN_USDPRICE) || undefined, }; - } else { - return defaultEthBaseToken; } + + return defaultBaseToken; }; +const getEthToken = (): BaseToken => { + const { + ETH_TOKEN_SYMBOL, + ETH_TOKEN_DECIMALS, + ETH_TOKEN_L2_ADDRESS, + ETH_TOKEN_ICON_URL, + ETH_TOKEN_NAME, + ETH_TOKEN_LIQUIDITY, + ETH_TOKEN_USDPRICE, + } = process.env; + + if (ETH_TOKEN_L2_ADDRESS) { + return { + name: ETH_TOKEN_NAME || defaultBaseToken.name, + symbol: ETH_TOKEN_SYMBOL || defaultBaseToken.symbol, + decimals: parseFloat(ETH_TOKEN_DECIMALS) || defaultBaseToken.decimals, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: ETH_TOKEN_L2_ADDRESS, + liquidity: parseFloat(ETH_TOKEN_LIQUIDITY) || undefined, + iconURL: ETH_TOKEN_ICON_URL || defaultBaseToken.iconURL, + usdPrice: parseFloat(ETH_TOKEN_USDPRICE) || undefined, + }; + } + + return defaultBaseToken; +}; + +export const baseToken: BaseToken = getBaseToken(); +export const ethToken: BaseToken = getEthToken(); + export default () => { const { NODE_ENV, @@ -65,8 +94,6 @@ export default () => { GRACEFUL_SHUTDOWN_TIMEOUT_MS, } = process.env; - const baseTokenData: BaseToken = baseTokenFromEnv(); - const MAX_NUMBER_OF_REPLICA = 100; const getDatabaseReplicaSet = () => { @@ -127,9 +154,8 @@ export default () => { typeORM: getTypeOrmModuleOptions(), contractVerificationApiUrl: CONTRACT_VERIFICATION_API_URL || "http://127.0.0.1:3070", featureFlags, - baseTokenData, + baseToken: getBaseToken(), + ethToken: getEthToken(), gracefulShutdownTimeoutMs: parseInt(GRACEFUL_SHUTDOWN_TIMEOUT_MS, 10) || 0, }; }; - -export const baseTokenData = baseTokenFromEnv(); diff --git a/packages/api/src/health/health.controller.spec.ts b/packages/api/src/health/health.controller.spec.ts index 9bfd136f56..c720e81c3a 100644 --- a/packages/api/src/health/health.controller.spec.ts +++ b/packages/api/src/health/health.controller.spec.ts @@ -1,5 +1,6 @@ import { ServiceUnavailableException } from "@nestjs/common"; import { Test, TestingModule } from "@nestjs/testing"; +import { Logger } from "@nestjs/common"; import { HealthCheckService, TypeOrmHealthIndicator, HealthCheckResult } from "@nestjs/terminus"; import { mock } from "jest-mock-extended"; import { ConfigService } from "@nestjs/config"; @@ -47,7 +48,7 @@ describe("HealthController", () => { }, ], }).compile(); - + app.useLogger(mock()); healthController = app.get(HealthController); }); diff --git a/packages/api/src/token/token.service.spec.ts b/packages/api/src/token/token.service.spec.ts index 257d724335..237bd02923 100644 --- a/packages/api/src/token/token.service.spec.ts +++ b/packages/api/src/token/token.service.spec.ts @@ -7,7 +7,8 @@ import { Token } from "./token.entity"; import { Pagination, IPaginationMeta } from "nestjs-typeorm-paginate"; import * as utils from "../common/utils"; import config from "../config"; -const { baseTokenData } = config(); + +const { baseToken } = config(); jest.mock("../common/utils"); @@ -75,7 +76,7 @@ describe("TokenService", () => { it("returns ETH token for ETH address", async () => { const result = await service.findOne("0x000000000000000000000000000000000000800a"); - expect(result).toEqual(baseTokenData); + expect(result).toEqual(baseToken); }); it("returns null for non ETH address", async () => { diff --git a/packages/api/src/token/token.service.ts b/packages/api/src/token/token.service.ts index 559606467c..1ab5990ed2 100644 --- a/packages/api/src/token/token.service.ts +++ b/packages/api/src/token/token.service.ts @@ -6,8 +6,8 @@ import { IPaginationOptions } from "../common/types"; import { paginate } from "../common/utils"; import { Token } from "./token.entity"; import { BASE_TOKEN_L2_ADDRESS } from "../common/constants"; -import config from "../config"; -const { baseTokenData } = config(); +import { baseToken } from "../config"; + export interface FilterTokensOptions { minLiquidity?: number; } @@ -27,7 +27,7 @@ export class TokenService { select: fields, }); if (!token && address.toLowerCase() === BASE_TOKEN_L2_ADDRESS.toLowerCase()) { - return baseTokenData as Token; + return baseToken as Token; } return token; } diff --git a/packages/api/src/transfer/transfer.entity.ts b/packages/api/src/transfer/transfer.entity.ts index 3cf5d3e3d0..91957512f9 100644 --- a/packages/api/src/transfer/transfer.entity.ts +++ b/packages/api/src/transfer/transfer.entity.ts @@ -5,7 +5,7 @@ import { normalizeAddressTransformer } from "../common/transformers/normalizeAdd import { bigIntNumberTransformer } from "../common/transformers/bigIntNumber.transformer"; import { hexTransformer } from "../common/transformers/hex.transformer"; import { Transaction } from "../transaction/entities/transaction.entity"; -import { baseTokenData } from "../config/index"; +import { baseToken, ethToken } from "../config"; export enum TransferType { Deposit = "deposit", @@ -88,8 +88,14 @@ export class Transfer extends BaseEntity { @AfterLoad() populateBaseToken() { - if (!this.token && this.tokenAddress.toLowerCase() === baseTokenData.l2Address.toLowerCase()) { - this.token = baseTokenData as Token; + // tokenAddress might be empty when not all entity fields are requested from the DB + if (this.tokenAddress && !this.token) { + const tokenAddress = this.tokenAddress.toLowerCase(); + if (tokenAddress === baseToken.l2Address.toLowerCase()) { + this.token = baseToken as Token; + } else if (tokenAddress === ethToken.l2Address.toLowerCase()) { + this.token = ethToken as Token; + } } } } diff --git a/packages/api/test/address.e2e-spec.ts b/packages/api/test/address.e2e-spec.ts index 6c080dc081..7ffa7f5508 100644 --- a/packages/api/test/address.e2e-spec.ts +++ b/packages/api/test/address.e2e-spec.ts @@ -17,10 +17,10 @@ import { BatchDetails } from "../src/batch/batchDetails.entity"; import { Counter } from "../src/counter/counter.entity"; import { Transfer, TransferType } from "../src/transfer/transfer.entity"; import { AddressTransfer } from "../src/transfer/addressTransfer.entity"; -import { baseTokenData } from "../src/config"; +import { baseToken } from "../src/config"; describe("AddressController (e2e)", () => { - const ETH_TOKEN = baseTokenData; + const ETH_TOKEN = baseToken; let app: INestApplication; let addressRepository: Repository
; let blockRepository: Repository; diff --git a/packages/api/test/stats-api.e2e-spec.ts b/packages/api/test/stats-api.e2e-spec.ts index aed8ed3856..046e55b8fb 100644 --- a/packages/api/test/stats-api.e2e-spec.ts +++ b/packages/api/test/stats-api.e2e-spec.ts @@ -8,7 +8,7 @@ import { BlockDetails } from "../src/block/blockDetails.entity"; import { Token } from "../src/token/token.entity"; import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; -import { baseTokenData } from "../src/config"; +import { baseToken } from "../src/config"; describe("Stats API (e2e)", () => { let ETH_TOKEN; @@ -21,7 +21,7 @@ describe("Stats API (e2e)", () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); - ETH_TOKEN = baseTokenData; + ETH_TOKEN = baseToken; app = moduleFixture.createNestApplication({ logger: false }); configureApp(app); await app.init(); diff --git a/packages/api/test/token-api.e2e-spec.ts b/packages/api/test/token-api.e2e-spec.ts index 7930145e7c..0d357282b9 100644 --- a/packages/api/test/token-api.e2e-spec.ts +++ b/packages/api/test/token-api.e2e-spec.ts @@ -8,7 +8,7 @@ import { BlockDetails } from "../src/block/blockDetails.entity"; import { Token } from "../src/token/token.entity"; import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; -import { baseTokenData } from "../src/config"; +import { baseToken } from "../src/config"; describe("Token API (e2e)", () => { let app: INestApplication; @@ -56,16 +56,16 @@ describe("Token API (e2e)", () => { }); await tokenRepository.insert({ - l2Address: baseTokenData.l2Address, - l1Address: baseTokenData.l1Address, - symbol: baseTokenData.symbol, - name: baseTokenData.name, - decimals: baseTokenData.decimals, + l2Address: baseToken.l2Address, + l1Address: baseToken.l1Address, + symbol: baseToken.symbol, + name: baseToken.name, + decimals: baseToken.decimals, blockNumber: 0, logIndex: 0, - usdPrice: baseTokenData.usdPrice, - liquidity: baseTokenData.liquidity, - iconURL: baseTokenData.iconURL, + usdPrice: baseToken.usdPrice, + liquidity: baseToken.liquidity, + iconURL: baseToken.iconURL, }); await tokenRepository.insert({ @@ -129,21 +129,21 @@ describe("Token API (e2e)", () => { it("returns HTTP 200 and ETH token info for ETH token", () => { return request(app.getHttpServer()) - .get(`/api?module=token&action=tokeninfo&contractaddress=${baseTokenData.l2Address}`) + .get(`/api?module=token&action=tokeninfo&contractaddress=${baseToken.l2Address}`) .expect(200) .expect((res) => expect(res.body).toStrictEqual({ message: "OK", result: [ { - contractAddress: baseTokenData.l2Address, - iconURL: baseTokenData.iconURL, - l1Address: baseTokenData.l1Address, - liquidity: baseTokenData.liquidity.toString(), - symbol: baseTokenData.symbol, - tokenDecimal: baseTokenData.decimals.toString(), - tokenName: baseTokenData.name, - tokenPriceUSD: baseTokenData.usdPrice.toString(), + contractAddress: baseToken.l2Address, + iconURL: baseToken.iconURL, + l1Address: baseToken.l1Address, + liquidity: baseToken.liquidity.toString(), + symbol: baseToken.symbol, + tokenDecimal: baseToken.decimals.toString(), + tokenName: baseToken.name, + tokenPriceUSD: baseToken.usdPrice.toString(), }, ], status: "1", diff --git a/packages/api/test/token.e2e-spec.ts b/packages/api/test/token.e2e-spec.ts index 94861bb827..1dea273b0b 100644 --- a/packages/api/test/token.e2e-spec.ts +++ b/packages/api/test/token.e2e-spec.ts @@ -10,7 +10,7 @@ import { BlockDetails } from "../src/block/blockDetails.entity"; import { Transaction } from "../src/transaction/entities/transaction.entity"; import { Transfer, TransferType } from "../src/transfer/transfer.entity"; import { BatchDetails } from "../src/batch/batchDetails.entity"; -import { baseTokenData } from "../src/config"; +import { baseToken } from "../src/config"; describe("TokenController (e2e)", () => { let ETH_TOKEN; @@ -25,7 +25,7 @@ describe("TokenController (e2e)", () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); - ETH_TOKEN = baseTokenData; + ETH_TOKEN = baseToken; app = moduleFixture.createNestApplication({ logger: false }); configureApp(app); diff --git a/packages/api/test/transaction.e2e-spec.ts b/packages/api/test/transaction.e2e-spec.ts index 8796813a6d..172af7c857 100644 --- a/packages/api/test/transaction.e2e-spec.ts +++ b/packages/api/test/transaction.e2e-spec.ts @@ -14,7 +14,7 @@ import { AddressTransaction } from "../src/transaction/entities/addressTransacti import { Transfer, TransferType } from "../src/transfer/transfer.entity"; import { Log } from "../src/log/log.entity"; import { BatchDetails } from "../src/batch/batchDetails.entity"; -import { baseTokenData } from "../src/config"; +import { baseToken } from "../src/config"; describe("TransactionController (e2e)", () => { let ETH_TOKEN; @@ -32,7 +32,7 @@ describe("TransactionController (e2e)", () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); - ETH_TOKEN = baseTokenData; + ETH_TOKEN = baseToken; app = moduleFixture.createNestApplication({ logger: false }); configureApp(app);