@dashevo/dapi-client 0.23.0-dev.9 → 0.23.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.
@@ -1,6 +1,6 @@
1
- const networks = require('@dashevo/dashcore-lib/lib/networks');
2
1
  const DAPIClientError = require('../errors/DAPIClientError');
3
2
  const BlockHeadersProvider = require('./BlockHeadersProvider');
3
+ const ReconnectableStream = require('../transport/ReconnectableStream');
4
4
 
5
5
  const validateNumber = (value, name, min = NaN, max = NaN) => {
6
6
  if (typeof value !== 'number') {
@@ -11,7 +11,7 @@ const validateNumber = (value, name, min = NaN, max = NaN) => {
11
11
  throw new DAPIClientError(`'${name}' can not be less than ${min}`);
12
12
  }
13
13
 
14
- if (!Number.isNaN(max) && value > min) {
14
+ if (!Number.isNaN(max) && value > max) {
15
15
  throw new DAPIClientError(`'${name}' can not be more than ${max}`);
16
16
  }
17
17
  };
@@ -32,45 +32,60 @@ function createBlockHeadersProviderFromOptions(options, coreMethods) {
32
32
  blockHeadersProvider = options.blockHeadersProvider;
33
33
  }
34
34
 
35
+ const createContinuousSyncStream = (fromBlockHeight) => ReconnectableStream
36
+ .create(
37
+ coreMethods.subscribeToBlockHeadersWithChainLocks,
38
+ {
39
+ maxRetriesOnError: -1,
40
+ },
41
+ )({
42
+ fromBlockHeight,
43
+ });
44
+
45
+ const createHistoricalSyncStream = (fromBlockHeight, count) => {
46
+ const { subscribeToBlockHeadersWithChainLocks } = coreMethods;
47
+ return subscribeToBlockHeadersWithChainLocks({
48
+ fromBlockHeight,
49
+ count,
50
+ });
51
+ };
52
+
35
53
  if (options.blockHeadersProviderOptions) {
54
+ const { network } = options;
55
+
36
56
  const blockHeadersProviderOptions = {
37
57
  ...BlockHeadersProvider.defaultOptions,
38
58
  ...options.blockHeadersProviderOptions,
59
+ network,
39
60
  };
40
61
 
41
62
  const {
42
- network,
43
- autoStart,
44
63
  maxParallelStreams,
45
64
  targetBatchSize,
46
65
  fromBlockHeight,
47
66
  maxRetries,
48
67
  } = blockHeadersProviderOptions;
49
68
 
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
69
  validateNumber(maxParallelStreams, 'maxParallelStreams', 1);
59
70
  validateNumber(targetBatchSize, 'targetBatchSize', 1);
60
71
  validateNumber(fromBlockHeight, 'fromBlockHeight', 1);
61
- validateNumber(maxRetries, 'maxRetries', 0);
72
+ validateNumber(maxRetries, 'maxRetries', 0, 100);
62
73
 
63
74
  blockHeadersProvider = new BlockHeadersProvider(
64
75
  blockHeadersProviderOptions,
76
+ createHistoricalSyncStream,
77
+ createContinuousSyncStream,
65
78
  );
66
79
  }
67
80
 
68
81
  if (!blockHeadersProvider) {
69
- blockHeadersProvider = new BlockHeadersProvider();
82
+ blockHeadersProvider = new BlockHeadersProvider(
83
+ {},
84
+ createContinuousSyncStream,
85
+ createHistoricalSyncStream,
86
+ );
70
87
  }
71
88
 
72
- blockHeadersProvider.setCoreMethods(coreMethods);
73
-
74
89
  return blockHeadersProvider;
75
90
  }
76
91
 
package/lib/DAPIClient.js CHANGED
@@ -65,12 +65,6 @@ class DAPIClient extends EventEmitter {
65
65
  this.blockHeadersProvider.on(BlockHeadersProvider.EVENTS.ERROR, (e) => {
66
66
  this.emit(EVENTS.ERROR, e);
67
67
  });
68
-
69
- if (this.options.blockHeadersProviderOptions.autoStart) {
70
- this.blockHeadersProvider.start().catch((e) => {
71
- this.emit(EVENTS.ERROR, e);
72
- });
73
- }
74
68
  }
75
69
  }
76
70
 
package/lib/index.js CHANGED
@@ -1,9 +1,12 @@
1
1
  const DAPIClient = require('./DAPIClient');
2
2
 
3
3
  const NotFoundError = require('./transport/GrpcTransport/errors/NotFoundError');
4
+ const BlockHeadersProvider = require('./BlockHeadersProvider/BlockHeadersProvider');
4
5
 
5
6
  DAPIClient.Errors = {
6
7
  NotFoundError,
7
8
  };
8
9
 
10
+ DAPIClient.BlockHeadersProvider = BlockHeadersProvider;
11
+
9
12
  module.exports = DAPIClient;
@@ -12,156 +12,120 @@ module.exports = {
12
12
  // that breaks test suite and application logic. Temporary solution is to hardcode
13
13
  // reliable DCG testnet masternodes to connect. Should be removed when PoSe is introduced.
14
14
  dapiAddressesWhiteList: [
15
- '52.11.85.154',
16
- '52.38.248.133',
17
- '34.212.231.240',
18
- '54.185.249.226',
19
- '34.215.57.86',
20
- '54.190.73.116',
21
- '34.214.2.219',
22
- '54.212.84.164',
23
- '35.164.96.124',
24
- '34.219.81.129',
25
- '34.221.42.205',
26
- '34.208.88.128',
27
- '54.189.162.193',
28
- '34.220.124.90',
29
- '54.201.242.241',
30
- '54.68.10.46',
31
- '34.210.81.39',
32
- '18.237.47.243',
33
- '54.187.229.6',
34
- '34.214.102.160',
35
- '34.219.93.145',
36
- '35.165.37.186',
37
- '54.202.157.120',
38
- '34.215.144.176',
39
- '52.13.119.69',
40
- '34.220.12.188',
41
- '18.237.5.33',
42
- '54.191.32.70',
43
- '54.213.219.155',
44
- '35.167.25.157',
45
- '54.213.89.75',
46
- '52.32.232.156',
47
- '34.212.226.44',
48
- '35.160.140.37',
49
- '52.11.133.244',
50
- '54.201.189.185',
51
- '34.216.200.22',
52
- '34.220.144.226',
53
- '34.216.195.19',
54
- '54.185.1.69',
55
- '35.166.29.155',
56
- '18.237.147.160',
57
- '34.220.228.214',
58
- '54.212.75.8',
59
- '35.163.152.74',
60
- '18.236.78.191',
61
- '54.148.106.179',
62
- '34.211.46.222',
63
- '35.160.13.25',
64
- '34.220.17.107',
65
- '34.212.65.137',
66
- '54.185.249.172',
67
- '54.70.65.199',
68
- '54.69.210.42',
69
- '18.236.160.247',
70
- '54.245.197.173',
71
- '54.187.11.213',
72
- '54.218.70.46',
73
- '35.165.207.13',
74
- '34.211.49.3',
75
- '34.219.36.94',
76
- '34.222.127.158',
77
- '34.222.242.228',
78
- '52.26.220.40',
79
- '52.36.244.225',
80
- '34.222.225.76',
81
- '18.236.169.114',
82
- '54.201.236.212',
83
- '54.203.241.214',
84
- '34.221.254.29',
85
- '54.187.50.120',
86
- '54.184.140.221',
87
- '34.215.192.133',
88
- '35.164.180.39',
89
- '54.184.183.20',
90
- '52.43.197.215',
91
- '54.201.42.245',
92
- '54.218.113.88',
93
- '54.244.141.192',
94
- '34.217.98.54',
95
- '34.222.168.33',
96
- '52.32.143.49',
97
- '54.187.224.80',
98
- '54.189.87.145',
99
- '52.39.164.105',
100
- '54.70.55.164',
101
- '54.214.68.206',
102
- '54.201.239.109',
103
- '34.215.146.162',
104
- '18.236.233.120',
105
- '54.190.217.178',
106
- '34.220.41.134',
107
- '34.212.178.215',
108
- '34.219.169.55',
109
- '54.218.251.43',
110
- '18.236.216.191',
111
- '54.188.17.60',
112
- '54.191.227.118',
113
- '34.213.5.102',
114
- '35.166.79.235',
115
- '54.71.107.225',
116
- '54.201.162.86',
117
- '52.34.141.75',
118
- '34.217.43.189',
119
- '52.38.77.105',
120
- '52.11.252.174',
121
- '54.191.221.246',
122
- '54.218.107.83',
123
- '54.212.18.218',
124
- '34.220.53.77',
125
- '54.244.41.15',
126
- '34.222.135.203',
127
- '54.191.110.152',
128
- '34.208.190.130',
129
- '34.222.6.55',
130
- '54.184.7.184',
131
- '52.12.47.86',
132
- '34.217.28.248',
133
- '54.149.252.146',
134
- '54.149.80.193',
135
- '34.215.55.0',
136
- '34.220.74.48',
137
- '34.209.124.112',
138
- '34.217.23.70',
139
- '34.222.102.137',
140
- '34.209.166.42',
141
- '18.236.128.49',
142
- '35.163.99.20',
143
- '34.215.67.224',
144
- '34.211.244.117',
145
- '18.236.199.232',
146
- '54.191.237.52',
147
- '34.223.226.224',
148
- '54.149.133.143',
149
- '52.41.198.242',
150
- '54.148.215.161',
151
- '54.188.193.70',
152
- '54.218.104.194',
153
- '34.209.73.208',
154
- '34.220.88.70',
155
- '52.40.101.104',
156
- '18.236.68.153',
157
- '34.218.76.179',
158
- '34.219.94.178',
159
- '54.218.127.128',
160
- '52.27.198.246',
161
- '18.237.204.153',
162
- '35.166.57.113',
163
- '54.191.15.3',
164
- '18.237.128.46',
15
+ '34.216.69.175',
16
+ '34.218.75.96',
17
+ '18.237.220.27',
18
+ '54.191.38.234',
19
+ '35.93.95.157',
20
+ '35.166.240.246',
21
+ '35.91.186.151',
22
+ '35.161.123.225',
23
+ '54.212.169.115',
24
+ '54.187.168.12',
25
+ '18.236.191.199',
26
+ '18.237.165.224',
27
+ '52.36.42.1',
28
+ '34.220.32.216',
29
+ '34.222.238.250',
30
+ '35.93.34.215',
31
+ '34.221.10.165',
32
+ '54.203.241.195',
33
+ '35.92.138.231',
34
+ '52.38.169.156',
35
+ '54.187.21.108',
36
+ '34.219.48.219',
37
+ '34.217.38.221',
38
+ '35.92.157.107',
39
+ '18.236.82.230',
40
+ '54.184.225.22',
41
+ '18.237.144.120',
42
+ '18.237.254.214',
43
+ '35.88.29.196',
44
+ '35.89.126.245',
45
+ '34.217.148.69',
46
+ '35.89.193.46',
47
+ '35.89.119.37',
48
+ '54.186.161.236',
49
+ '52.13.63.7',
50
+ '18.236.233.225',
51
+ '54.191.138.72',
52
+ '54.191.59.75',
53
+ '18.237.160.84',
54
+ '54.218.236.193',
55
+ '54.148.178.140',
56
+ '35.161.168.136',
57
+ '35.161.33.22',
58
+ '35.160.130.44',
59
+ '34.212.104.247',
60
+ '52.13.29.83',
61
+ '54.149.39.172',
62
+ '35.89.93.255',
63
+ '35.85.46.137',
64
+ '54.188.154.252',
65
+ '54.218.11.172',
66
+ '54.186.47.235',
67
+ '54.244.145.48',
68
+ '18.236.232.153',
69
+ '34.220.226.135',
70
+ '34.220.30.59',
71
+ '18.237.160.97',
72
+ '18.236.146.99',
73
+ '35.88.169.18',
74
+ '35.164.17.198',
75
+ '54.218.80.158',
76
+ '34.220.102.107',
77
+ '35.165.60.113',
78
+ '34.215.234.63',
79
+ '35.89.146.226',
80
+ '35.89.86.26',
81
+ '35.88.160.231',
82
+ '54.245.8.155',
83
+ '52.36.221.94',
84
+ '52.35.46.188',
85
+ '34.221.153.67',
86
+ '54.212.153.15',
87
+ '35.85.55.192',
88
+ '35.89.105.90',
89
+ '52.24.22.52',
90
+ '54.212.33.96',
91
+ '52.10.19.238',
92
+ '35.160.190.165',
93
+ '34.219.3.61',
94
+ '54.187.32.187',
95
+ '35.162.221.77',
96
+ '35.91.64.183',
97
+ '18.236.189.15',
98
+ '35.91.145.195',
99
+ '54.186.251.30',
100
+ '54.245.9.46',
101
+ '35.91.48.128',
102
+ '54.244.75.85',
103
+ '34.221.159.53',
104
+ '35.89.88.166',
105
+ '54.185.249.165',
106
+ '54.245.9.209',
107
+ '34.222.167.162',
108
+ '54.191.88.232',
109
+ '54.191.111.112',
110
+ '18.237.146.37',
111
+ '35.89.148.27',
112
+ '35.91.8.48',
113
+ '18.236.208.138',
114
+ '54.213.60.60',
115
+ '35.92.151.94',
116
+ '18.237.241.37',
117
+ '54.202.209.229',
118
+ '34.221.9.70',
119
+ '35.89.38.62',
120
+ '54.218.81.193',
121
+ '34.221.158.21',
122
+ '35.88.97.57',
123
+ '54.68.247.40',
124
+ '35.88.168.176',
125
+ '35.89.202.171',
126
+ '34.220.106.205',
127
+ '34.210.86.23',
128
+ '44.230.40.184',
165
129
  ],
166
130
  },
167
131
  evonet: {
@@ -20,4 +20,10 @@ afterEach(function afterEach() {
20
20
  this.sinon.restore();
21
21
  });
22
22
 
23
+ before(function before() {
24
+ if (!this.sinon) {
25
+ this.sinon = sinon.createSandbox();
26
+ }
27
+ });
28
+
23
29
  global.expect = expect;
@@ -0,0 +1,53 @@
1
+ const EventEmitter = require('events');
2
+
3
+ class BlockHeadersWithChainLocksStreamMock extends EventEmitter {
4
+ constructor(sinon) {
5
+ super();
6
+
7
+ sinon.spy(this, 'on');
8
+ sinon.spy(this, 'removeListener');
9
+ sinon.spy(this, 'emit');
10
+ sinon.spy(this, 'destroy');
11
+ sinon.spy(this, 'removeAllListeners');
12
+ sinon.spy(this, 'cancel');
13
+
14
+ this.errored = false;
15
+ }
16
+
17
+ destroy(e) {
18
+ this.emit('end');
19
+ if (e) {
20
+ this.emit('error', e);
21
+ }
22
+ }
23
+
24
+ cancel() {
25
+ if (!this.errored) {
26
+ const err = new Error('CANCELED_ON_CLIENT');
27
+ err.code = 1;
28
+ this.emit('error', err);
29
+ }
30
+ }
31
+
32
+ emit(event, data) {
33
+ if (event === 'error') {
34
+ this.errored = true;
35
+ }
36
+ super.emit(event, data);
37
+ }
38
+
39
+ /**
40
+ * @param headers {BlockHeader[]}
41
+ */
42
+ sendHeaders(headers) {
43
+ this.emit('data', {
44
+ getBlockHeaders: () => ({
45
+ getHeadersList() {
46
+ return headers.map((header) => header.toBuffer());
47
+ },
48
+ }),
49
+ });
50
+ }
51
+ }
52
+
53
+ module.exports = BlockHeadersWithChainLocksStreamMock;
@@ -0,0 +1,55 @@
1
+ const X11 = require('wasm-x11-hash');
2
+ const { BlockHeader, configure } = require('@dashevo/dashcore-lib');
3
+ const { genesis } = require('@dashevo/dash-spv');
4
+
5
+ const getRoot = (network) => {
6
+ switch (network) {
7
+ case 'testnet':
8
+ return genesis.getTestnetGenesis();
9
+ case 'devnet':
10
+ return genesis.getDevnetGenesis();
11
+ case 'regtest':
12
+ return genesis.getRegtestGenesis();
13
+ default:
14
+ break;
15
+ }
16
+
17
+ return null;
18
+ };
19
+
20
+ const BLOCK_TIME = 2.5 * 60;
21
+
22
+ let x11;
23
+
24
+ const mockHeadersChain = async (network, length, root) => {
25
+ if (!x11) {
26
+ x11 = await X11();
27
+ // Configure Dashcore lib to operate with wasm x11
28
+ configure({
29
+ x11hash: x11,
30
+ });
31
+ }
32
+
33
+ const rootHeader = root || getRoot(network);
34
+
35
+ const chain = [rootHeader];
36
+
37
+ let prevHeader = rootHeader;
38
+ for (let i = 0; i < length - 1; i += 1) {
39
+ const header = new BlockHeader({
40
+ version: prevHeader.version,
41
+ prevHash: Buffer.from(prevHeader.hash, 'hex').reverse(),
42
+ merkleRoot: Buffer.alloc(32),
43
+ time: prevHeader.time + BLOCK_TIME,
44
+ bits: prevHeader.bits,
45
+ nonce: 3861367235,
46
+ });
47
+
48
+ chain.push(header);
49
+ prevHeader = header;
50
+ }
51
+
52
+ return chain;
53
+ };
54
+
55
+ module.exports = mockHeadersChain;
@@ -50,32 +50,34 @@ function createGrpcTransportError(grpcError, dapiAddress) {
50
50
 
51
51
  const message = grpcError.details || grpcError.message;
52
52
 
53
+ let metadata = {};
54
+
53
55
  if (grpcError.metadata) {
54
56
  // In cases of gRPC-Web client we get plain map instead of Metadata instance
55
- let metadataMap = grpcError.metadata;
57
+ metadata = grpcError.metadata;
56
58
  if (grpcError.metadata instanceof Metadata) {
57
- metadataMap = grpcError.metadata.getMap();
59
+ metadata = grpcError.metadata.getMap();
58
60
  }
61
+ }
59
62
 
60
- // Error data
61
- const driveErrorData = metadataMap['drive-error-data-bin'];
62
- if (driveErrorData) {
63
- const encodedData = Buffer.from(driveErrorData, 'base64');
64
- data = cbor.decode(encodedData);
65
- }
63
+ // Error data
64
+ const driveErrorData = metadata['drive-error-data-bin'];
65
+ if (driveErrorData) {
66
+ const encodedData = Buffer.from(driveErrorData, 'base64');
67
+ data = cbor.decode(encodedData);
68
+ }
66
69
 
67
- // Error code
68
- const driveErrorCode = metadataMap.code;
69
- if (driveErrorCode) {
70
- code = Number(driveErrorCode);
71
- }
70
+ // Error code
71
+ const driveErrorCode = metadata.code;
72
+ if (driveErrorCode) {
73
+ code = Number(driveErrorCode);
74
+ }
72
75
 
73
- // Error stack
74
- const driveErrorStack = metadataMap['stack-bin'];
75
- if (driveErrorStack) {
76
- const encodedStack = Buffer.from(driveErrorStack, 'base64');
77
- data.stack = cbor.decode(encodedStack);
78
- }
76
+ // Error stack
77
+ const driveErrorStack = metadata['stack-bin'];
78
+ if (driveErrorStack) {
79
+ const encodedStack = Buffer.from(driveErrorStack, 'base64');
80
+ data.stack = cbor.decode(encodedStack);
79
81
  }
80
82
 
81
83
  // Specialized classes
@@ -100,13 +102,6 @@ function createGrpcTransportError(grpcError, dapiAddress) {
100
102
  }
101
103
 
102
104
  if (code === GrpcErrorCodes.INTERNAL) {
103
- if (grpcError.metadata) {
104
- const metaStack = grpcError.metadata.get('stack-bin');
105
- if (metaStack && metaStack.length > 0) {
106
- data.stack = cbor.decode(metaStack[0]);
107
- }
108
- }
109
-
110
105
  return new InternalServerError(
111
106
  code,
112
107
  message,