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.
Files changed (56) hide show
  1. package/.env-local +9 -0
  2. package/README.md +22 -0
  3. package/bin/server.js +24 -1
  4. package/package.json +6 -2
  5. package/src/adapters/fulcrum-api.js +124 -0
  6. package/src/adapters/full-node-rpc.js +2 -6
  7. package/src/adapters/index.js +4 -0
  8. package/src/adapters/slp-indexer-api.js +124 -0
  9. package/src/config/env/common.js +45 -24
  10. package/src/config/x402.js +43 -0
  11. package/src/controllers/index.js +3 -1
  12. package/src/controllers/rest-api/fulcrum/controller.js +563 -0
  13. package/src/controllers/rest-api/fulcrum/router.js +64 -0
  14. package/src/controllers/rest-api/full-node/blockchain/controller.js +26 -26
  15. package/src/controllers/rest-api/full-node/blockchain/{index.js → router.js} +5 -1
  16. package/src/controllers/rest-api/full-node/control/controller.js +68 -0
  17. package/src/controllers/rest-api/full-node/control/router.js +51 -0
  18. package/src/controllers/rest-api/full-node/dsproof/controller.js +90 -0
  19. package/src/controllers/rest-api/full-node/dsproof/router.js +51 -0
  20. package/src/controllers/rest-api/full-node/mining/controller.js +99 -0
  21. package/src/controllers/rest-api/full-node/mining/router.js +52 -0
  22. package/src/controllers/rest-api/full-node/rawtransactions/controller.js +333 -0
  23. package/src/controllers/rest-api/full-node/rawtransactions/router.js +58 -0
  24. package/src/controllers/rest-api/index.js +33 -2
  25. package/src/controllers/rest-api/slp/controller.js +218 -0
  26. package/src/controllers/rest-api/slp/router.js +55 -0
  27. package/src/controllers/timer-controller.js +1 -1
  28. package/src/use-cases/fulcrum-use-cases.js +155 -0
  29. package/src/use-cases/full-node-control-use-cases.js +24 -0
  30. package/src/use-cases/full-node-dsproof-use-cases.js +24 -0
  31. package/src/use-cases/full-node-mining-use-cases.js +28 -0
  32. package/src/use-cases/full-node-rawtransactions-use-cases.js +121 -0
  33. package/src/use-cases/index.js +12 -0
  34. package/src/use-cases/slp-use-cases.js +321 -0
  35. package/test/unit/controllers/blockchain-controller-unit.js +2 -3
  36. package/test/unit/controllers/control-controller-unit.js +88 -0
  37. package/test/unit/controllers/dsproof-controller-unit.js +117 -0
  38. package/test/unit/controllers/fulcrum-controller-unit.js +481 -0
  39. package/test/unit/controllers/mining-controller-unit.js +139 -0
  40. package/test/unit/controllers/rawtransactions-controller-unit.js +388 -0
  41. package/test/unit/controllers/rest-api-index-unit.js +76 -6
  42. package/test/unit/controllers/slp-controller-unit.js +312 -0
  43. package/test/unit/use-cases/fulcrum-use-cases-unit.js +297 -0
  44. package/test/unit/use-cases/full-node-control-use-cases-unit.js +53 -0
  45. package/test/unit/use-cases/full-node-dsproof-use-cases-unit.js +54 -0
  46. package/test/unit/use-cases/full-node-mining-use-cases-unit.js +84 -0
  47. package/test/unit/use-cases/full-node-rawtransactions-use-cases-unit.js +267 -0
  48. package/test/unit/use-cases/slp-use-cases-unit.js +296 -0
  49. package/src/entities/event.js +0 -71
  50. package/test/integration/api/event-integration.js +0 -250
  51. package/test/integration/api/req-integration.js +0 -173
  52. package/test/integration/api/subscription-integration.js +0 -198
  53. package/test/integration/use-cases/manage-subscription-integration.js +0 -163
  54. package/test/integration/use-cases/publish-event-integration.js +0 -104
  55. package/test/integration/use-cases/query-events-integration.js +0 -95
  56. 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/v5/blockchain/getBestBlockHash" -H "accept: application/json"
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, { isProUser: Boolean(req.locals?.proLimit) })) {
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, { isProUser: Boolean(req.locals?.proLimit) })) {
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, { isProUser: Boolean(req.locals?.proLimit) })) {
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, { isProUser: Boolean(req.locals?.proLimit) })) {
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.baseUrl = '/full-node/blockchain'
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