Skip to content

Commit

Permalink
feat: add default Eth token data (#76)
Browse files Browse the repository at this point in the history
# What ❔

Add l1Address and default offchain data for ETH token when it is not
present in DB.
  • Loading branch information
Romsters authored Nov 2, 2023
1 parent 4af7b13 commit a3a9cf6
Show file tree
Hide file tree
Showing 19 changed files with 180 additions and 49 deletions.
6 changes: 6 additions & 0 deletions packages/api/src/address/dtos/baseAddress.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ export class BaseAddressDto {
symbol: "symbol",
name: "Token name",
decimals: 18,
usdPrice: 1.0001,
liquidity: 1000000,
iconURL: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266",
},
},
"0xD754fF5e8A6f257E162F72578A4Bb0493C0681d9": {
Expand All @@ -60,6 +63,9 @@ export class BaseAddressDto {
symbol: "symbol 2",
name: "Token name 2",
decimals: 18,
usdPrice: 1.0001,
liquidity: 1000000,
iconURL: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266",
},
},
},
Expand Down
8 changes: 4 additions & 4 deletions packages/api/src/api/api.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ export class ApiController {
@ApiQuery({
name: "contractaddress",
description: "The Token contract address to get balance for",
example: constants.tokenAddress,
example: constants.erc20TokenAddress,
required: true,
})
@ApiOkResponse({
Expand All @@ -414,7 +414,7 @@ export class ApiController {
@ApiQuery({
name: "contractaddress",
description: "The Token contract address to get transfers for",
example: constants.tokenAddress,
example: constants.erc20TokenAddress,
required: false,
})
@ApiQuery({
Expand Down Expand Up @@ -451,13 +451,13 @@ export class ApiController {
@ApiQuery({
name: "address",
description: "The address to get transfers for",
example: constants.address,
example: constants.erc721TokenHolderAddress,
required: false,
})
@ApiQuery({
name: "contractaddress",
description: "The Token contract address to get transfers for",
example: constants.tokenAddress,
example: constants.erc721TokenAddress,
required: false,
})
@ApiQuery({
Expand Down
5 changes: 4 additions & 1 deletion packages/api/src/config/docs/constants.mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
"address": "0xd3D526A8CCA22Fe072cD1852faA4F0a6F2C21765",
"addressWithInternalTx": "0x8B021d2BeD73675F7715422C4BFcBfE759890308",
"addressTxWithInternalTransfers": "0x4683986b4d6b07aa5a8ba6c4a6aa7b1a420a0dfd944ac7128f3e4ab7bd74567c",
"tokenAddress": "0x000000000000000000000000000000000000800A"
"tokenAddress": "0x000000000000000000000000000000000000800A",
"erc20TokenAddress": "0x319897e0F6bEBDf39B46c2eFc5549701C53B53C0",
"erc721TokenAddress": "0xF27e53EDC24Be11B4C5dc4631Fd75EA0Ed896D64",
"erc721TokenHolderAddress": "0x96a337e1B3ccf03E78D5a41272615ee02cb14473"
}
5 changes: 4 additions & 1 deletion packages/api/src/config/docs/constants.testnet-goerli.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
"address": "0xE4ce1da467a7Ca37727eb7e19857e5167DE25966",
"addressWithInternalTx": "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0",
"addressTxWithInternalTransfers": "0x8a453b8dd3e095b3034dc3692663d5bf0c9883cbe6e9f9a0425a3ebf9b9360ab",
"tokenAddress": "0x000000000000000000000000000000000000800A"
"tokenAddress": "0x000000000000000000000000000000000000800A",
"erc20TokenAddress": "0x0faF6df7054946141266420b43783387A78d82A9",
"erc721TokenAddress": "0x09B0196641D91eDEC4042e4bb8C605bb35a02546",
"erc721TokenHolderAddress": "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28"
}
6 changes: 6 additions & 0 deletions packages/api/src/config/docs/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ describe("constants", () => {
txHash: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a",
verifiedContractAddress: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594",
verifiedContractAddress2: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14",
erc20TokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9",
erc721TokenAddress: "0x09B0196641D91eDEC4042e4bb8C605bb35a02546",
erc721TokenHolderAddress: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28",
};

beforeEach(() => {
Expand All @@ -47,6 +50,9 @@ describe("constants", () => {
addressWithInternalTx: "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0",
addressTxWithInternalTransfers: "0x8a453b8dd3e095b3034dc3692663d5bf0c9883cbe6e9f9a0425a3ebf9b9360ab",
tokenAddress: "0x000000000000000000000000000000000000800A",
erc20TokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9",
erc721TokenAddress: "0x09B0196641D91eDEC4042e4bb8C605bb35a02546",
erc721TokenHolderAddress: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28",
};

existsSyncMock.mockReturnValue(true);
Expand Down
3 changes: 3 additions & 0 deletions packages/api/src/config/docs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const defaultDocsConstants = {
addressWithInternalTx: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14",
addressTxWithInternalTransfers: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a",
tokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9",
erc20TokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9",
erc721TokenAddress: "0x09B0196641D91eDEC4042e4bb8C605bb35a02546",
erc721TokenHolderAddress: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28",
};
let networkDocsConstants = {};

Expand Down
27 changes: 27 additions & 0 deletions packages/api/src/token/token.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,31 @@ export class TokenDto {

@ApiProperty({ type: Number, description: "Token decimals value", example: 18 })
public readonly decimals: number;

@ApiProperty({
type: Number,
description: "Token USD price",
example: 1.00001,
examples: [1.0001, null],
required: false,
})
public readonly usdPrice?: number;

@ApiProperty({
type: Number,
description: "Token liquidity",
example: 1000000,
examples: [1000000, null],
required: false,
})
public readonly liquidity?: number;

@ApiProperty({
type: String,
description: "Token icon URL",
example: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266",
examples: ["https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", null],
required: false,
})
public readonly iconURL?: string;
}
9 changes: 5 additions & 4 deletions packages/api/src/token/token.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ export enum TokenType {

export const ETH_TOKEN: Token = {
l2Address: "0x000000000000000000000000000000000000800A",
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
symbol: "ETH",
name: "Ether",
decimals: 18,
iconURL: null,
liquidity: null,
usdPrice: null,
// 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,
} as Token;

@Entity({ name: "tokens" })
Expand Down
15 changes: 3 additions & 12 deletions packages/api/src/token/token.service.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 { getRepositoryToken } from "@nestjs/typeorm";
import { Repository, SelectQueryBuilder } from "typeorm";
import { TokenService } from "./token.service";
import { Token } from "./token.entity";
import { Token, ETH_TOKEN } from "./token.entity";
import { Pagination, IPaginationMeta } from "nestjs-typeorm-paginate";
import * as utils from "../common/utils";

Expand Down Expand Up @@ -62,16 +62,7 @@ describe("TokenService", () => {

it("returns ETH token for ETH address", async () => {
const result = await service.findOne("0x000000000000000000000000000000000000800a");
expect(result).toEqual({
decimals: 18,
l1Address: null,
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
iconURL: null,
liquidity: null,
usdPrice: null,
});
expect(result).toEqual(ETH_TOKEN);
});

it("returns null for non ETH address", async () => {
Expand Down Expand Up @@ -145,7 +136,7 @@ describe("TokenService", () => {
it("returns tokens ordered by liquidity, blockNumber and logIndex DESC", async () => {
await service.findAll(pagingOptions);
expect(queryBuilderMock.orderBy).toBeCalledTimes(1);
expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("token.liquidity", "DESC");
expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("token.liquidity", "DESC", "NULLS LAST");
expect(queryBuilderMock.addOrderBy).toBeCalledTimes(2);
expect(queryBuilderMock.addOrderBy).toHaveBeenCalledWith("token.blockNumber", "DESC");
expect(queryBuilderMock.addOrderBy).toHaveBeenCalledWith("token.logIndex", "DESC");
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/token/token.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class TokenService {

public async findAll(paginationOptions: IPaginationOptions): Promise<Pagination<Token>> {
const queryBuilder = this.tokenRepository.createQueryBuilder("token");
queryBuilder.orderBy("token.liquidity", "DESC");
queryBuilder.orderBy("token.liquidity", "DESC", "NULLS LAST");
queryBuilder.addOrderBy("token.blockNumber", "DESC");
queryBuilder.addOrderBy("token.logIndex", "DESC");
return await paginate<Token>(queryBuilder, paginationOptions);
Expand Down
24 changes: 17 additions & 7 deletions packages/api/test/address.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Transaction } from "../src/transaction/entities/transaction.entity";
import { AddressTransaction } from "../src/transaction/entities/addressTransaction.entity";
import { TransactionReceipt } from "../src/transaction/entities/transactionReceipt.entity";
import { Log } from "../src/log/log.entity";
import { Token, TokenType } from "../src/token/token.entity";
import { Token, TokenType, ETH_TOKEN } from "../src/token/token.entity";
import { BatchDetails } from "../src/batch/batchDetails.entity";
import { Counter } from "../src/counter/counter.entity";
import { Transfer, TransferType } from "../src/transfer/transfer.entity";
Expand Down Expand Up @@ -150,6 +150,16 @@ describe("AddressController (e2e)", () => {
bytecode: "0x",
});

await tokenRepository.insert({
l2Address: ETH_TOKEN.l2Address,
l1Address: ETH_TOKEN.l1Address,
symbol: ETH_TOKEN.symbol,
name: ETH_TOKEN.name,
decimals: ETH_TOKEN.decimals,
blockNumber: 0,
logIndex: 0,
});

// tokens for balances
for (let i = 0; i <= 9; i++) {
await tokenRepository.insert({
Expand Down Expand Up @@ -387,7 +397,7 @@ describe("AddressController (e2e)", () => {
balance: "34500",
token: {
decimals: 18,
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
Expand Down Expand Up @@ -456,7 +466,7 @@ describe("AddressController (e2e)", () => {
balance: "34500",
token: {
decimals: 18,
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
Expand Down Expand Up @@ -525,7 +535,7 @@ describe("AddressController (e2e)", () => {
balance: "34500",
token: {
decimals: 18,
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
Expand Down Expand Up @@ -594,7 +604,7 @@ describe("AddressController (e2e)", () => {
balance: "34500",
token: {
decimals: 18,
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
Expand Down Expand Up @@ -665,7 +675,7 @@ describe("AddressController (e2e)", () => {
balance: "34500",
token: {
decimals: 18,
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
Expand Down Expand Up @@ -1197,7 +1207,7 @@ describe("AddressController (e2e)", () => {
to: "0x91d0a23f34e535e44Df8Ba84c53a0945cf0eEB60",
token: {
l2Address: "0x000000000000000000000000000000000000800A",
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
symbol: "ETH",
name: "Ether",
decimals: 18,
Expand Down
26 changes: 18 additions & 8 deletions packages/api/test/token.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Repository } from "typeorm";
import { getRepositoryToken } from "@nestjs/typeorm";
import { AppModule } from "../src/app.module";
import { configureApp } from "../src/configureApp";
import { Token, TokenType } from "../src/token/token.entity";
import { Token, TokenType, ETH_TOKEN } from "../src/token/token.entity";
import { BlockDetail } from "../src/block/blockDetail.entity";
import { Transaction } from "../src/transaction/entities/transaction.entity";
import { Transfer, TransferType } from "../src/transfer/transfer.entity";
Expand Down Expand Up @@ -88,6 +88,16 @@ describe("TokenController (e2e)", () => {
let tokenIndex = 0;
let transferIndex = 0;

await tokenRepository.insert({
l2Address: ETH_TOKEN.l2Address,
l1Address: ETH_TOKEN.l1Address,
symbol: ETH_TOKEN.symbol,
name: ETH_TOKEN.name,
decimals: ETH_TOKEN.decimals,
blockNumber: 0,
logIndex: 0,
});

for (let i = 1; i <= 30; i++) {
await tokenRepository.insert({
l1Address: i % 2 != 0 ? `0xf754ff5e8a6f257e162f72578a4bb0493c0681${i < 10 ? "0" : ""}${i}` : null,
Expand Down Expand Up @@ -304,7 +314,7 @@ describe("TokenController (e2e)", () => {
.expect((res) =>
expect(res.body).toStrictEqual({
l2Address: "0x000000000000000000000000000000000000800A",
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
symbol: "ETH",
name: "Ether",
decimals: 18,
Expand Down Expand Up @@ -380,8 +390,8 @@ describe("TokenController (e2e)", () => {
currentPage: 2,
itemCount: 10,
itemsPerPage: 10,
totalItems: 30,
totalPages: 3,
totalItems: 31,
totalPages: 4,
})
);
});
Expand All @@ -393,7 +403,7 @@ describe("TokenController (e2e)", () => {
.expect((res) =>
expect(res.body.links).toStrictEqual({
first: "tokens?limit=10",
last: "tokens?page=3&limit=10",
last: "tokens?page=4&limit=10",
next: "tokens?page=3&limit=10",
previous: "tokens?page=1&limit=10",
})
Expand Down Expand Up @@ -645,7 +655,7 @@ describe("TokenController (e2e)", () => {
to: "0x52312AD6f01657413b2eaE9287f6B9ADaD93D5FE",
token: {
decimals: 18,
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
Expand All @@ -668,7 +678,7 @@ describe("TokenController (e2e)", () => {
to: "0x52312AD6f01657413b2eaE9287f6B9ADaD93D5FE",
token: {
decimals: 18,
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
Expand All @@ -691,7 +701,7 @@ describe("TokenController (e2e)", () => {
to: "0x52312AD6f01657413b2eaE9287f6B9ADaD93D5FE",
token: {
decimals: 18,
l1Address: null,
l1Address: "0x0000000000000000000000000000000000000000",
l2Address: "0x000000000000000000000000000000000000800A",
name: "Ether",
symbol: "ETH",
Expand Down
Loading

0 comments on commit a3a9cf6

Please sign in to comment.