psf-bch-api 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env-local +9 -0
- package/README.md +22 -0
- package/bin/server.js +24 -1
- package/package.json +6 -2
- package/src/adapters/fulcrum-api.js +124 -0
- package/src/adapters/full-node-rpc.js +2 -6
- package/src/adapters/index.js +4 -0
- package/src/adapters/slp-indexer-api.js +124 -0
- package/src/config/env/common.js +45 -24
- package/src/config/x402.js +43 -0
- package/src/controllers/index.js +3 -1
- package/src/controllers/rest-api/fulcrum/controller.js +563 -0
- package/src/controllers/rest-api/fulcrum/router.js +64 -0
- package/src/controllers/rest-api/full-node/blockchain/controller.js +26 -26
- package/src/controllers/rest-api/full-node/blockchain/{index.js → router.js} +5 -1
- package/src/controllers/rest-api/full-node/control/controller.js +68 -0
- package/src/controllers/rest-api/full-node/control/router.js +51 -0
- package/src/controllers/rest-api/full-node/dsproof/controller.js +90 -0
- package/src/controllers/rest-api/full-node/dsproof/router.js +51 -0
- package/src/controllers/rest-api/full-node/mining/controller.js +99 -0
- package/src/controllers/rest-api/full-node/mining/router.js +52 -0
- package/src/controllers/rest-api/full-node/rawtransactions/controller.js +333 -0
- package/src/controllers/rest-api/full-node/rawtransactions/router.js +58 -0
- package/src/controllers/rest-api/index.js +33 -2
- package/src/controllers/rest-api/slp/controller.js +218 -0
- package/src/controllers/rest-api/slp/router.js +55 -0
- package/src/controllers/timer-controller.js +1 -1
- package/src/use-cases/fulcrum-use-cases.js +155 -0
- package/src/use-cases/full-node-control-use-cases.js +24 -0
- package/src/use-cases/full-node-dsproof-use-cases.js +24 -0
- package/src/use-cases/full-node-mining-use-cases.js +28 -0
- package/src/use-cases/full-node-rawtransactions-use-cases.js +121 -0
- package/src/use-cases/index.js +12 -0
- package/src/use-cases/slp-use-cases.js +321 -0
- package/test/unit/controllers/blockchain-controller-unit.js +2 -3
- package/test/unit/controllers/control-controller-unit.js +88 -0
- package/test/unit/controllers/dsproof-controller-unit.js +117 -0
- package/test/unit/controllers/fulcrum-controller-unit.js +481 -0
- package/test/unit/controllers/mining-controller-unit.js +139 -0
- package/test/unit/controllers/rawtransactions-controller-unit.js +388 -0
- package/test/unit/controllers/rest-api-index-unit.js +76 -6
- package/test/unit/controllers/slp-controller-unit.js +312 -0
- package/test/unit/use-cases/fulcrum-use-cases-unit.js +297 -0
- package/test/unit/use-cases/full-node-control-use-cases-unit.js +53 -0
- package/test/unit/use-cases/full-node-dsproof-use-cases-unit.js +54 -0
- package/test/unit/use-cases/full-node-mining-use-cases-unit.js +84 -0
- package/test/unit/use-cases/full-node-rawtransactions-use-cases-unit.js +267 -0
- package/test/unit/use-cases/slp-use-cases-unit.js +296 -0
- package/src/entities/event.js +0 -71
- package/test/integration/api/event-integration.js +0 -250
- package/test/integration/api/req-integration.js +0 -173
- package/test/integration/api/subscription-integration.js +0 -198
- package/test/integration/use-cases/manage-subscription-integration.js +0 -163
- package/test/integration/use-cases/publish-event-integration.js +0 -104
- package/test/integration/use-cases/query-events-integration.js +0 -95
- package/test/unit/entities/event-unit.js +0 -139
|
@@ -48,7 +48,7 @@ class BlockchainRESTController {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
* @api {get} /full-node/blockchain/ Service status
|
|
51
|
+
* @api {get} /v6/full-node/blockchain/ Service status
|
|
52
52
|
* @apiName BlockchainRoot
|
|
53
53
|
* @apiGroup Blockchain
|
|
54
54
|
*
|
|
@@ -61,13 +61,13 @@ class BlockchainRESTController {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* @api {get} /full-node/blockchain/getBestBlockHash Get best block hash
|
|
64
|
+
* @api {get} /v6/full-node/blockchain/getBestBlockHash Get best block hash
|
|
65
65
|
* @apiName GetBestBlockHash
|
|
66
66
|
* @apiGroup Blockchain
|
|
67
67
|
* @apiDescription Returns the hash of the best (tip) block in the longest block chain.
|
|
68
68
|
*
|
|
69
69
|
* @apiExample Example usage:
|
|
70
|
-
* curl -X GET "https://api.fullstack.cash/
|
|
70
|
+
* curl -X GET "https://api.fullstack.cash/v6/full-node/blockchain/getBestBlockHash" -H "accept: application/json"
|
|
71
71
|
*
|
|
72
72
|
* @apiSuccess {String} bestBlockHash Hash of the best block
|
|
73
73
|
*/
|
|
@@ -81,7 +81,7 @@ class BlockchainRESTController {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* @api {get} /full-node/blockchain/getBlockchainInfo Get blockchain info
|
|
84
|
+
* @api {get} /v6/full-node/blockchain/getBlockchainInfo Get blockchain info
|
|
85
85
|
* @apiName GetBlockchainInfo
|
|
86
86
|
* @apiGroup Blockchain
|
|
87
87
|
* @apiDescription Returns various state info regarding blockchain processing.
|
|
@@ -96,7 +96,7 @@ class BlockchainRESTController {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* @api {get} /full-node/blockchain/getBlockCount Get block count
|
|
99
|
+
* @api {get} /v6/full-node/blockchain/getBlockCount Get block count
|
|
100
100
|
* @apiName GetBlockCount
|
|
101
101
|
* @apiGroup Blockchain
|
|
102
102
|
* @apiDescription Returns the number of blocks in the longest blockchain.
|
|
@@ -111,7 +111,7 @@ class BlockchainRESTController {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
|
-
* @api {get} /full-node/blockchain/getBlockHeader/:hash Get single block header
|
|
114
|
+
* @api {get} /v6/full-node/blockchain/getBlockHeader/:hash Get single block header
|
|
115
115
|
* @apiName GetSingleBlockHeader
|
|
116
116
|
* @apiGroup Blockchain
|
|
117
117
|
* @apiDescription Returns serialized block header data.
|
|
@@ -136,7 +136,7 @@ class BlockchainRESTController {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
/**
|
|
139
|
-
* @api {post} /full-node/blockchain/getBlockHeader Get multiple block headers
|
|
139
|
+
* @api {post} /v6/full-node/blockchain/getBlockHeader Get multiple block headers
|
|
140
140
|
* @apiName GetBulkBlockHeader
|
|
141
141
|
* @apiGroup Blockchain
|
|
142
142
|
* @apiDescription Returns serialized block header data for multiple hashes.
|
|
@@ -155,7 +155,7 @@ class BlockchainRESTController {
|
|
|
155
155
|
})
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
if (!this.adapters.fullNode.validateArraySize(hashes.length
|
|
158
|
+
if (!this.adapters.fullNode.validateArraySize(hashes.length)) {
|
|
159
159
|
return res.status(400).json({ error: 'Array too large.' })
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -173,7 +173,7 @@ class BlockchainRESTController {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
/**
|
|
176
|
-
* @api {get} /full-node/blockchain/getChainTips Get chain tips
|
|
176
|
+
* @api {get} /v6/full-node/blockchain/getChainTips Get chain tips
|
|
177
177
|
* @apiName GetChainTips
|
|
178
178
|
* @apiGroup Blockchain
|
|
179
179
|
* @apiDescription Returns information about known tips in the block tree.
|
|
@@ -188,7 +188,7 @@ class BlockchainRESTController {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
/**
|
|
191
|
-
* @api {get} /full-node/blockchain/getDifficulty Get difficulty
|
|
191
|
+
* @api {get} /v6/full-node/blockchain/getDifficulty Get difficulty
|
|
192
192
|
* @apiName GetDifficulty
|
|
193
193
|
* @apiGroup Blockchain
|
|
194
194
|
* @apiDescription Returns the current difficulty value.
|
|
@@ -203,7 +203,7 @@ class BlockchainRESTController {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
/**
|
|
206
|
-
* @api {get} /full-node/blockchain/getMempoolEntry/:txid Get single mempool entry
|
|
206
|
+
* @api {get} /v6/full-node/blockchain/getMempoolEntry/:txid Get single mempool entry
|
|
207
207
|
* @apiName GetMempoolEntry
|
|
208
208
|
* @apiGroup Blockchain
|
|
209
209
|
* @apiDescription Returns mempool data for a transaction.
|
|
@@ -223,7 +223,7 @@ class BlockchainRESTController {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
/**
|
|
226
|
-
* @api {post} /full-node/blockchain/getMempoolEntry Get bulk mempool entry
|
|
226
|
+
* @api {post} /v6/full-node/blockchain/getMempoolEntry Get bulk mempool entry
|
|
227
227
|
* @apiName GetMempoolEntryBulk
|
|
228
228
|
* @apiGroup Blockchain
|
|
229
229
|
* @apiDescription Returns mempool data for multiple transactions.
|
|
@@ -238,7 +238,7 @@ class BlockchainRESTController {
|
|
|
238
238
|
})
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
if (!this.adapters.fullNode.validateArraySize(txids.length
|
|
241
|
+
if (!this.adapters.fullNode.validateArraySize(txids.length)) {
|
|
242
242
|
return res.status(400).json({ error: 'Array too large.' })
|
|
243
243
|
}
|
|
244
244
|
|
|
@@ -256,7 +256,7 @@ class BlockchainRESTController {
|
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
/**
|
|
259
|
-
* @api {get} /full-node/blockchain/getMempoolAncestors/:txid Get mempool ancestors
|
|
259
|
+
* @api {get} /v6/full-node/blockchain/getMempoolAncestors/:txid Get mempool ancestors
|
|
260
260
|
* @apiName GetMempoolAncestors
|
|
261
261
|
* @apiGroup Blockchain
|
|
262
262
|
* @apiDescription Returns mempool ancestor data for a transaction.
|
|
@@ -281,7 +281,7 @@ class BlockchainRESTController {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
/**
|
|
284
|
-
* @api {get} /full-node/blockchain/getMempoolInfo Get mempool info
|
|
284
|
+
* @api {get} /v6/full-node/blockchain/getMempoolInfo Get mempool info
|
|
285
285
|
* @apiName GetMempoolInfo
|
|
286
286
|
* @apiGroup Blockchain
|
|
287
287
|
* @apiDescription Returns details on the state of the mempool.
|
|
@@ -296,7 +296,7 @@ class BlockchainRESTController {
|
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
/**
|
|
299
|
-
* @api {get} /full-node/blockchain/getRawMempool Get raw mempool
|
|
299
|
+
* @api {get} /v6/full-node/blockchain/getRawMempool Get raw mempool
|
|
300
300
|
* @apiName GetRawMempool
|
|
301
301
|
* @apiGroup Blockchain
|
|
302
302
|
* @apiDescription Returns all transaction ids in the mempool.
|
|
@@ -314,7 +314,7 @@ class BlockchainRESTController {
|
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
/**
|
|
317
|
-
* @api {get} /full-node/blockchain/getTxOut/:txid/:n Get transaction output
|
|
317
|
+
* @api {get} /v6/full-node/blockchain/getTxOut/:txid/:n Get transaction output
|
|
318
318
|
* @apiName GetTxOut
|
|
319
319
|
* @apiGroup Blockchain
|
|
320
320
|
* @apiDescription Returns details about an unspent transaction output.
|
|
@@ -347,7 +347,7 @@ class BlockchainRESTController {
|
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
/**
|
|
350
|
-
* @api {post} /full-node/blockchain/getTxOut Validate a UTXO
|
|
350
|
+
* @api {post} /v6/full-node/blockchain/getTxOut Validate a UTXO
|
|
351
351
|
* @apiName GetTxOutPost
|
|
352
352
|
* @apiGroup Blockchain
|
|
353
353
|
* @apiDescription Returns details about an unspent transaction output.
|
|
@@ -380,7 +380,7 @@ class BlockchainRESTController {
|
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
/**
|
|
383
|
-
* @api {get} /full-node/blockchain/getTxOutProof/:txid Get TxOut proof
|
|
383
|
+
* @api {get} /v6/full-node/blockchain/getTxOutProof/:txid Get TxOut proof
|
|
384
384
|
* @apiName GetTxOutProofSingle
|
|
385
385
|
* @apiGroup Blockchain
|
|
386
386
|
* @apiDescription Returns a hex-encoded proof that the transaction was included in a block.
|
|
@@ -400,7 +400,7 @@ class BlockchainRESTController {
|
|
|
400
400
|
}
|
|
401
401
|
|
|
402
402
|
/**
|
|
403
|
-
* @api {post} /full-node/blockchain/getTxOutProof Get TxOut proofs
|
|
403
|
+
* @api {post} /v6/full-node/blockchain/getTxOutProof Get TxOut proofs
|
|
404
404
|
* @apiName GetTxOutProofBulk
|
|
405
405
|
* @apiGroup Blockchain
|
|
406
406
|
* @apiDescription Returns hex-encoded proofs for transactions.
|
|
@@ -415,7 +415,7 @@ class BlockchainRESTController {
|
|
|
415
415
|
})
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
-
if (!this.adapters.fullNode.validateArraySize(txids.length
|
|
418
|
+
if (!this.adapters.fullNode.validateArraySize(txids.length)) {
|
|
419
419
|
return res.status(400).json({ error: 'Array too large.' })
|
|
420
420
|
}
|
|
421
421
|
|
|
@@ -435,7 +435,7 @@ class BlockchainRESTController {
|
|
|
435
435
|
}
|
|
436
436
|
|
|
437
437
|
/**
|
|
438
|
-
* @api {get} /full-node/blockchain/verifyTxOutProof/:proof Verify TxOut proof
|
|
438
|
+
* @api {get} /v6/full-node/blockchain/verifyTxOutProof/:proof Verify TxOut proof
|
|
439
439
|
* @apiName VerifyTxOutProofSingle
|
|
440
440
|
* @apiGroup Blockchain
|
|
441
441
|
* @apiDescription Verifies a hex-encoded proof was included in a block.
|
|
@@ -455,7 +455,7 @@ class BlockchainRESTController {
|
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
/**
|
|
458
|
-
* @api {post} /full-node/blockchain/verifyTxOutProof Verify TxOut proofs
|
|
458
|
+
* @api {post} /v6/full-node/blockchain/verifyTxOutProof Verify TxOut proofs
|
|
459
459
|
* @apiName VerifyTxOutProofBulk
|
|
460
460
|
* @apiGroup Blockchain
|
|
461
461
|
* @apiDescription Verifies hex-encoded proofs were included in blocks.
|
|
@@ -470,7 +470,7 @@ class BlockchainRESTController {
|
|
|
470
470
|
})
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
if (!this.adapters.fullNode.validateArraySize(proofs.length
|
|
473
|
+
if (!this.adapters.fullNode.validateArraySize(proofs.length)) {
|
|
474
474
|
return res.status(400).json({ error: 'Array too large.' })
|
|
475
475
|
}
|
|
476
476
|
|
|
@@ -490,7 +490,7 @@ class BlockchainRESTController {
|
|
|
490
490
|
}
|
|
491
491
|
|
|
492
492
|
/**
|
|
493
|
-
* @api {post} /full-node/blockchain/getBlock Get block details
|
|
493
|
+
* @api {post} /v6/full-node/blockchain/getBlock Get block details
|
|
494
494
|
* @apiName GetBlock
|
|
495
495
|
* @apiGroup Blockchain
|
|
496
496
|
* @apiDescription Returns block details for a hash.
|
|
@@ -519,7 +519,7 @@ class BlockchainRESTController {
|
|
|
519
519
|
}
|
|
520
520
|
|
|
521
521
|
/**
|
|
522
|
-
* @api {get} /full-node/blockchain/getBlockHash/:height Get block hash
|
|
522
|
+
* @api {get} /v6/full-node/blockchain/getBlockHash/:height Get block hash
|
|
523
523
|
* @apiName GetBlockHash
|
|
524
524
|
* @apiGroup Blockchain
|
|
525
525
|
* @apiDescription Returns the hash of a block by height.
|
|
@@ -28,7 +28,11 @@ class BlockchainRouter {
|
|
|
28
28
|
|
|
29
29
|
this.blockchainController = new BlockchainRESTController(dependencies)
|
|
30
30
|
|
|
31
|
-
this.
|
|
31
|
+
this.apiPrefix = (localConfig.apiPrefix || '').replace(/\/$/, '')
|
|
32
|
+
this.baseUrl = `${this.apiPrefix}/full-node/blockchain`
|
|
33
|
+
if (!this.baseUrl.startsWith('/')) {
|
|
34
|
+
this.baseUrl = `/${this.baseUrl}`
|
|
35
|
+
}
|
|
32
36
|
this.router = express.Router()
|
|
33
37
|
}
|
|
34
38
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
REST API Controller for the /full-node/control routes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import wlogger from '../../../../adapters/wlogger.js'
|
|
6
|
+
|
|
7
|
+
class ControlRESTController {
|
|
8
|
+
constructor (localConfig = {}) {
|
|
9
|
+
this.adapters = localConfig.adapters
|
|
10
|
+
if (!this.adapters) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
'Instance of Adapters library required when instantiating Control REST Controller.'
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
this.useCases = localConfig.useCases
|
|
17
|
+
if (!this.useCases || !this.useCases.control) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'Instance of Control use cases required when instantiating Control REST Controller.'
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.controlUseCases = this.useCases.control
|
|
24
|
+
|
|
25
|
+
this.root = this.root.bind(this)
|
|
26
|
+
this.getNetworkInfo = this.getNetworkInfo.bind(this)
|
|
27
|
+
this.handleError = this.handleError.bind(this)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @api {get} /v6/full-node/control/ Service status
|
|
32
|
+
* @apiName ControlRoot
|
|
33
|
+
* @apiGroup Control
|
|
34
|
+
*
|
|
35
|
+
* @apiDescription Returns the status of the control service.
|
|
36
|
+
*
|
|
37
|
+
* @apiSuccess {String} status Service identifier
|
|
38
|
+
*/
|
|
39
|
+
async root (req, res) {
|
|
40
|
+
return res.status(200).json({ status: 'control' })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @api {get} /v6/full-node/control/getNetworkInfo Get Network Info
|
|
45
|
+
* @apiName GetNetworkInfo
|
|
46
|
+
* @apiGroup Control
|
|
47
|
+
* @apiDescription RPC call that gets basic full node information.
|
|
48
|
+
*/
|
|
49
|
+
async getNetworkInfo (req, res) {
|
|
50
|
+
try {
|
|
51
|
+
const result = await this.controlUseCases.getNetworkInfo()
|
|
52
|
+
return res.status(200).json(result)
|
|
53
|
+
} catch (err) {
|
|
54
|
+
return this.handleError(err, res)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
handleError (err, res) {
|
|
59
|
+
wlogger.error('Error in ControlRESTController:', err)
|
|
60
|
+
|
|
61
|
+
const status = err.status || 500
|
|
62
|
+
const message = err.message || 'Internal server error'
|
|
63
|
+
|
|
64
|
+
return res.status(status).json({ error: message })
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default ControlRESTController
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
REST API router for /full-node/control routes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import express from 'express'
|
|
6
|
+
import ControlRESTController from './controller.js'
|
|
7
|
+
|
|
8
|
+
class ControlRouter {
|
|
9
|
+
constructor (localConfig = {}) {
|
|
10
|
+
this.adapters = localConfig.adapters
|
|
11
|
+
if (!this.adapters) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
'Instance of Adapters library required when instantiating Control REST Router.'
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
this.useCases = localConfig.useCases
|
|
18
|
+
if (!this.useCases) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
'Instance of Use Cases library required when instantiating Control REST Router.'
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const dependencies = {
|
|
25
|
+
adapters: this.adapters,
|
|
26
|
+
useCases: this.useCases
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.controlController = new ControlRESTController(dependencies)
|
|
30
|
+
|
|
31
|
+
this.apiPrefix = (localConfig.apiPrefix || '').replace(/\/$/, '')
|
|
32
|
+
this.baseUrl = `${this.apiPrefix}/full-node/control`
|
|
33
|
+
if (!this.baseUrl.startsWith('/')) {
|
|
34
|
+
this.baseUrl = `/${this.baseUrl}`
|
|
35
|
+
}
|
|
36
|
+
this.router = express.Router()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
attach (app) {
|
|
40
|
+
if (!app) {
|
|
41
|
+
throw new Error('Must pass app object when attaching REST API controllers.')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.router.get('/', this.controlController.root)
|
|
45
|
+
this.router.get('/getNetworkInfo', this.controlController.getNetworkInfo)
|
|
46
|
+
|
|
47
|
+
app.use(this.baseUrl, this.router)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default ControlRouter
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*
|
|
2
|
+
REST API Controller for the /full-node/dsproof routes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import wlogger from '../../../../adapters/wlogger.js'
|
|
6
|
+
|
|
7
|
+
class DSProofRESTController {
|
|
8
|
+
constructor (localConfig = {}) {
|
|
9
|
+
this.adapters = localConfig.adapters
|
|
10
|
+
if (!this.adapters) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
'Instance of Adapters library required when instantiating DSProof REST Controller.'
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
this.useCases = localConfig.useCases
|
|
17
|
+
if (!this.useCases || !this.useCases.dsproof) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'Instance of DSProof use cases required when instantiating DSProof REST Controller.'
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.dsproofUseCases = this.useCases.dsproof
|
|
24
|
+
|
|
25
|
+
this.root = this.root.bind(this)
|
|
26
|
+
this.getDSProof = this.getDSProof.bind(this)
|
|
27
|
+
this.handleError = this.handleError.bind(this)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @api {get} /v6/full-node/dsproof/ Service status
|
|
32
|
+
* @apiName DSProofRoot
|
|
33
|
+
* @apiGroup DSProof
|
|
34
|
+
*
|
|
35
|
+
* @apiDescription Returns the status of the dsproof service.
|
|
36
|
+
*
|
|
37
|
+
* @apiSuccess {String} status Service identifier
|
|
38
|
+
*/
|
|
39
|
+
async root (req, res) {
|
|
40
|
+
return res.status(200).json({ status: 'dsproof' })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @api {get} /v6/full-node/dsproof/getDSProof/:txid Get Double-Spend Proof
|
|
45
|
+
* @apiName GetDSProof
|
|
46
|
+
* @apiGroup DSProof
|
|
47
|
+
* @apiDescription Get information for a double-spend proof.
|
|
48
|
+
*
|
|
49
|
+
* @apiParam {String} txid Transaction ID
|
|
50
|
+
* @apiParam {String} verbose Verbose level (`false`, `true`) for compatibility with legacy API
|
|
51
|
+
*/
|
|
52
|
+
async getDSProof (req, res) {
|
|
53
|
+
try {
|
|
54
|
+
const txid = req.params.txid
|
|
55
|
+
|
|
56
|
+
if (!txid) {
|
|
57
|
+
return res.status(400).json({
|
|
58
|
+
success: false,
|
|
59
|
+
error: 'txid can not be empty'
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (txid.length !== 64) {
|
|
64
|
+
return res.status(400).json({
|
|
65
|
+
success: false,
|
|
66
|
+
error: `txid must be of length 64 (not ${txid.length})`
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let verbose = 2
|
|
71
|
+
if (req.query.verbose === 'true') verbose = 3
|
|
72
|
+
|
|
73
|
+
const result = await this.dsproofUseCases.getDSProof({ txid, verbose })
|
|
74
|
+
return res.status(200).json(result)
|
|
75
|
+
} catch (err) {
|
|
76
|
+
return this.handleError(err, res)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
handleError (err, res) {
|
|
81
|
+
wlogger.error('Error in DSProofRESTController:', err)
|
|
82
|
+
|
|
83
|
+
const status = err.status || 500
|
|
84
|
+
const message = err.message || 'Internal server error'
|
|
85
|
+
|
|
86
|
+
return res.status(status).json({ error: message })
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default DSProofRESTController
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
REST API router for /full-node/dsproof routes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import express from 'express'
|
|
6
|
+
import DSProofRESTController from './controller.js'
|
|
7
|
+
|
|
8
|
+
class DSProofRouter {
|
|
9
|
+
constructor (localConfig = {}) {
|
|
10
|
+
this.adapters = localConfig.adapters
|
|
11
|
+
if (!this.adapters) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
'Instance of Adapters library required when instantiating DSProof REST Router.'
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
this.useCases = localConfig.useCases
|
|
18
|
+
if (!this.useCases) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
'Instance of Use Cases library required when instantiating DSProof REST Router.'
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const dependencies = {
|
|
25
|
+
adapters: this.adapters,
|
|
26
|
+
useCases: this.useCases
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.dsproofController = new DSProofRESTController(dependencies)
|
|
30
|
+
|
|
31
|
+
this.apiPrefix = (localConfig.apiPrefix || '').replace(/\/$/, '')
|
|
32
|
+
this.baseUrl = `${this.apiPrefix}/full-node/dsproof`
|
|
33
|
+
if (!this.baseUrl.startsWith('/')) {
|
|
34
|
+
this.baseUrl = `/${this.baseUrl}`
|
|
35
|
+
}
|
|
36
|
+
this.router = express.Router()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
attach (app) {
|
|
40
|
+
if (!app) {
|
|
41
|
+
throw new Error('Must pass app object when attaching REST API controllers.')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.router.get('/', this.dsproofController.root)
|
|
45
|
+
this.router.get('/getDSProof/:txid', this.dsproofController.getDSProof)
|
|
46
|
+
|
|
47
|
+
app.use(this.baseUrl, this.router)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default DSProofRouter
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/*
|
|
2
|
+
REST API Controller for the /full-node/mining routes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import wlogger from '../../../../adapters/wlogger.js'
|
|
6
|
+
|
|
7
|
+
class MiningRESTController {
|
|
8
|
+
constructor (localConfig = {}) {
|
|
9
|
+
this.adapters = localConfig.adapters
|
|
10
|
+
if (!this.adapters) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
'Instance of Adapters library required when instantiating Mining REST Controller.'
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
this.useCases = localConfig.useCases
|
|
17
|
+
if (!this.useCases || !this.useCases.mining) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'Instance of Mining use cases required when instantiating Mining REST Controller.'
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.miningUseCases = this.useCases.mining
|
|
24
|
+
|
|
25
|
+
// Bind functions
|
|
26
|
+
this.root = this.root.bind(this)
|
|
27
|
+
this.getMiningInfo = this.getMiningInfo.bind(this)
|
|
28
|
+
this.getNetworkHashPS = this.getNetworkHashPS.bind(this)
|
|
29
|
+
this.handleError = this.handleError.bind(this)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @api {get} /v6/full-node/mining/ Service status
|
|
34
|
+
* @apiName MiningRoot
|
|
35
|
+
* @apiGroup Mining
|
|
36
|
+
*
|
|
37
|
+
* @apiDescription Returns the status of the mining service.
|
|
38
|
+
*
|
|
39
|
+
* @apiSuccess {String} status Service identifier
|
|
40
|
+
*/
|
|
41
|
+
async root (req, res) {
|
|
42
|
+
return res.status(200).json({ status: 'mining' })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @api {get} /v6/full-node/mining/getMiningInfo Get Mining Info
|
|
47
|
+
* @apiName GetMiningInfo
|
|
48
|
+
* @apiGroup Mining
|
|
49
|
+
* @apiDescription Returns a json object containing mining-related information.
|
|
50
|
+
*
|
|
51
|
+
* @apiExample Example usage:
|
|
52
|
+
* curl -X GET "https://api.fullstack.cash/v6/full-node/mining/getMiningInfo" -H "accept: application/json"
|
|
53
|
+
*/
|
|
54
|
+
async getMiningInfo (req, res) {
|
|
55
|
+
try {
|
|
56
|
+
const result = await this.miningUseCases.getMiningInfo()
|
|
57
|
+
return res.status(200).json(result)
|
|
58
|
+
} catch (err) {
|
|
59
|
+
return this.handleError(err, res)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @api {get} /v6/full-node/mining/getNetworkHashPS Get Estimated network hashes per second
|
|
65
|
+
* @apiName GetNetworkHashPS
|
|
66
|
+
* @apiGroup Mining
|
|
67
|
+
* @apiDescription Returns the estimated network hashes per second based on the last n blocks. Pass in [nblocks] to override # of blocks, -1 specifies since last difficulty change. Pass in [height] to estimate the network speed at the time when a certain block was found.
|
|
68
|
+
*
|
|
69
|
+
* @apiParam {Number} nblocks Number of blocks to use for estimation (default: 120)
|
|
70
|
+
* @apiParam {Number} height Block height to estimate at (default: -1)
|
|
71
|
+
*
|
|
72
|
+
* @apiExample Example usage:
|
|
73
|
+
* curl -X GET "https://api.fullstack.cash/v6/full-node/mining/getNetworkHashPS?nblocks=120&height=-1" -H "accept: application/json"
|
|
74
|
+
*/
|
|
75
|
+
async getNetworkHashPS (req, res) {
|
|
76
|
+
try {
|
|
77
|
+
let nblocks = 120 // Default
|
|
78
|
+
let height = -1 // Default
|
|
79
|
+
if (req.query.nblocks) nblocks = parseInt(req.query.nblocks)
|
|
80
|
+
if (req.query.height) height = parseInt(req.query.height)
|
|
81
|
+
|
|
82
|
+
const result = await this.miningUseCases.getNetworkHashPS({ nblocks, height })
|
|
83
|
+
return res.status(200).json(result)
|
|
84
|
+
} catch (err) {
|
|
85
|
+
return this.handleError(err, res)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
handleError (err, res) {
|
|
90
|
+
wlogger.error('Error in MiningRESTController:', err)
|
|
91
|
+
|
|
92
|
+
const status = err.status || 500
|
|
93
|
+
const message = err.message || 'Internal server error'
|
|
94
|
+
|
|
95
|
+
return res.status(status).json({ error: message })
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export default MiningRESTController
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
REST API router for /full-node/mining routes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import express from 'express'
|
|
6
|
+
import MiningRESTController from './controller.js'
|
|
7
|
+
|
|
8
|
+
class MiningRouter {
|
|
9
|
+
constructor (localConfig = {}) {
|
|
10
|
+
this.adapters = localConfig.adapters
|
|
11
|
+
if (!this.adapters) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
'Instance of Adapters library required when instantiating Mining REST Router.'
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
this.useCases = localConfig.useCases
|
|
18
|
+
if (!this.useCases) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
'Instance of Use Cases library required when instantiating Mining REST Router.'
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const dependencies = {
|
|
25
|
+
adapters: this.adapters,
|
|
26
|
+
useCases: this.useCases
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.miningController = new MiningRESTController(dependencies)
|
|
30
|
+
|
|
31
|
+
this.apiPrefix = (localConfig.apiPrefix || '').replace(/\/$/, '')
|
|
32
|
+
this.baseUrl = `${this.apiPrefix}/full-node/mining`
|
|
33
|
+
if (!this.baseUrl.startsWith('/')) {
|
|
34
|
+
this.baseUrl = `/${this.baseUrl}`
|
|
35
|
+
}
|
|
36
|
+
this.router = express.Router()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
attach (app) {
|
|
40
|
+
if (!app) {
|
|
41
|
+
throw new Error('Must pass app object when attaching REST API controllers.')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.router.get('/', this.miningController.root)
|
|
45
|
+
this.router.get('/getMiningInfo', this.miningController.getMiningInfo)
|
|
46
|
+
this.router.get('/getNetworkHashPS', this.miningController.getNetworkHashPS)
|
|
47
|
+
|
|
48
|
+
app.use(this.baseUrl, this.router)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default MiningRouter
|