@dashevo/dapi-client 0.22.0-dev.7 → 0.22.0-dev.8

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.
@@ -0,0 +1,121 @@
1
+ const EventEmitter = require('events');
2
+ const { SpvChain } = require('@dashevo/dash-spv');
3
+
4
+ const BlockHeadersReader = require('./BlockHeadersReader');
5
+
6
+ /**
7
+ * @typedef {BlockHeadersProviderOptions} BlockHeadersProviderOptions
8
+ * @property {string} [network=testnet]
9
+ * @property {number} [maxParallelStreams=5] max parallel streams to read historical block headers
10
+ * @property {number} [targetBatchSize=100000] a target batch size per stream
11
+ * @property {number} [maxRetries=10] max amount of retries per stream connection
12
+ * @property {number} [autoStart=false] auto start fetching verifying block headers
13
+ */
14
+ const defaultOptions = {
15
+ network: 'testnet',
16
+ maxParallelStreams: 5,
17
+ targetBatchSize: 100000,
18
+ fromBlockHeight: 1,
19
+ maxRetries: 10,
20
+ autoStart: false,
21
+ };
22
+
23
+ const EVENTS = {
24
+ ERROR: 'error',
25
+ };
26
+
27
+ class BlockHeadersProvider extends EventEmitter {
28
+ /**
29
+ * @param {BlockHeadersProviderOptions} options
30
+ */
31
+ constructor(options = {}) {
32
+ super();
33
+ this.options = {
34
+ ...defaultOptions,
35
+ ...options,
36
+ };
37
+
38
+ this.spvChain = new SpvChain(this.options.network);
39
+ this.started = false;
40
+ }
41
+
42
+ /**
43
+ * @param {CoreMethodsFacade} coreMethods
44
+ */
45
+ setCoreMethods(coreMethods) {
46
+ this.coreMethods = coreMethods;
47
+ }
48
+
49
+ /**
50
+ * @param {BlockHeadersReader} blockHeadersReader
51
+ */
52
+ setBlockHeadersReader(blockHeadersReader) {
53
+ this.blockHeadersReader = blockHeadersReader;
54
+ }
55
+
56
+ /**
57
+ *
58
+ * @param spvChain
59
+ */
60
+ setSpvChain(spvChain) {
61
+ this.spvChain = spvChain;
62
+ }
63
+
64
+ async start() {
65
+ if (!this.coreMethods) {
66
+ throw new Error('Core methods have not been provided. Please use "setCoreMethods"');
67
+ }
68
+
69
+ if (this.started) {
70
+ throw new Error('BlockHeaderProvider has already been started');
71
+ }
72
+
73
+ const { chain: { blocksCount: bestBlockHeight } } = await this.coreMethods.getStatus();
74
+
75
+ if (!this.blockHeadersReader) {
76
+ this.blockHeadersReader = new BlockHeadersReader(
77
+ {
78
+ coreMethods: this.coreMethods,
79
+ maxParallelStreams: this.options.maxParallelStreams,
80
+ targetBatchSize: this.options.targetBatchSize,
81
+ maxRetries: this.options.maxRetries,
82
+ },
83
+ );
84
+ }
85
+
86
+ this.blockHeadersReader.on(BlockHeadersReader.EVENTS.ERROR, (e) => {
87
+ this.emit(EVENTS.ERROR, e);
88
+ });
89
+
90
+ this.blockHeadersReader.on(BlockHeadersReader.EVENTS.HISTORICAL_DATA_OBTAINED, () => {
91
+ this.blockHeadersReader.subscribeToNew(bestBlockHeight)
92
+ .catch((e) => {
93
+ this.emit(EVENTS.ERROR, e);
94
+ });
95
+ });
96
+
97
+ this.blockHeadersReader.on(BlockHeadersReader.EVENTS.BLOCK_HEADERS, (headers, reject) => {
98
+ try {
99
+ this.spvChain.addHeaders(headers.map((header) => Buffer.from(header)));
100
+ } catch (e) {
101
+ if (e.message === 'Some headers are invalid') {
102
+ reject(e);
103
+ } else {
104
+ this.emit(EVENTS.ERROR, e);
105
+ }
106
+ }
107
+ });
108
+
109
+ await this.blockHeadersReader.readHistorical(
110
+ this.options.fromBlockHeight,
111
+ bestBlockHeight - 1,
112
+ );
113
+
114
+ this.started = true;
115
+ }
116
+ }
117
+
118
+ BlockHeadersProvider.EVENTS = EVENTS;
119
+ BlockHeadersProvider.defaultOptions = defaultOptions;
120
+
121
+ module.exports = BlockHeadersProvider;
@@ -0,0 +1,229 @@
1
+ const { EventEmitter } = require('events');
2
+
3
+ const EVENTS = {
4
+ BLOCK_HEADERS: 'BLOCK_HEADERS',
5
+ HISTORICAL_DATA_OBTAINED: 'HISTORICAL_DATA_OBTAINED',
6
+ ERROR: 'error',
7
+ };
8
+
9
+ const COMMANDS = {
10
+ HANDLE_FINISHED_STREAM: 'HANDLE_FINISHED_STREAM',
11
+ HANDLE_STREAM_RETRY: 'HANDLE_STREAM_RETRY',
12
+ HANDLE_STREAM_ERROR: 'HANDLE_STREAM_ERROR',
13
+ };
14
+
15
+ /**
16
+ * @typedef BlockHeadersReaderOptions
17
+ * @property {CoreMethodsFacade} [coreMethods]
18
+ * @property {number} [maxParallelStreams]
19
+ * @property {number} [targetBatchSize]
20
+ * @property {number} [maxRetries]
21
+ */
22
+
23
+ class BlockHeadersReader extends EventEmitter {
24
+ /**
25
+ * @param {BlockHeadersReaderOptions} options
26
+ */
27
+ constructor(options = {}) {
28
+ super();
29
+ this.coreMethods = options.coreMethods;
30
+ this.maxParallelStreams = options.maxParallelStreams;
31
+ this.targetBatchSize = options.targetBatchSize;
32
+ this.maxRetries = options.maxRetries;
33
+
34
+ /**
35
+ * Holds references to the historical streams
36
+ *
37
+ * @type {*[]}
38
+ */
39
+ this.historicalStreams = [];
40
+ }
41
+
42
+ /**
43
+ * Reads historical block heights using multiple streams
44
+ *
45
+ * @param {number} fromBlockHeight
46
+ * @param {number} toBlockHeight
47
+ * @returns {Promise<void>}
48
+ */
49
+ async readHistorical(fromBlockHeight, toBlockHeight) {
50
+ if (this.historicalStreams.length) {
51
+ throw new Error('Historical streams are already running');
52
+ }
53
+
54
+ const totalAmount = toBlockHeight - fromBlockHeight + 1;
55
+ if (totalAmount === 0) {
56
+ return;
57
+ }
58
+
59
+ if (totalAmount < 0) {
60
+ throw new Error(`Invalid total amount of headers to read: ${totalAmount}`);
61
+ }
62
+
63
+ // Resubscribe to the stream in case of error, and replace the stream in the array
64
+ this.on(COMMANDS.HANDLE_STREAM_RETRY, (oldStream, newStream) => {
65
+ const index = this.historicalStreams.indexOf(oldStream);
66
+ this.historicalStreams[index] = newStream;
67
+ });
68
+
69
+ // Remove stream from the array in case of error
70
+ this.on(COMMANDS.HANDLE_STREAM_ERROR, (stream, e) => {
71
+ const index = this.historicalStreams.indexOf(stream);
72
+ this.historicalStreams.splice(index, 1);
73
+ this.emit(EVENTS.ERROR, e);
74
+ });
75
+
76
+ // Remove finished stream from the array and emit HISTORICAL_DATA_OBTAINED event
77
+ this.on(COMMANDS.HANDLE_FINISHED_STREAM, (stream) => {
78
+ const index = this.historicalStreams.indexOf(stream);
79
+ this.historicalStreams.splice(index, 1);
80
+ if (this.historicalStreams.length === 0) {
81
+ this.emit(EVENTS.HISTORICAL_DATA_OBTAINED);
82
+ }
83
+ });
84
+
85
+ const numStreams = Math.min(
86
+ Math.max(Math.round(totalAmount / this.targetBatchSize), 1),
87
+ this.maxParallelStreams,
88
+ );
89
+
90
+ const actualBatchSize = Math.ceil(totalAmount / numStreams);
91
+ for (let batchIndex = 0; batchIndex < numStreams; batchIndex += 1) {
92
+ const startingHeight = (batchIndex * actualBatchSize) + 1;
93
+ const count = Math.min(actualBatchSize, toBlockHeight - startingHeight + 1);
94
+
95
+ const subscribeWithRetries = this.subscribeToHistoricalBatch(this.maxRetries);
96
+
97
+ // eslint-disable-next-line no-await-in-loop
98
+ const stream = await subscribeWithRetries(startingHeight, count);
99
+ this.historicalStreams.push(stream);
100
+ }
101
+ }
102
+
103
+ stopReadingHistorical() {
104
+ this.removeAllListeners(COMMANDS.HANDLE_STREAM_RETRY);
105
+ this.removeAllListeners(COMMANDS.HANDLE_STREAM_ERROR);
106
+ this.removeAllListeners(COMMANDS.HANDLE_FINISHED_STREAM);
107
+ this.historicalStreams.forEach((stream) => stream.destroy());
108
+ this.historicalStreams = [];
109
+ }
110
+
111
+ /**
112
+ * Subscribes to continuously arriving block headers
113
+ *
114
+ * @param {number} fromBlockHeight
115
+ * @returns {Promise<Stream>}
116
+ */
117
+ async subscribeToNew(fromBlockHeight) {
118
+ const stream = await this.coreMethods.subscribeToBlockHeadersWithChainLocks({
119
+ fromBlockHeight,
120
+ });
121
+
122
+ stream.on('data', (data) => {
123
+ const blockHeaders = data.getBlockHeaders();
124
+
125
+ if (blockHeaders) {
126
+ /**
127
+ * Kills stream in case of deliberate rejection from the outside
128
+ *
129
+ * @param e
130
+ */
131
+ const rejectHeaders = (e) => {
132
+ stream.destroy(e);
133
+ };
134
+
135
+ this.emit(EVENTS.BLOCK_HEADERS, blockHeaders.getHeadersList(), rejectHeaders);
136
+ }
137
+ });
138
+
139
+ stream.on('error', (e) => {
140
+ this.emit(EVENTS.ERROR, e);
141
+ });
142
+
143
+ return stream;
144
+ }
145
+
146
+ /**
147
+ * A HOF that returns a function to subscribe to historical block headers and chain locks
148
+ * and handles retry logic
149
+ *
150
+ * @private
151
+ * @param {number} [maxRetries=0] - maximum amount of retries
152
+ * @returns {function(*, *): Promise<Stream>}
153
+ */
154
+ subscribeToHistoricalBatch(maxRetries = 0) {
155
+ let currentRetries = 0;
156
+
157
+ /**
158
+ * Subscribes to the stream of historical data and handles retry logic
159
+ *
160
+ * @param {number} fromBlockHeight
161
+ * @param {number} count
162
+ * @returns {Promise<Stream>}
163
+ */
164
+ const subscribeWithRetries = async (fromBlockHeight, count) => {
165
+ let headersObtained = 0;
166
+
167
+ const stream = await this.coreMethods.subscribeToBlockHeadersWithChainLocks({
168
+ fromBlockHeight,
169
+ count,
170
+ });
171
+
172
+ stream.on('data', (data) => {
173
+ const blockHeaders = data.getBlockHeaders();
174
+
175
+ if (blockHeaders) {
176
+ const headersList = blockHeaders.getHeadersList();
177
+
178
+ let rejected = false;
179
+
180
+ /**
181
+ * Kills stream in case of deliberate rejection from the outside
182
+ *
183
+ * @param e
184
+ */
185
+ const rejectHeaders = (e) => {
186
+ rejected = true;
187
+ stream.destroy(e);
188
+ };
189
+
190
+ this.emit(EVENTS.BLOCK_HEADERS, headersList, rejectHeaders);
191
+
192
+ if (!rejected) {
193
+ headersObtained += headersList.length;
194
+ }
195
+ }
196
+ });
197
+
198
+ stream.on('error', (streamError) => {
199
+ if (currentRetries < maxRetries) {
200
+ const newFromBlockHeight = fromBlockHeight + headersObtained;
201
+ const newCount = count - headersObtained;
202
+
203
+ subscribeWithRetries(newFromBlockHeight, newCount)
204
+ .then((newStream) => {
205
+ currentRetries += 1;
206
+ this.emit(COMMANDS.HANDLE_STREAM_RETRY, stream, newStream);
207
+ }).catch((e) => {
208
+ this.emit(COMMANDS.HANDLE_STREAM_ERROR, stream, e);
209
+ });
210
+ } else {
211
+ this.emit(COMMANDS.HANDLE_STREAM_ERROR, stream, streamError);
212
+ }
213
+ });
214
+
215
+ stream.on('end', () => {
216
+ this.emit(COMMANDS.HANDLE_FINISHED_STREAM, stream);
217
+ });
218
+
219
+ return stream;
220
+ };
221
+
222
+ return subscribeWithRetries;
223
+ }
224
+ }
225
+
226
+ BlockHeadersReader.EVENTS = EVENTS;
227
+ BlockHeadersReader.COMMANDS = COMMANDS;
228
+
229
+ module.exports = BlockHeadersReader;
@@ -0,0 +1,77 @@
1
+ const networks = require('@dashevo/dashcore-lib/lib/networks');
2
+ const DAPIClientError = require('../errors/DAPIClientError');
3
+ const BlockHeadersProvider = require('./BlockHeadersProvider');
4
+
5
+ const validateNumber = (value, name, min = NaN, max = NaN) => {
6
+ if (typeof value !== 'number') {
7
+ throw new DAPIClientError(`'${name}' is not a number`);
8
+ }
9
+
10
+ if (!Number.isNaN(min) && value < min) {
11
+ throw new DAPIClientError(`'${name}' can not be less than ${min}`);
12
+ }
13
+
14
+ if (!Number.isNaN(max) && value > min) {
15
+ throw new DAPIClientError(`'${name}' can not be more than ${max}`);
16
+ }
17
+ };
18
+
19
+ /**
20
+ * @typedef {createBlockHeadersProviderFromOptions}
21
+ * @param {DAPIClientOptions} options
22
+ * @param {CoreMethodsFacade} coreMethods
23
+ * @returns {BlockHeadersProvider}
24
+ */
25
+ function createBlockHeadersProviderFromOptions(options, coreMethods) {
26
+ let blockHeadersProvider;
27
+ if (options.blockHeadersProvider) {
28
+ if (options.blockHeadersProviderOptions) {
29
+ throw new DAPIClientError("Can't use 'blockHeadersProviderOptions' with 'blockHeadersProvider' option");
30
+ }
31
+
32
+ blockHeadersProvider = options.blockHeadersProvider;
33
+ }
34
+
35
+ if (options.blockHeadersProviderOptions) {
36
+ const blockHeadersProviderOptions = {
37
+ ...BlockHeadersProvider.defaultOptions,
38
+ ...options.blockHeadersProviderOptions,
39
+ };
40
+
41
+ const {
42
+ network,
43
+ autoStart,
44
+ maxParallelStreams,
45
+ targetBatchSize,
46
+ fromBlockHeight,
47
+ maxRetries,
48
+ } = blockHeadersProviderOptions;
49
+
50
+ if (network && !networks.get(network)) {
51
+ throw new DAPIClientError(`Invalid network '${options.network}'`);
52
+ }
53
+
54
+ if (typeof autoStart !== 'boolean') {
55
+ throw new DAPIClientError('\'autoStart\' option must have boolean type');
56
+ }
57
+
58
+ validateNumber(maxParallelStreams, 'maxParallelStreams', 1);
59
+ validateNumber(targetBatchSize, 'targetBatchSize', 1);
60
+ validateNumber(fromBlockHeight, 'fromBlockHeight', 1);
61
+ validateNumber(maxRetries, 'maxRetries', 0);
62
+
63
+ blockHeadersProvider = new BlockHeadersProvider(
64
+ blockHeadersProviderOptions,
65
+ );
66
+ }
67
+
68
+ if (!blockHeadersProvider) {
69
+ blockHeadersProvider = new BlockHeadersProvider();
70
+ }
71
+
72
+ blockHeadersProvider.setCoreMethods(coreMethods);
73
+
74
+ return blockHeadersProvider;
75
+ }
76
+
77
+ module.exports = createBlockHeadersProviderFromOptions;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @interface BlockHeadersReader
3
+ */
4
+
5
+ /**
6
+ * @private
7
+ * @function
8
+ * @async
9
+ * @name BlockHeadersReader#createBatchFetcher
10
+ * @returns {(function(*, *): Promise<void>)|*}
11
+ */
12
+
13
+ /**
14
+ * @function
15
+ * @async
16
+ * @name BlockHeadersReader#subscribeToNew
17
+ * @returns {Promise<Stream>}
18
+ */
19
+
20
+ /**
21
+ * @function
22
+ * @async
23
+ * @name BlockHeadersReader#readHistorical
24
+ * @returns {Promise<void>}
25
+ */
package/lib/DAPIClient.js CHANGED
@@ -1,3 +1,5 @@
1
+ const EventEmitter = require('events');
2
+
1
3
  const GrpcTransport = require('./transport/GrpcTransport/GrpcTransport');
2
4
  const JsonRpcTransport = require('./transport/JsonRpcTransport/JsonRpcTransport');
3
5
 
@@ -9,15 +11,25 @@ const requestJsonRpc = require('./transport/JsonRpcTransport/requestJsonRpc');
9
11
  const createGrpcTransportError = require('./transport/GrpcTransport/createGrpcTransportError');
10
12
  const createJsonTransportError = require('./transport/JsonRpcTransport/createJsonTransportError');
11
13
 
12
- class DAPIClient {
14
+ const BlockHeadersProvider = require('./BlockHeadersProvider/BlockHeadersProvider');
15
+ const createBlockHeadersProviderFromOptions = require('./BlockHeadersProvider/createBlockHeadersProviderFromOptions');
16
+
17
+ const EVENTS = {
18
+ ERROR: 'error',
19
+ };
20
+
21
+ class DAPIClient extends EventEmitter {
13
22
  /**
14
23
  * @param {DAPIClientOptions} [options]
15
24
  */
16
25
  constructor(options = {}) {
26
+ super();
27
+
17
28
  this.options = {
18
29
  network: 'testnet',
19
30
  timeout: 10000,
20
31
  retries: 5,
32
+ blockHeadersProviderOptions: BlockHeadersProvider.defaultOptions,
21
33
  ...options,
22
34
  };
23
35
 
@@ -40,9 +52,30 @@ class DAPIClient {
40
52
 
41
53
  this.core = new CoreMethodsFacade(jsonRpcTransport, grpcTransport);
42
54
  this.platform = new PlatformMethodsFacade(grpcTransport);
55
+
56
+ this.initBlockHeadersProvider();
57
+ }
58
+
59
+ /**
60
+ * @private
61
+ */
62
+ initBlockHeadersProvider() {
63
+ this.blockHeadersProvider = createBlockHeadersProviderFromOptions(this.options, this.core);
64
+
65
+ this.blockHeadersProvider.on(BlockHeadersProvider.EVENTS.ERROR, (e) => {
66
+ this.emit(EVENTS.ERROR, e);
67
+ });
68
+
69
+ if (this.options.blockHeadersProviderOptions.autoStart) {
70
+ this.blockHeadersProvider.start().catch((e) => {
71
+ this.emit(EVENTS.ERROR, e);
72
+ });
73
+ }
43
74
  }
44
75
  }
45
76
 
77
+ DAPIClient.EVENTS = EVENTS;
78
+
46
79
  /**
47
80
  * @typedef {DAPIClientOptions} DAPIClientOptions
48
81
  * @property {DAPIAddressProvider} [dapiAddressProvider]
@@ -54,6 +87,8 @@ class DAPIClient {
54
87
  * @property {number} [retries=3]
55
88
  * @property {number} [baseBanTime=60000]
56
89
  * @property {boolean} [throwDeadlineExceeded]
90
+ * @property {BlockHeadersProvider} [blockHeadersProvider]
91
+ * @property {BlockHeadersProviderOptions} [blockHeadersProviderOptions]
57
92
  */
58
93
 
59
94
  module.exports = DAPIClient;
@@ -1,16 +1,12 @@
1
- const StoreTreeProofs = require('./StoreTreeProofs');
2
-
3
1
  class Proof {
4
2
  /**
5
3
  * @param {object} properties
6
- * @param {Buffer} properties.rootTreeProof
7
- * @param {StoreTreeProofs} properties.storeTreeProofs
4
+ * @param {Buffer} properties.merkleProof
8
5
  * @param {Buffer} properties.signatureLLMQHash
9
6
  * @param {Buffer} properties.signature
10
7
  */
11
8
  constructor(properties) {
12
- this.rootTreeProof = properties.rootTreeProof;
13
- this.storeTreeProofs = properties.storeTreeProofs;
9
+ this.merkleProof = properties.merkleProof;
14
10
  this.signatureLLMQHash = properties.signatureLLMQHash;
15
11
  this.signature = properties.signature;
16
12
  }
@@ -18,15 +14,8 @@ class Proof {
18
14
  /**
19
15
  * @returns {Buffer}
20
16
  */
21
- getRootTreeProof() {
22
- return this.rootTreeProof;
23
- }
24
-
25
- /**
26
- * @returns {StoreTreeProofs}
27
- */
28
- getStoreTreeProofs() {
29
- return this.storeTreeProofs;
17
+ getMerkleProof() {
18
+ return this.merkleProof;
30
19
  }
31
20
 
32
21
  /**
@@ -44,27 +33,13 @@ class Proof {
44
33
  }
45
34
 
46
35
  /**
47
- * @param proofProto
36
+ * @param {Object} proofProto
48
37
  *
49
38
  * @returns {Proof}
50
39
  */
51
40
  static createFromProto(proofProto) {
52
- const rawStoreProofs = proofProto.getStoreTreeProofs();
53
-
54
- const storeTreeProofs = new StoreTreeProofs({
55
- dataContractsProof: rawStoreProofs.getDataContractsProof()
56
- ? Buffer.from(rawStoreProofs.getDataContractsProof()) : null,
57
- publicKeyHashesToIdentityIdsProof: rawStoreProofs.getPublicKeyHashesToIdentityIdsProof()
58
- ? Buffer.from(rawStoreProofs.getPublicKeyHashesToIdentityIdsProof()) : null,
59
- identitiesProof: rawStoreProofs.getIdentitiesProof()
60
- ? Buffer.from(rawStoreProofs.getIdentitiesProof()) : null,
61
- documentsProof: rawStoreProofs.getDocumentsProof()
62
- ? Buffer.from(rawStoreProofs.getDocumentsProof()) : null,
63
- });
64
-
65
41
  return new Proof({
66
- rootTreeProof: Buffer.from(proofProto.getRootTreeProof()),
67
- storeTreeProofs,
42
+ merkleProof: Buffer.from(proofProto.getMerkleProof()),
68
43
  signatureLLMQHash: Buffer.from(proofProto.getSignatureLlmqHash()),
69
44
  signature: Buffer.from(proofProto.getSignature()),
70
45
  });
@@ -0,0 +1,215 @@
1
+ const { BlockHeader } = require('@dashevo/dashcore-lib');
2
+
3
+ const headers = [
4
+ {
5
+ version: 2,
6
+ prevHash: '00000bafbc94add76cb75e2ec92894837288a481e5c005f6563d91623bf8bc2c',
7
+ merkleRoot: 'b4fd581bc4bfe51a5a66d8b823bd6ee2b492f0ddc44cf7e820550714cedc117f',
8
+ time: 1398712771,
9
+ bits: '1e0fffff',
10
+ nonce: 31475,
11
+ },
12
+ {
13
+ version: 2,
14
+ prevHash: '0000047d24635e347be3aaaeb66c26be94901a2f962feccd4f95090191f208c1',
15
+ merkleRoot: '0d6d332e68eb8ecc66a5baaa95dc4b10c0b32841aed57dc99a5ae0b2f9e4294d',
16
+ time: 1398712772,
17
+ nonce: 6523,
18
+ bits: '1e0ffff0',
19
+ },
20
+ {
21
+ version: 2,
22
+ prevHash: '00000c6264fab4ba2d23990396f42a76aa4822f03cbc7634b79f4dfea36fccc2',
23
+ merkleRoot: '1cc711129405a328c58d1948e748c3b8f3d610e66d9901db88c42c5247829658',
24
+ time: 1398712774,
25
+ nonce: 53194,
26
+ bits: '1e0ffff0',
27
+ },
28
+ {
29
+ version: 2,
30
+ prevHash: '0000057d5c945acbe476bc17bbbaeb2fc1c1b18673e7582c48ac04af61f4d811',
31
+ merkleRoot: '7e6b1b1457308bf6ccb1e325c64607ba7dfac05e26c08887cd28f97d4d4ab3e2',
32
+ time: 1398712782,
33
+ nonce: 193159,
34
+ bits: '1e0ffff0',
35
+ },
36
+ {
37
+ version: 2,
38
+ prevHash: '000002258bd58bf4cdcde282abc030437c103dbb12d2a7dbc978d07bcf386b42',
39
+ merkleRoot: '4cf4f3b788e8dc847a9e0ff3b279340207c555a6bc0736f93e95dbdc2e3c2f16',
40
+ time: 1398712784,
41
+ nonce: 41103,
42
+ bits: '1e0ffff0',
43
+ },
44
+ {
45
+ version: 2,
46
+ prevHash: '00000b1406007f9148c4c173e2314437a315b79b5b79e73ed534a2e8b18a43fc',
47
+ merkleRoot: '99c25e1373c0a5277157b730624d110d04322ffaac49ac0c98cc2d01c80f4c4c',
48
+ time: 1398712787,
49
+ nonce: 62295,
50
+ bits: '1e0ffff0',
51
+ },
52
+ {
53
+ version: 2,
54
+ prevHash: '00000d93de4b31ec550d324876ee7c502a073911972d26c2c990b94d9d5b5a44',
55
+ merkleRoot: '769fc473dc8e5073e4fe3f69f0603972d3d72fbeb62a64de826c64e44260b3f3',
56
+ time: 1398712793,
57
+ nonce: 127755,
58
+ bits: '1e0ffff0',
59
+ },
60
+ {
61
+ version: 2,
62
+ prevHash: '00000154b50ded9d6298dc965e541cef117103c3376256185d0d70e92850853d',
63
+ merkleRoot: '8243e732675d2936bb27917844e714ff5e2012726e3f76e374e7f6236e78669e',
64
+ time: 1398712796,
65
+ nonce: 62099,
66
+ bits: '1e0ffff0',
67
+ },
68
+ {
69
+ version: 2,
70
+ prevHash: '0000089e53a33e48061fa4dbc0a52c40736c2eedddaf563ec25cfe406dd8a541',
71
+ merkleRoot: '243786d6706421ba9ebe9a0d153a5e79d9f781825dbbb0ed26ccc647f10984ee',
72
+ time: 1398712802,
73
+ nonce: 128139,
74
+ bits: '1e0ffff0',
75
+ },
76
+ {
77
+ version: 2,
78
+ prevHash: '00000e98a2b0b1505e3ed00dba28988cd81440de4ec48d817412c2178d332985',
79
+ merkleRoot: 'b158385f441d9299732ec264442d28b6009b8d24388ee7e23a6ce7e6051bfa31',
80
+ time: 1398712803,
81
+ nonce: 23451,
82
+ bits: '1e0ffff0',
83
+ },
84
+ {
85
+ version: 2,
86
+ prevHash: '000001128124cab4756edc387dce2b8762514916d953a4993971a40d78240978',
87
+ merkleRoot: '1f966cdf6ca90f211308554f90f33935cd8e25ab329ffedfa1066b00a581d5d5',
88
+ time: 1398712807,
89
+ nonce: 58648,
90
+ bits: '1e0ffff0',
91
+ },
92
+ {
93
+ version: 2,
94
+ prevHash: '00000ce430de949c85a145b02e33ebbaed3772dc8f3d668f66edc6852c24d002',
95
+ merkleRoot: '663360403b5fba9cd8744c3706f9660c7d3fee4e5a9ee98ce0ad5e5ad7824c1d',
96
+ time: 1398712821,
97
+ nonce: 312363,
98
+ bits: '1e0ffff0',
99
+ },
100
+ {
101
+ version: 2,
102
+ prevHash: '00000ac3a0c9df709260e41290d6902e5a4a073099f11fe8c1ce80aadc4bb331',
103
+ merkleRoot: 'c2ed22a3e6712b842359dfbb6f0a133ae122ffb601e4cf60e30b8c99f9438f4f',
104
+ time: 1398712821,
105
+ nonce: 8325,
106
+ bits: '1e0ffff0',
107
+ },
108
+ {
109
+ version: 2,
110
+ prevHash: '00000b526b34e733532d706c1f4cef93eefe707b87c2c3cb2978e1a84b97c501',
111
+ merkleRoot: '8994e231d4986bbea391d08f67ff9b6da758c86aa2fc9e9816f105462d18cf1b',
112
+ time: 1398712824,
113
+ nonce: 60659,
114
+ bits: '1e0ffff0',
115
+ },
116
+ {
117
+ version: 2,
118
+ prevHash: '00000799cc6963498a215e04402737fc1a08e696a91540756b0697f1ac7b23a8',
119
+ merkleRoot: 'f57a78dd55cb4530df55a8b7ba5aed632b1d3819950e78f90d1acdba5ac595d9',
120
+ time: 1398712825,
121
+ nonce: 18064,
122
+ bits: '1e0ffff0',
123
+ },
124
+ {
125
+ version: 2,
126
+ prevHash: '00000170cc708e9c3b491625dd8dc2d737730a738ebd349f2a770fb26944c04f',
127
+ merkleRoot: '5494a90a580a4f16ff80d2b0c7507d7a565415091d88abeaa752b517da92e06d',
128
+ time: 1398886700,
129
+ nonce: 1555411,
130
+ bits: '1e0fffff',
131
+ },
132
+ {
133
+ version: 2,
134
+ prevHash: '000000ab6ae22728c701e15a13dfa022c88f17a4e0fd71f073b0a720229de22b',
135
+ merkleRoot: '0c03f4a03f47046d1295207ca99cc9db6757a6e4ff313a359d1182cfb8431a84',
136
+ time: 1405697551,
137
+ nonce: 1491503,
138
+ bits: '1e0fffff',
139
+ },
140
+ {
141
+ version: 2,
142
+ confirmations: 86916,
143
+ prevHash: '00000541dfefddc46d4a7ef3873375db4a6f5b1c06a84b67346fb88e07f024d0',
144
+ merkleRoot: '2d6ad1b165c8b7dd4f038d8003d0229259db52e7e828d0d25af38c2f2f7e1990',
145
+ time: 1405697569,
146
+ nonce: 966245,
147
+ bits: '1e0ffff0',
148
+ },
149
+ {
150
+ version: 2,
151
+ prevHash: '000000d275d8dc93e7bf8c358463c97e12be9b2b17d4e64770aca7af8dcb93d8',
152
+ merkleRoot: 'e3552304f4c424ebe5bfc0911b1a3a6fcec15fe788acaf910f45238f16d522f7',
153
+ time: 1405697598,
154
+ nonce: 1661888,
155
+ bits: '1e0ffff0',
156
+ },
157
+ {
158
+ version: 2,
159
+ prevHash: '0000073a769b38812ca2e3a6d4958cab3f21ed3cf4cc80590be3db4b9cb17c8a',
160
+ merkleRoot: 'dd0e01125ffba80e7e7508d57da2725ccc648ed3ea3bac60ee19f81efcf8b934',
161
+ time: 1405697613,
162
+ nonce: 828461,
163
+ bits: '1e0ffff0',
164
+ },
165
+ {
166
+ version: 2,
167
+ prevHash: '00000816a46bd5ea15161c7864b76a263f890d60d4aad6b53cceb8c39ee6b153',
168
+ merkleRoot: '2847d5749c81f8c0b6b91a87a833532611feebb39a833d0e092ec7c8e141467e',
169
+ time: 1405697617,
170
+ nonce: 50599,
171
+ bits: '1e0ffff0',
172
+ },
173
+ {
174
+ version: 2,
175
+ prevHash: '00000976f999bcb32be3d5b7c2e684e8000d8566f22df2612f58b8574536addc',
176
+ merkleRoot: '78d7b2982419345c34391df68ff2d10c0475d5513a6b52f8caaae4f350af1eee',
177
+ time: 1405697628,
178
+ nonce: 613213,
179
+ bits: '1e0ffff0',
180
+ },
181
+ {
182
+ version: 2,
183
+ prevHash: '00000a4f6e00f23dde0b9197d5633b1637c0c22748adadda2d1a799b26115d0d',
184
+ merkleRoot: 'bc8af9a84bc94da13dd144c4e1bff2d8580d33f7613d2e4c9c504b4df5c6d9b4',
185
+ time: 1405697647,
186
+ nonce: 1050462,
187
+ bits: '1e0ffff0',
188
+ },
189
+ {
190
+ version: 2,
191
+ prevHash: '00000ad04d60ac3b1567b499c359b2f901be9826e358e071e5ffcb014d7e60ef',
192
+ merkleRoot: '3cbf4973f43b967773b06169246fbbc80258631280ea84165a1c269b3601943f',
193
+ time: 1405697671,
194
+ nonce: 1381148,
195
+ bits: '1e0ffff0',
196
+ },
197
+ {
198
+ version: 2,
199
+ prevHash: '00000df1e666a530efa28ac37c8cf8b80970c65aa69497fc4fbb3252d2e5f661',
200
+ merkleRoot: '4050c8893b1d882da44d15e481b30e145ed6fe29ffa51ac99dc0e206696aa6dc',
201
+ time: 1405697678,
202
+ nonce: 352597,
203
+ bits: '1e0ffff0',
204
+ },
205
+ ];
206
+
207
+ /**
208
+ * @returns {BlockHeader[]}
209
+ */
210
+ function getHeadersFixture() {
211
+ return headers
212
+ .map((header) => new BlockHeader({ ...header, bits: parseInt(header.bits, 16) }));
213
+ }
214
+
215
+ module.exports = getHeadersFixture;
@@ -1,13 +1,7 @@
1
1
  /**
2
2
  * @returns {{
3
- * rootTreeProof: Buffer,
3
+ * merkleProof: Buffer,
4
4
  * signature: Buffer,
5
- * storeTreeProofs: {
6
- * documentsProof: Buffer,
7
- * publicKeyHashesToIdentityIdsProof: Buffer,
8
- * dataContractsProof: Buffer,
9
- * identitiesProof: Buffer
10
- * },
11
5
  * signatureLLMQHash: Buffer
12
6
  * }}
13
7
  */
@@ -15,13 +9,7 @@ function getProofFixture() {
15
9
  return {
16
10
  signatureLLMQHash: Buffer.from('AQEBAQEBAQEBAQEB', 'base64'),
17
11
  signature: Buffer.from('AgICAgICAgICAgIC', 'base64'),
18
- rootTreeProof: Buffer.from('0100000001f0faf5f55674905a68eba1be2f946e667c1cb5010101', 'hex'),
19
- storeTreeProofs: {
20
- publicKeyHashesToIdentityIdsProof: Buffer.from('03046b657931060076616c75653103046b657932060076616c75653210', 'hex'),
21
- identitiesProof: Buffer.from('03046b657931060076616c75653103046b657932060076616c75653210', 'hex'),
22
- documentsProof: Buffer.from('03046b657931060076616c75653103046b657932060076616c75653210', 'hex'),
23
- dataContractsProof: Buffer.from('03046b657931060076616c75653103046b657932060076616c75653210', 'hex'),
24
- },
12
+ merkleProof: Buffer.from('0100000001f0faf5f55674905a68eba1be2f946e667c1cb5010101', 'hex'),
25
13
  };
26
14
  }
27
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dashevo/dapi-client",
3
- "version": "0.22.0-dev.7",
3
+ "version": "0.22.0-dev.8",
4
4
  "description": "Client library used to access Dash DAPI endpoints",
5
5
  "main": "lib/DAPIClient.js",
6
6
  "contributors": [
@@ -26,10 +26,11 @@
26
26
  }
27
27
  ],
28
28
  "dependencies": {
29
- "@dashevo/dapi-grpc": "~0.22.0-dev.7",
30
- "@dashevo/dashcore-lib": "~0.19.29",
31
- "@dashevo/dpp": "~0.22.0-dev.7",
32
- "@dashevo/grpc-common": "~0.22.0-dev.7",
29
+ "@dashevo/dapi-grpc": "~0.22.0-dev.8",
30
+ "@dashevo/dash-spv": "github:dashevo/dash-spv",
31
+ "@dashevo/dashcore-lib": "~0.19.30",
32
+ "@dashevo/dpp": "~0.22.0-dev.8",
33
+ "@dashevo/grpc-common": "~0.22.0-dev.8",
33
34
  "@grpc/grpc-js": "^1.3.7",
34
35
  "axios": "^0.21.1",
35
36
  "bs58": "^4.0.1",