Skip to content

Commit c890e61

Browse files
committed
feat: enhance blockchain indexer API functionality
1 parent 10a30c7 commit c890e61

File tree

1 file changed

+103
-16
lines changed

1 file changed

+103
-16
lines changed

basic/83-blockchain-indexer/src/api/routes.js

+103-16
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
const express = require('express');
22
const router = express.Router();
3+
const Block = require('../models/Block');
34

45
// 获取区块信息
56
router.get('/block/:blockNumber', async (req, res) => {
67
try {
7-
const blockNumber = req.params.blockNumber;
8-
// TODO: 从数据库获取区块信息
9-
const blockInfo = {}; // 替换为实际的数据库查询
8+
const blockNumber = parseInt(req.params.blockNumber);
9+
const blockInfo = await Block.findOne({ number: blockNumber });
10+
11+
if (!blockInfo) {
12+
return res.status(404).json({
13+
success: false,
14+
error: '区块未找到'
15+
});
16+
}
17+
1018
res.json({
1119
success: true,
1220
data: blockInfo
@@ -23,8 +31,16 @@ router.get('/block/:blockNumber', async (req, res) => {
2331
router.get('/transaction/:txHash', async (req, res) => {
2432
try {
2533
const txHash = req.params.txHash;
26-
// TODO: 从数据库获取交易信息
27-
const txInfo = {}; // 替换为实际的数据库查询
34+
const block = await Block.findOne({ 'transactions.hash': txHash });
35+
36+
if (!block) {
37+
return res.status(404).json({
38+
success: false,
39+
error: '交易未找到'
40+
});
41+
}
42+
43+
const txInfo = block.transactions.find(tx => tx.hash === txHash);
2844
res.json({
2945
success: true,
3046
data: txInfo
@@ -40,13 +56,34 @@ router.get('/transaction/:txHash', async (req, res) => {
4056
// 获取地址的交易历史
4157
router.get('/address/:address/transactions', async (req, res) => {
4258
try {
43-
const address = req.params.address;
59+
const address = req.params.address.toLowerCase();
4460
const page = parseInt(req.query.page) || 1;
4561
const limit = parseInt(req.query.limit) || 10;
62+
const skip = (page - 1) * limit;
4663

47-
// TODO: 从数据库获取地址的交易历史
48-
const transactions = []; // 替换为实际的数据库查询
49-
const total = 0; // 替换为实际的总记录数
64+
const query = {
65+
$or: [
66+
{ 'transactions.from': address },
67+
{ 'transactions.to': address }
68+
]
69+
};
70+
71+
const [blocks, total] = await Promise.all([
72+
Block.find(query)
73+
.sort({ number: -1 })
74+
.skip(skip)
75+
.limit(limit),
76+
Block.countDocuments(query)
77+
]);
78+
79+
const transactions = blocks.reduce((acc, block) => {
80+
return acc.concat(
81+
block.transactions.filter(tx =>
82+
tx.from.toLowerCase() === address ||
83+
(tx.to && tx.to.toLowerCase() === address)
84+
)
85+
);
86+
}, []);
5087

5188
res.json({
5289
success: true,
@@ -71,8 +108,10 @@ router.get('/address/:address/transactions', async (req, res) => {
71108
router.get('/blocks/latest', async (req, res) => {
72109
try {
73110
const limit = parseInt(req.query.limit) || 10;
74-
// TODO: 从数据库获取最新的区块列表
75-
const blocks = []; // 替换为实际的数据库查询
111+
const blocks = await Block.find()
112+
.sort({ number: -1 })
113+
.limit(limit)
114+
.select('-transactions');
76115

77116
res.json({
78117
success: true,
@@ -90,8 +129,14 @@ router.get('/blocks/latest', async (req, res) => {
90129
router.get('/transactions/latest', async (req, res) => {
91130
try {
92131
const limit = parseInt(req.query.limit) || 10;
93-
// TODO: 从数据库获取最新的交易列表
94-
const transactions = []; // 替换为实际的数据库查询
132+
const blocks = await Block.find()
133+
.sort({ number: -1 })
134+
.limit(Math.ceil(limit / 2))
135+
.select('transactions');
136+
137+
const transactions = blocks.reduce((acc, block) => {
138+
return acc.concat(block.transactions);
139+
}, []).slice(0, limit);
95140

96141
res.json({
97142
success: true,
@@ -109,11 +154,52 @@ router.get('/transactions/latest', async (req, res) => {
109154
router.get('/search/:query', async (req, res) => {
110155
try {
111156
const query = req.params.query;
112-
// TODO: 实现搜索逻辑
113-
const result = {
114-
type: '', // 'block', 'transaction', 'address'
157+
let result = {
158+
type: '',
115159
data: null
116160
};
161+
162+
// 尝试作为区块号搜索
163+
if (/^\d+$/.test(query)) {
164+
const block = await Block.findOne({ number: parseInt(query) });
165+
if (block) {
166+
result = { type: 'block', data: block };
167+
}
168+
}
169+
170+
// 尝试作为交易哈希搜索
171+
if (!result.data && /^0x[a-fA-F0-9]{64}$/.test(query)) {
172+
const block = await Block.findOne({ 'transactions.hash': query });
173+
if (block) {
174+
const transaction = block.transactions.find(tx => tx.hash === query);
175+
if (transaction) {
176+
result = { type: 'transaction', data: transaction };
177+
}
178+
}
179+
}
180+
181+
// 尝试作为地址搜索
182+
if (!result.data && /^0x[a-fA-F0-9]{40}$/.test(query)) {
183+
const address = query.toLowerCase();
184+
const blocks = await Block.find({
185+
$or: [
186+
{ 'transactions.from': address },
187+
{ 'transactions.to': address }
188+
]
189+
}).limit(10);
190+
191+
if (blocks.length > 0) {
192+
const transactions = blocks.reduce((acc, block) => {
193+
return acc.concat(
194+
block.transactions.filter(tx =>
195+
tx.from.toLowerCase() === address ||
196+
(tx.to && tx.to.toLowerCase() === address)
197+
)
198+
);
199+
}, []);
200+
result = { type: 'address', data: transactions };
201+
}
202+
}
117203

118204
res.json({
119205
success: true,
@@ -127,4 +213,5 @@ router.get('/search/:query', async (req, res) => {
127213
}
128214
});
129215

216+
130217
module.exports = router;

0 commit comments

Comments
 (0)