Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3b74d79
chore: navbar icons and social links
PrashantShaw Sep 6, 2024
e3c2c9f
chore: page title and favicon with site meta
PrashantShaw Sep 6, 2024
8e03c92
chore: text swaps for validium
PrashantShaw Sep 9, 2024
171d447
chore: deep scan text and icon fixes
PrashantShaw Sep 10, 2024
a29c97f
feat: insights card at HomeView
PrashantShaw Oct 29, 2024
021d7a7
feat: add dashboard api
jishnundth Nov 8, 2024
a7b6217
edit: fetching avg gas fee over 24h
jishnundth Nov 8, 2024
ef6c022
Merge remote-tracking branch 'upstream/main' into feat/validium-based-ui
sachanayush47 Nov 11, 2024
2b85e91
Merge branch 'feat/validium-based-ui' of https://github.com/Validium-…
sachanayush47 Nov 11, 2024
a3ddecc
Github link update
sachanayush47 Nov 18, 2024
554551f
fix: fee mechanism docs linked to zksync, google favicon shows zksync…
PrashantShaw Feb 5, 2025
8bff1aa
Merge branch 'feat/validium-based-ui' of https://github.com/Validium-…
PrashantShaw Feb 5, 2025
d8bb27c
chore: footer links update
PrashantShaw Feb 5, 2025
8762453
feat: account number
sachanayush47 Apr 3, 2025
29260bc
feat: chain stats section connected to api
PrashantShaw Apr 4, 2025
5d7b226
Merge branch 'feat/validium-based-ui' of https://github.com/Validium-…
PrashantShaw Apr 4, 2025
2597f68
fix: navbar documentation tab open validium.gitbook.io
PrashantShaw Apr 10, 2025
195f4dd
chore: update redirectionSet1 docs url
PrashantShaw Apr 10, 2025
e2e7e89
Merge remote-tracking branch 'upstream/main' into feat/validium-based-ui
sachanayush47 May 8, 2025
67867fe
fix: chain stats section with latest data
PrashantShaw May 8, 2025
a2f9752
chore: linting
sachanayush47 May 8, 2025
0a625cb
chore: linting
sachanayush47 May 8, 2025
326abf9
fix: txns render blocked
PrashantShaw May 8, 2025
498d0df
Merge branch 'feat/validium-based-ui' of https://github.com/Validium-…
PrashantShaw May 8, 2025
8bbf624
fix: og:image showing zksync-era banner
PrashantShaw Jun 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "block-explorer",
"version": "1.0.0-development",
"title": "ZKsync Era Block Explorer",
"description": "ZKsync Era Block Explorer",
"author": "Matter Labs",
"title": "Validium Block Explorer",
"description": "Validium Block Explorer",
"author": "Validium",
"license": "MIT",
"repository": "https://github.com/matter-labs/block-explorer",
"repository": "https://github.com/Validium-Chain/validium-block-explorer",
"private": true,
"workspaces": [
"packages/*"
Expand Down Expand Up @@ -48,4 +48,4 @@
"npm": ">=9.0.0",
"node": ">=18.0.0"
}
}
}
10 changes: 5 additions & 5 deletions packages/api/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "api",
"version": "0.0.0",
"title": "ZKsync Era Block Explorer API",
"description": "ZKsync Era Block Explorer API",
"author": "Matter Labs",
"title": "Validium Block Explorer API",
"description": "Validium Block Explorer API",
"author": "Validium",
"private": true,
"license": "MIT",
"repository": "https://github.com/matter-labs/block-explorer",
"repository": "https://github.com/Validium-Chain/validium-block-explorer",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
Expand Down Expand Up @@ -124,4 +124,4 @@
"npm": ">=9.0.0",
"node": ">=18.0.0"
}
}
}
2 changes: 2 additions & 0 deletions packages/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { TransferModule } from "./transfer/transfer.module";
import { TransactionModule } from "./transaction/transaction.module";
import { LogModule } from "./log/log.module";
import { StatsModule } from "./stats/stats.module";
import { DashboardModule } from "./dashboard/dashboard.module";
import { MetricsMiddleware } from "./middlewares/metrics.middleware";
import { metricProviders } from "./metrics";
import { DbMetricsService } from "./dbMetrics.service";
Expand All @@ -44,6 +45,7 @@ import config from "./config";
BalanceModule,
BatchModule,
BlockModule,
DashboardModule,
TransferModule,
TransactionModule,
LogModule,
Expand Down
14 changes: 14 additions & 0 deletions packages/api/src/balance/balance.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export class BalanceService {
private readonly balanceRepository: Repository<Balance>
) {}

public async getBalanceCount(): Promise<number> {
return this.balanceRepository.count();
}

public async getBalances(address: string): Promise<{ balances: Record<string, TokenBalance>; blockNumber: number }> {
const latestBalancesQuery = this.balanceRepository.createQueryBuilder("latest_balances");
latestBalancesQuery.select("address");
Expand Down Expand Up @@ -99,4 +103,14 @@ export class BalanceService {
const balancesRecords = await balancesQuery.getMany();
return balancesRecords;
}

public async getTotalActiveAccounts(): Promise<number> {
const query = this.balanceRepository
.createQueryBuilder("balances")
.select("COUNT(DISTINCT balances.address)", "activeCount")
.where("CAST(balances.balance AS NUMERIC) > 0");

const result = await query.getRawOne();
return parseInt(result.activeCount, 10);
}
}
32 changes: 32 additions & 0 deletions packages/api/src/dashboard/dashboard.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Controller, Get } from "@nestjs/common";
import { ApiTags, ApiOkResponse, ApiExcludeController } from "@nestjs/swagger";
import { DashboardDto } from "./dashboard.dto";
import { swagger } from "../config/featureFlags";
import { TokenService } from "src/token/token.service";
import { TransactionService } from "../transaction/transaction.service";
import { BalanceService } from "../balance/balance.service";

const entityName = "dashboard";

@ApiTags("Dashboard BFF")
@ApiExcludeController(!swagger.bffEnabled)
@Controller(entityName)
export class DashboardController {
constructor(
private readonly balanceService: BalanceService,
private readonly tokenService: TokenService,
private readonly transactionService: TransactionService
) {}

@Get()
@ApiOkResponse({ description: "Dashboard", type: DashboardDto })
public async dashboard(): Promise<DashboardDto> {
const response = {
totalAccounts: await this.balanceService.getBalanceCount(),
totalTransaction: await this.transactionService.count(),
avgGasFee: await this.transactionService.getAvgGasFeeLast24h(),
totalTokens: await this.tokenService.getTokensCount(),
};
return response;
}
}
15 changes: 15 additions & 0 deletions packages/api/src/dashboard/dashboard.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ApiProperty } from "@nestjs/swagger";

export class DashboardDto {
@ApiProperty({ type: Number, description: "Total number of accounts", example: 1000 })
public readonly totalAccounts: number;

@ApiProperty({ type: Number, description: "Total number of transactions", example: 5000 })
public readonly totalTransaction: number;

@ApiProperty({ type: Number, description: "Average gas fee", example: 0.01 })
public readonly avgGasFee: number;

@ApiProperty({ type: Number, description: "Total number of tokens", example: 300 })
public readonly totalTokens: number;
}
11 changes: 11 additions & 0 deletions packages/api/src/dashboard/dashboard.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from "@nestjs/common";
import { DashboardController } from "./dashboard.controller";
import { TokenModule } from "../token/token.module";
import { BalanceModule } from "src/balance/balance.module";
import { TransactionModule } from "../transaction/transaction.module";

@Module({
imports: [BalanceModule, TokenModule, TransactionModule],
controllers: [DashboardController],
})
export class DashboardModule {}
2 changes: 1 addition & 1 deletion packages/api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ async function bootstrap() {
if (configService.get<boolean>("featureFlags.swagger.enabled")) {
const swaggerConfig = new DocumentBuilder()
.setTitle("Block explorer API")
.setDescription("ZkSync Block Explorer API")
.setDescription("Validium Block Explorer API")
.setVersion("1.0")
.build();
const document = SwaggerModule.createDocument(app, swaggerConfig);
Expand Down
28 changes: 19 additions & 9 deletions packages/api/src/stats/stats.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Not, IsNull } from "typeorm";
import { BatchService } from "../batch/batch.service";
import { BlockService } from "../block/block.service";
import { TransactionService } from "../transaction/transaction.service";
import { BalanceService } from "../balance/balance.service";
import { StatsDto } from "./stats.dto";
import { swagger } from "../config/featureFlags";

Expand All @@ -16,27 +17,36 @@ export class StatsController {
constructor(
private readonly batchService: BatchService,
private readonly blocksService: BlockService,
private readonly transactionService: TransactionService
private readonly transactionService: TransactionService,
private readonly balanceService: BalanceService
) {}

@Get()
@ApiOkResponse({ description: "Blockchain stats", type: StatsDto })
public async stats(): Promise<StatsDto> {
const [lastSealedBatch, lastVerifiedBatch, lastSealedBlock, lastVerifiedBlock, totalTransactions] =
await Promise.all([
this.batchService.getLastBatchNumber(),
this.batchService.getLastBatchNumber({ executedAt: Not(IsNull()) }),
this.blocksService.getLastBlockNumber(),
this.blocksService.getLastVerifiedBlockNumber(),
this.transactionService.count(),
]);
const [
lastSealedBatch,
lastVerifiedBatch,
lastSealedBlock,
lastVerifiedBlock,
totalTransactions,
totalActiveAccounts,
] = await Promise.all([
this.batchService.getLastBatchNumber(),
this.batchService.getLastBatchNumber({ executedAt: Not(IsNull()) }),
this.blocksService.getLastBlockNumber(),
this.blocksService.getLastVerifiedBlockNumber(),
this.transactionService.count(),
this.balanceService.getTotalActiveAccounts(),
]);

return {
lastSealedBatch,
lastVerifiedBatch,
lastSealedBlock,
lastVerifiedBlock,
totalTransactions,
totalActiveAccounts,
};
}
}
3 changes: 3 additions & 0 deletions packages/api/src/stats/stats.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ export class StatsDto {

@ApiProperty({ type: Number, description: "The total number of processed transactions", example: 30 })
public readonly totalTransactions: number;

@ApiProperty({ type: Number, description: "The total number of active accounts with balance > 0", example: 1024 })
public readonly totalActiveAccounts: number;
}
3 changes: 2 additions & 1 deletion packages/api/src/stats/stats.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { StatsController } from "./stats.controller";
import { BatchModule } from "../batch/batch.module";
import { BlockModule } from "../block/block.module";
import { TransactionModule } from "../transaction/transaction.module";
import { BalanceModule } from "../balance/balance.module";

@Module({
imports: [BatchModule, BlockModule, TransactionModule],
imports: [BatchModule, BlockModule, TransactionModule, BalanceModule],
controllers: [StatsController],
})
export class StatsModule {}
4 changes: 4 additions & 0 deletions packages/api/src/token/token.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export class TokenService {
private readonly tokenRepository: Repository<Token>
) {}

public async getTokensCount(): Promise<number> {
return this.tokenRepository.count();
}

public async findOne(address: string, fields?: FindOptionsSelect<Token>): Promise<Token> {
const token = await this.tokenRepository.findOne({
where: {
Expand Down
11 changes: 11 additions & 0 deletions packages/api/src/transaction/transaction.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,15 @@ export class TransactionService {
public count(criteria: CounterCriteria<Transaction> = {}): Promise<number> {
return this.counterService.count(Transaction, criteria);
}
public async getAvgGasFeeLast24h(): Promise<number> {
const queryBuilder = this.transactionRepository.createQueryBuilder("transaction");
const date = new Date();
date.setDate(date.getDate() - 1);

queryBuilder.select("AVG(CAST(CONV(SUBSTRING(transaction.fee, 3), 16, 10) AS numeric))", "avgFee");
queryBuilder.where("transaction.createdAt >= :date", { date });

const result = await queryBuilder.getRawOne();
return parseFloat(result.avgFee) || 0;
}
}
56 changes: 31 additions & 25 deletions packages/app/index.html
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>ZKsync Era Block Explorer</title>
<meta charset="UTF-8" />
<meta name="description" content="ZKsync Era Block Explorer provides all the information to deep dive into transactions, blocks, contracts, and much more. Deep dive into ZKsync Era and explore the network."/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<meta property="og:title" content="ZKsync Era Block Explorer" />
<meta property="og:description" content="ZKsync Era Block Explorer provides all the information to deep dive into transactions, blocks, contracts, and much more. Deep dive into ZKsync Era and explore the network." />
<meta property="og:image" content="https://explorer.zksync.io/preview.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="ZKsync Era Block Explorer" />

<link rel="alternate icon" type="image/x-icon" href="/favicon.ico" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<head>
<title>Validium Block Explorer</title>
<meta charset="UTF-8" />
<meta name="description"
content="Validium Block Explorer provides all the information to deep dive into transactions, blocks, contracts, and much more. Deep dive into Validium and explore the network." />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<meta property="og:title" content="Validium Block Explorer" />
<meta property="og:description"
content="Validium Block Explorer provides all the information to deep dive into transactions, blocks, contracts, and much more. Deep dive into Validium and explore the network." />
<meta property="og:image" content="https://testnet.explorer.validium.network/preview.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Validium Block Explorer" />

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="true" />
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<script src="/config.js"></script>

</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
<link rel="alternate icon" type="image/x-icon" href="/validium-ico.ico" />
<link rel="icon" type="image/svg+xml" href="/validium-svg.svg" />

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="true" />
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono&family=Roboto:wght@400;700&display=swap"
rel="stylesheet">
<script src="/config.js"></script>

</head>

<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>

</html>
10 changes: 5 additions & 5 deletions packages/app/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "app",
"version": "0.0.0",
"title": "ZKsync Era Block Explorer App",
"description": "ZKsync Era Block Explorer App",
"author": "Matter Labs",
"title": "Validium Block Explorer App",
"description": "Validium Block Explorer App",
"author": "Validium",
"private": true,
"license": "MIT",
"repository": "https://github.com/matter-labs/block-explorer",
"repository": "https://github.com/Validium-Chain/validium-block-explorer",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
Expand Down Expand Up @@ -97,4 +97,4 @@
"vue-loader": "16.8.3",
"vue-tsc": "0.33.6"
}
}
}
Binary file modified packages/app/public/favicon.ico
Binary file not shown.
39 changes: 35 additions & 4 deletions packages/app/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/app/public/preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/app/public/validium-ico.ico
Binary file not shown.
Binary file added packages/app/public/validium-png.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading