1
1
const express = require ( 'express' ) ;
2
2
const router = express . Router ( ) ;
3
+ const { Block } = require ( '../utils/db' ) ;
4
+ const NodeCache = require ( 'node-cache' ) ;
3
5
4
- // 获取区块信息
6
+ // 创建缓存实例,默认缓存时间10分钟
7
+ const cache = new NodeCache ( { stdTTL : 600 } ) ;
8
+
9
+ /**
10
+ * @api {get } /block/:blockNumber 获取区块信息
11
+ * @apiName GetBlock
12
+ * @apiGroup Blockchain
13
+ * @apiParam {Number} blockNumber 区块号
14
+ * @apiSuccess {Boolean} success 请求是否成功
15
+ * @apiSuccess {Object} data 区块数据
16
+ */
5
17
router . get ( '/block/:blockNumber' , async ( req , res ) => {
6
18
try {
7
- const blockNumber = req . params . blockNumber ;
8
- // TODO: 从数据库获取区块信息
9
- const blockInfo = { } ; // 替换为实际的数据库查询
19
+ const blockNumber = parseInt ( req . params . blockNumber ) ;
20
+
21
+ // 参数验证
22
+ if ( isNaN ( blockNumber ) || blockNumber < 0 ) {
23
+ return res . status ( 400 ) . json ( {
24
+ success : false ,
25
+ error : '无效的区块号'
26
+ } ) ;
27
+ }
28
+
29
+ // 检查缓存
30
+ const cacheKey = `block_${ blockNumber } ` ;
31
+ const cachedBlock = cache . get ( cacheKey ) ;
32
+ if ( cachedBlock ) {
33
+ return res . json ( {
34
+ success : true ,
35
+ data : cachedBlock
36
+ } ) ;
37
+ }
38
+
39
+ // 从数据库获取区块信息
40
+ const blockInfo = await Block . findOne ( { number : blockNumber } ) ;
41
+ if ( ! blockInfo ) {
42
+ return res . status ( 404 ) . json ( {
43
+ success : false ,
44
+ error : '区块未找到'
45
+ } ) ;
46
+ }
47
+
48
+ // 设置缓存
49
+ cache . set ( cacheKey , blockInfo )
10
50
res . json ( {
11
51
success : true ,
12
52
data : blockInfo
@@ -19,12 +59,49 @@ router.get('/block/:blockNumber', async (req, res) => {
19
59
}
20
60
} ) ;
21
61
22
- // 获取交易信息
62
+ /**
63
+ * @api {get } /transaction/:txHash 获取交易信息
64
+ * @apiName GetTransaction
65
+ * @apiGroup Blockchain
66
+ * @apiParam {String} txHash 交易哈希
67
+ * @apiSuccess {Boolean} success 请求是否成功
68
+ * @apiSuccess {Object} data 交易数据
69
+ */
23
70
router . get ( '/transaction/:txHash' , async ( req , res ) => {
24
71
try {
25
72
const txHash = req . params . txHash ;
26
- // TODO: 从数据库获取交易信息
27
- const txInfo = { } ; // 替换为实际的数据库查询
73
+
74
+ // 参数验证
75
+ if ( ! / ^ 0 x [ 0 - 9 a - f A - F ] { 64 } $ / . test ( txHash ) ) {
76
+ return res . status ( 400 ) . json ( {
77
+ success : false ,
78
+ error : '无效的交易哈希'
79
+ } ) ;
80
+ }
81
+
82
+ // 检查缓存
83
+ const cacheKey = `tx_${ txHash } ` ;
84
+ const cachedTx = cache . get ( cacheKey ) ;
85
+ if ( cachedTx ) {
86
+ return res . json ( {
87
+ success : true ,
88
+ data : cachedTx
89
+ } ) ;
90
+ }
91
+
92
+ // 从数据库获取交易信息
93
+ const block = await Block . findOne ( { 'transactions.hash' : txHash } ) ;
94
+ const txInfo = block ? block . transactions . find ( tx => tx . hash === txHash ) : null ;
95
+
96
+ if ( ! txInfo ) {
97
+ return res . status ( 404 ) . json ( {
98
+ success : false ,
99
+ error : '交易未找到'
100
+ } ) ;
101
+ }
102
+
103
+ // 设置缓存
104
+ cache . set ( cacheKey , txInfo )
28
105
res . json ( {
29
106
success : true ,
30
107
data : txInfo
@@ -37,16 +114,80 @@ router.get('/transaction/:txHash', async (req, res) => {
37
114
}
38
115
} ) ;
39
116
40
- // 获取地址的交易历史
117
+ /**
118
+ * @api {get } /address/:address/transactions 获取地址的交易历史
119
+ * @apiName GetAddressTransactions
120
+ * @apiGroup Blockchain
121
+ * @apiParam {String} address 以太坊地址
122
+ * @apiParam {Number} [page=1] 页码
123
+ * @apiParam {Number} [limit=10] 每页记录数
124
+ * @apiSuccess {Boolean} success 请求是否成功
125
+ * @apiSuccess {Object} data 交易列表和分页信息
126
+ */
41
127
router . get ( '/address/:address/transactions' , async ( req , res ) => {
42
128
try {
43
129
const address = req . params . address ;
44
130
const page = parseInt ( req . query . page ) || 1 ;
45
131
const limit = parseInt ( req . query . limit ) || 10 ;
46
132
47
- // TODO: 从数据库获取地址的交易历史
48
- const transactions = [ ] ; // 替换为实际的数据库查询
49
- const total = 0 ; // 替换为实际的总记录数
133
+ // 参数验证
134
+ if ( ! / ^ 0 x [ 0 - 9 a - f A - F ] { 40 } $ / . test ( address ) ) {
135
+ return res . status ( 400 ) . json ( {
136
+ success : false ,
137
+ error : '无效的以太坊地址'
138
+ } ) ;
139
+ }
140
+
141
+ if ( page < 1 || limit < 1 || limit > 100 ) {
142
+ return res . status ( 400 ) . json ( {
143
+ success : false ,
144
+ error : '无效的分页参数'
145
+ } ) ;
146
+ }
147
+
148
+ // 检查缓存
149
+ const cacheKey = `addr_tx_${ address } _${ page } _${ limit } ` ;
150
+ const cachedResult = cache . get ( cacheKey ) ;
151
+ if ( cachedResult ) {
152
+ return res . json ( {
153
+ success : true ,
154
+ data : cachedResult
155
+ } ) ;
156
+ }
157
+
158
+ // 从数据库获取地址的交易历史
159
+ const query = {
160
+ $or : [
161
+ { 'transactions.from' : address } ,
162
+ { 'transactions.to' : address }
163
+ ]
164
+ } ;
165
+
166
+ const blocks = await Block . find ( query )
167
+ . sort ( { timestamp : - 1 } )
168
+ . skip ( ( page - 1 ) * limit )
169
+ . limit ( limit ) ;
170
+
171
+ const transactions = blocks . reduce ( ( txs , block ) => {
172
+ const addressTxs = block . transactions . filter ( tx =>
173
+ tx . from === address || tx . to === address
174
+ ) ;
175
+ return [ ...txs , ...addressTxs ] ;
176
+ } , [ ] ) ;
177
+
178
+ const total = await Block . countDocuments ( query ) ;
179
+
180
+ const result = {
181
+ transactions,
182
+ pagination : {
183
+ page,
184
+ limit,
185
+ total
186
+ }
187
+ } ;
188
+
189
+ // 设置缓存
190
+ cache . set ( cacheKey , result )
50
191
51
192
res . json ( {
52
193
success : true ,
0 commit comments