@rosen-bridge/abstract-extractor 0.2.0 → 0.3.1
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/CHANGELOG.md +17 -0
- package/dist/ergo/AbstractErgoExtractor.d.ts +3 -5
- package/dist/ergo/AbstractErgoExtractor.d.ts.map +1 -1
- package/dist/ergo/AbstractErgoExtractor.js +3 -3
- package/dist/ergo/AbstractErgoExtractorAction.d.ts +4 -3
- package/dist/ergo/AbstractErgoExtractorAction.d.ts.map +1 -1
- package/dist/ergo/AbstractErgoExtractorAction.js +1 -1
- package/dist/ergo/initializable/AbstractInitializable.d.ts +25 -20
- package/dist/ergo/initializable/AbstractInitializable.d.ts.map +1 -1
- package/dist/ergo/initializable/AbstractInitializable.js +126 -47
- package/dist/ergo/initializable/index.d.ts +0 -2
- package/dist/ergo/initializable/index.d.ts.map +1 -1
- package/dist/ergo/initializable/index.js +1 -3
- package/dist/ergo/interfaces.d.ts +5 -6
- package/dist/ergo/interfaces.d.ts.map +1 -1
- package/dist/ergo/interfaces.js +1 -1
- package/dist/ergo/network/ExplorerNetwork.d.ts +33 -4
- package/dist/ergo/network/ExplorerNetwork.d.ts.map +1 -1
- package/dist/ergo/network/ExplorerNetwork.js +88 -1
- package/dist/ergo/network/NodeNetwork.d.ts +18 -3
- package/dist/ergo/network/NodeNetwork.d.ts.map +1 -1
- package/dist/ergo/network/NodeNetwork.js +43 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/lib/ergo/AbstractErgoExtractor.ts +6 -15
- package/lib/ergo/AbstractErgoExtractorAction.ts +4 -2
- package/lib/ergo/initializable/AbstractInitializable.ts +163 -82
- package/lib/ergo/initializable/index.ts +0 -2
- package/lib/ergo/interfaces.ts +6 -6
- package/lib/ergo/network/ExplorerNetwork.ts +119 -4
- package/lib/ergo/network/NodeNetwork.ts +55 -2
- package/package.json +2 -1
- package/tests/AbstractExtractor.mock.ts +2 -4
- package/tests/AbstractExtractor.spec.ts +2 -6
- package/tests/initializable/AbstractInitializable.mock.ts +1 -5
- package/tests/initializable/AbstractInitializable.spec.ts +282 -174
- package/tests/initializable/testData.ts +219 -0
- package/tests/network/ExplorerNetwork.spec.ts +46 -2
- package/tests/network/NodeNetwork.spec.ts +21 -1
- package/tests/network/testData.ts +483 -0
- package/tests/testData.ts +0 -2
- package/tsconfig.build.tsbuildinfo +1 -1
- package/lib/ergo/initializable/InitializableByAddress.ts +0 -43
- package/lib/ergo/initializable/InitializableByToken.ts +0 -43
|
@@ -21,11 +21,7 @@ export class MockedInitializableErgoExtractor extends AbstractInitializableErgoE
|
|
|
21
21
|
return Promise.resolve({ boxes: ergoBoxes, hasNextBatch: true });
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
extractBoxData = (
|
|
25
|
-
box: V1.OutputInfo | OutputBox,
|
|
26
|
-
blockId: string,
|
|
27
|
-
height: number
|
|
28
|
-
) => {
|
|
24
|
+
extractBoxData = (box: V1.OutputInfo | OutputBox) => {
|
|
29
25
|
return undefined;
|
|
30
26
|
};
|
|
31
27
|
}
|
|
@@ -1,247 +1,355 @@
|
|
|
1
|
-
import { describe, it,
|
|
1
|
+
import { describe, expect, it, vi, vitest } from 'vitest';
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
ErgoNetworkType,
|
|
5
|
+
NodeNetwork,
|
|
6
|
+
ErgoExtractedData,
|
|
7
|
+
ExplorerNetwork,
|
|
8
|
+
} from '../../lib';
|
|
3
9
|
import { MockedInitializableErgoExtractor } from './AbstractInitializable.mock';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
10
|
+
import { transactionBatch } from './testData';
|
|
11
|
+
import { RETRIAL_COUNT } from '../../lib/constants';
|
|
6
12
|
import { AbstractInitializableErgoExtractorAction } from '../../lib/ergo/initializable';
|
|
7
13
|
|
|
8
|
-
describe('
|
|
9
|
-
describe('
|
|
14
|
+
describe('AbstractInitializableErgoExtractor', () => {
|
|
15
|
+
describe('getTotalTxCount', () => {
|
|
10
16
|
/**
|
|
11
|
-
* @target
|
|
17
|
+
* @target getTotalTxCount should return the total tx count
|
|
12
18
|
* @dependencies
|
|
19
|
+
* - explorer network
|
|
13
20
|
* @scenario
|
|
14
21
|
* - mock extractor
|
|
15
|
-
* - mock `
|
|
16
|
-
* -
|
|
17
|
-
* - run test (call `fetchDataWithOffsetLimit`)
|
|
22
|
+
* - mock `getAddressTransactionsWithOffsetLimit` in node network
|
|
23
|
+
* - run test (call `getTotalTxCount`)
|
|
18
24
|
* @expected
|
|
19
|
-
* -
|
|
20
|
-
* - return one extracted element (the unspent box) and api total
|
|
25
|
+
* - return one total tx count
|
|
21
26
|
*/
|
|
22
|
-
it('should
|
|
23
|
-
const extractor = new MockedInitializableErgoExtractor(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return false;
|
|
28
|
-
};
|
|
29
|
-
const extractSpy = vitest.fn().mockReturnValue(extractedData);
|
|
30
|
-
extractor.extractBoxData = extractSpy;
|
|
31
|
-
const txBlockSpy = vitest.fn();
|
|
32
|
-
extractor.getTxBlock = txBlockSpy;
|
|
33
|
-
const data = await extractor.fetchDataWithOffsetLimit(1252681, 0, 2);
|
|
34
|
-
expect(extractSpy).toHaveBeenCalledWith(
|
|
35
|
-
unspentBox,
|
|
36
|
-
unspentBox.blockId,
|
|
37
|
-
unspentBox.inclusionHeight
|
|
27
|
+
it('should return the total tx count', async () => {
|
|
28
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
29
|
+
ErgoNetworkType.Node,
|
|
30
|
+
'node_url',
|
|
31
|
+
'address'
|
|
38
32
|
);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
hasNextBatch: true,
|
|
33
|
+
(
|
|
34
|
+
extractor['network'] as NodeNetwork
|
|
35
|
+
).getAddressTransactionsWithOffsetLimit = vitest.fn().mockResolvedValue({
|
|
36
|
+
items: [],
|
|
37
|
+
total: 196704,
|
|
45
38
|
});
|
|
39
|
+
const totalTxCount = await extractor['getTotalTxCount']();
|
|
40
|
+
expect(totalTxCount).toEqual(196704);
|
|
46
41
|
});
|
|
42
|
+
});
|
|
47
43
|
|
|
44
|
+
describe('processTransactionBatch', () => {
|
|
48
45
|
/**
|
|
49
|
-
* @target
|
|
46
|
+
* @target processTransactionBatch should group transactions and process them in correct order
|
|
50
47
|
* @dependencies
|
|
51
48
|
* @scenario
|
|
52
49
|
* - mock extractor
|
|
53
|
-
* -
|
|
54
|
-
* -
|
|
55
|
-
* - run test (call `fetchDataWithOffsetLimit`)
|
|
50
|
+
* - spy `processTransactions`
|
|
51
|
+
* - run test (call `processTransactionBatch`)
|
|
56
52
|
* @expected
|
|
57
|
-
* - to
|
|
58
|
-
* -
|
|
53
|
+
* - to group txs in two blocks
|
|
54
|
+
* - to process each blocks transaction separately
|
|
59
55
|
*/
|
|
60
|
-
it('should
|
|
61
|
-
const extractor = new MockedInitializableErgoExtractor(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
extractor.extractBoxData = extractSpy;
|
|
66
|
-
const data = await extractor.fetchDataWithOffsetLimit(1252678, 0, 2);
|
|
67
|
-
expect(extractSpy).toHaveBeenCalledWith(
|
|
68
|
-
spentBox,
|
|
69
|
-
spentBox.blockId,
|
|
70
|
-
spentBox.inclusionHeight
|
|
56
|
+
it('should group transactions and process them in correct order', async () => {
|
|
57
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
58
|
+
ErgoNetworkType.Node,
|
|
59
|
+
'node_url',
|
|
60
|
+
'address'
|
|
71
61
|
);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
const processSpy = vitest.fn();
|
|
63
|
+
extractor.processTransactions = processSpy;
|
|
64
|
+
await extractor['processTransactionBatch'](transactionBatch);
|
|
65
|
+
expect(processSpy).toBeCalledTimes(2);
|
|
66
|
+
expect(processSpy).toHaveBeenCalledWith([transactionBatch[2]], {
|
|
67
|
+
hash: '92eaff11a4a1c29b8654473258f9d837e9ce99fc0a8a4f27c484d5871afcde64',
|
|
68
|
+
height: 1320698,
|
|
77
69
|
});
|
|
70
|
+
expect(processSpy).toHaveBeenLastCalledWith(
|
|
71
|
+
transactionBatch.slice(0, 2),
|
|
72
|
+
{
|
|
73
|
+
hash: 'b861e2134821fcf1fcdad7e6edd56c4e4495b42b2fd72762a4c79ed1db78b44b',
|
|
74
|
+
height: 1320705,
|
|
75
|
+
}
|
|
76
|
+
);
|
|
78
77
|
});
|
|
78
|
+
});
|
|
79
79
|
|
|
80
|
+
describe('initWithRetrial', () => {
|
|
80
81
|
/**
|
|
81
|
-
* @target
|
|
82
|
+
* @target initWithRetrial should not run the init job when its not set
|
|
82
83
|
* @dependencies
|
|
84
|
+
* - database
|
|
83
85
|
* @scenario
|
|
84
|
-
* - mock extractor
|
|
85
|
-
* - mock `
|
|
86
|
-
* -
|
|
87
|
-
* - run test (call `
|
|
86
|
+
* - mock extractor with false initialization
|
|
87
|
+
* - mock `removeAllData` in database actions
|
|
88
|
+
* - mock init job
|
|
89
|
+
* - run test (call `initWithRetrial`)
|
|
88
90
|
* @expected
|
|
89
|
-
* - to
|
|
90
|
-
* -
|
|
91
|
+
* - not to remove database old data
|
|
92
|
+
* - not to run the init job
|
|
91
93
|
*/
|
|
92
|
-
it('should
|
|
93
|
-
const extractor = new MockedInitializableErgoExtractor(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const extractSpy = vitest.fn().mockReturnValue(extractedData);
|
|
100
|
-
extractor.extractBoxData = extractSpy;
|
|
101
|
-
const data = await extractor.fetchDataWithOffsetLimit(1252681, 0, 2);
|
|
102
|
-
expect(extractSpy).toHaveBeenCalledWith(
|
|
103
|
-
spentBox,
|
|
104
|
-
spentBox.blockId,
|
|
105
|
-
spentBox.inclusionHeight
|
|
94
|
+
it('should not run the init job when its not set', async () => {
|
|
95
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
96
|
+
ErgoNetworkType.Node,
|
|
97
|
+
'node_url',
|
|
98
|
+
'address',
|
|
99
|
+
undefined,
|
|
100
|
+
false
|
|
106
101
|
);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
'b08fa920a6907d0e76eb0ad754439f1a26fa112b39f4de489620e4e6241930b7',
|
|
116
|
-
spendIndex: 1,
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
hasNextBatch: true,
|
|
120
|
-
});
|
|
102
|
+
const removeSpy = vitest.fn();
|
|
103
|
+
extractor['actions'] = {
|
|
104
|
+
removeAllData: removeSpy,
|
|
105
|
+
} as unknown as AbstractInitializableErgoExtractorAction<ErgoExtractedData>;
|
|
106
|
+
const initSpy = vitest.fn();
|
|
107
|
+
await extractor['initWithRetrial'](initSpy);
|
|
108
|
+
expect(removeSpy).not.toHaveBeenCalled();
|
|
109
|
+
expect(initSpy).not.toHaveBeenCalled();
|
|
121
110
|
});
|
|
122
111
|
|
|
123
112
|
/**
|
|
124
|
-
* @target
|
|
113
|
+
* @target initWithRetrial should call init job once
|
|
125
114
|
* @dependencies
|
|
115
|
+
* - database
|
|
126
116
|
* @scenario
|
|
127
117
|
* - mock extractor
|
|
128
|
-
* - mock `
|
|
129
|
-
* -
|
|
130
|
-
* - run test (call `
|
|
118
|
+
* - mock `removeAllData` in database actions
|
|
119
|
+
* - mock init job
|
|
120
|
+
* - run test (call `initWithRetrial`)
|
|
131
121
|
* @expected
|
|
132
|
-
* - to
|
|
133
|
-
* -
|
|
122
|
+
* - to remove database old data once
|
|
123
|
+
* - call init job once
|
|
134
124
|
*/
|
|
135
|
-
it('should
|
|
136
|
-
const extractor = new MockedInitializableErgoExtractor(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return false;
|
|
141
|
-
};
|
|
142
|
-
const extractSpy = vitest.fn().mockReturnValue(extractedData);
|
|
143
|
-
extractor.extractBoxData = extractSpy;
|
|
144
|
-
const data = await extractor.fetchDataWithOffsetLimit(1252678, 0, 2);
|
|
145
|
-
expect(extractSpy).toHaveBeenCalledWith(
|
|
146
|
-
spentBox,
|
|
147
|
-
spentBox.blockId,
|
|
148
|
-
spentBox.inclusionHeight
|
|
125
|
+
it('should call init job once', async () => {
|
|
126
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
127
|
+
ErgoNetworkType.Node,
|
|
128
|
+
'node_url',
|
|
129
|
+
'address'
|
|
149
130
|
);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
131
|
+
const removeSpy = vitest.fn();
|
|
132
|
+
extractor['actions'] = {
|
|
133
|
+
removeAllData: removeSpy,
|
|
134
|
+
} as unknown as AbstractInitializableErgoExtractorAction<ErgoExtractedData>;
|
|
135
|
+
const initSpy = vitest.fn();
|
|
136
|
+
await extractor['initWithRetrial'](initSpy);
|
|
137
|
+
expect(removeSpy).toHaveBeenCalledOnce();
|
|
138
|
+
expect(initSpy).toHaveBeenCalledOnce();
|
|
156
139
|
});
|
|
157
|
-
});
|
|
158
140
|
|
|
159
|
-
describe('initializeBoxes', () => {
|
|
160
141
|
/**
|
|
161
|
-
* @target
|
|
142
|
+
* @target initWithRetrial should call init job RETRIAL_COUNT number of times
|
|
162
143
|
* @dependencies
|
|
144
|
+
* - database
|
|
163
145
|
* @scenario
|
|
164
146
|
* - mock extractor
|
|
165
|
-
* -
|
|
166
|
-
* - mock
|
|
167
|
-
* - run test (call `
|
|
147
|
+
* - mock `removeAllData` in database actions
|
|
148
|
+
* - mock init job to throw error
|
|
149
|
+
* - run test (call `initWithRetrial`)
|
|
168
150
|
* @expected
|
|
169
|
-
* - to
|
|
170
|
-
* -
|
|
151
|
+
* - to remove database old data once
|
|
152
|
+
* - call init job RETRIAL_COUNT number of times
|
|
153
|
+
* - to throw error after trials
|
|
171
154
|
*/
|
|
172
|
-
it('should
|
|
173
|
-
const extractor = new MockedInitializableErgoExtractor(
|
|
155
|
+
it('should call init job RETRIAL_COUNT number of times', async () => {
|
|
156
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
157
|
+
ErgoNetworkType.Node,
|
|
158
|
+
'node_url',
|
|
159
|
+
'address'
|
|
160
|
+
);
|
|
174
161
|
const removeSpy = vitest.fn();
|
|
175
|
-
const insertSpy = vitest.fn().mockResolvedValue(true);
|
|
176
162
|
extractor['actions'] = {
|
|
177
163
|
removeAllData: removeSpy,
|
|
178
|
-
insertBoxes: insertSpy,
|
|
179
164
|
} as unknown as AbstractInitializableErgoExtractorAction<ErgoExtractedData>;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
165
|
+
const initSpy = vitest.fn().mockRejectedValue(0);
|
|
166
|
+
await expect(
|
|
167
|
+
async () => await extractor['initWithRetrial'](initSpy)
|
|
168
|
+
).rejects.toThrowError();
|
|
169
|
+
expect(removeSpy).toHaveBeenCalledOnce();
|
|
170
|
+
expect(initSpy).toHaveBeenCalledTimes(RETRIAL_COUNT);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
184
173
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
174
|
+
describe('initializeWithNode', () => {
|
|
175
|
+
/**
|
|
176
|
+
* @target initializeWithNode should process all transactions bellow the init height twice
|
|
177
|
+
* @dependencies
|
|
178
|
+
* - node network
|
|
179
|
+
* @scenario
|
|
180
|
+
* - mock extractor
|
|
181
|
+
* - mock `getAddressTransactionsWithOffsetLimit` in node network
|
|
182
|
+
* - mock `initWithRetrial` to run the job once
|
|
183
|
+
* - mock `getTotalTxCount` to return 3
|
|
184
|
+
* - run test (call `initializeWithNode`)
|
|
185
|
+
* @expected
|
|
186
|
+
* - to filter the transactions and process the txs bellow the init height
|
|
187
|
+
* - to process all filtered transactions twice
|
|
188
|
+
*/
|
|
189
|
+
it('should process all transactions bellow the init height twice', async () => {
|
|
190
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
191
|
+
ErgoNetworkType.Node,
|
|
192
|
+
'node_url',
|
|
193
|
+
'address'
|
|
194
|
+
);
|
|
195
|
+
(
|
|
196
|
+
extractor['network'] as NodeNetwork
|
|
197
|
+
).getAddressTransactionsWithOffsetLimit = vitest.fn().mockResolvedValue({
|
|
198
|
+
items: transactionBatch,
|
|
199
|
+
total: 3,
|
|
200
|
+
});
|
|
201
|
+
extractor['initWithRetrial'] = async (job: () => Promise<void>) => job();
|
|
202
|
+
extractor['getTotalTxCount'] = async () => 3;
|
|
203
|
+
const processSpy = vitest.fn();
|
|
204
|
+
extractor['processTransactionBatch'] = processSpy;
|
|
205
|
+
await extractor['initializeWithNode']({ hash: 'hash', height: 1320698 });
|
|
206
|
+
expect(processSpy).toBeCalledTimes(2);
|
|
207
|
+
expect(processSpy).toBeCalledWith([transactionBatch[2]]);
|
|
188
208
|
});
|
|
189
209
|
|
|
190
210
|
/**
|
|
191
|
-
* @target
|
|
211
|
+
* @target initializeWithNode should throw error when total transaction count changes
|
|
192
212
|
* @dependencies
|
|
213
|
+
* - node network
|
|
193
214
|
* @scenario
|
|
194
215
|
* - mock extractor
|
|
195
|
-
* -
|
|
196
|
-
* - mock `
|
|
197
|
-
* -
|
|
216
|
+
* - mock `getAddressTransactionsWithOffsetLimit` in node network
|
|
217
|
+
* - mock `initWithRetrial` to run the job once
|
|
218
|
+
* - mock `getTotalTxCount` to return 3 then 4
|
|
219
|
+
* - run test (call `initializeWithNode`)
|
|
198
220
|
* @expected
|
|
199
|
-
* - to
|
|
200
|
-
* - to call insertBoxes twice
|
|
221
|
+
* - to throw error when the number of transactions change during initialization
|
|
201
222
|
*/
|
|
202
|
-
it('should
|
|
203
|
-
const extractor = new MockedInitializableErgoExtractor(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
223
|
+
it('should throw error when total transaction count changes', async () => {
|
|
224
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
225
|
+
ErgoNetworkType.Node,
|
|
226
|
+
'node_url',
|
|
227
|
+
'address'
|
|
228
|
+
);
|
|
229
|
+
(
|
|
230
|
+
extractor['network'] as NodeNetwork
|
|
231
|
+
).getAddressTransactionsWithOffsetLimit = vitest.fn().mockResolvedValue({
|
|
232
|
+
items: transactionBatch,
|
|
233
|
+
total: 3,
|
|
234
|
+
});
|
|
235
|
+
extractor['initWithRetrial'] = async (job: () => Promise<void>) => job();
|
|
236
|
+
extractor['getTotalTxCount'] = vitest
|
|
211
237
|
.fn()
|
|
212
|
-
.mockResolvedValueOnce(
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
await extractor.initializeBoxes({ height: 100, hash: 'hash' });
|
|
219
|
-
expect(removeSpy).toBeCalledTimes(1);
|
|
220
|
-
expect(insertSpy).toBeCalledTimes(2);
|
|
238
|
+
.mockResolvedValueOnce(3)
|
|
239
|
+
.mockResolvedValue(4);
|
|
240
|
+
extractor['processTransactionBatch'] = vitest.fn();
|
|
241
|
+
expect(() =>
|
|
242
|
+
extractor['initializeWithNode']({ hash: 'hash', height: 1320698 })
|
|
243
|
+
).rejects.toThrowError();
|
|
221
244
|
});
|
|
245
|
+
});
|
|
222
246
|
|
|
247
|
+
describe('initializeWithExplorer', () => {
|
|
223
248
|
/**
|
|
224
|
-
* @target
|
|
249
|
+
* @target initializeWithExplorer should limit the height and process
|
|
250
|
+
* transactions when they are less than the API_LIMIT
|
|
225
251
|
* @dependencies
|
|
252
|
+
* - explorer network
|
|
226
253
|
* @scenario
|
|
227
254
|
* - mock extractor
|
|
228
|
-
* -
|
|
229
|
-
* -
|
|
255
|
+
* - mock `initWithRetrial` to run the job once
|
|
256
|
+
* - mock `getAddressTransactionsWithHeight` in explorer network
|
|
257
|
+
* return API_LIMIT transactions in first call (to limit the height range)
|
|
258
|
+
* return 0 transactions in second call (to pass a range without process)
|
|
259
|
+
* return transactionBatch in last call (to process the transactions when they are less than API_LIMIT)
|
|
260
|
+
* - run test (call `initializeWithExplorer`)
|
|
230
261
|
* @expected
|
|
231
|
-
* -
|
|
262
|
+
* - to limit the height when the transaction count is equal to API_LIMIT
|
|
263
|
+
* - to cover all height ranges
|
|
264
|
+
* - to process transactions when they are less than API_LIMIT
|
|
232
265
|
*/
|
|
233
|
-
it(
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
266
|
+
it(`should limit the height and process transactions when they are less than
|
|
267
|
+
the API_LIMIT`, async () => {
|
|
268
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
269
|
+
ErgoNetworkType.Explorer,
|
|
270
|
+
'explorer_url',
|
|
271
|
+
'address'
|
|
272
|
+
);
|
|
273
|
+
extractor['initWithRetrial'] = async (job: () => Promise<void>) => job();
|
|
274
|
+
const addressTxSpy = vitest
|
|
275
|
+
.fn()
|
|
276
|
+
.mockResolvedValueOnce(new Array(100).fill(transactionBatch[0]))
|
|
277
|
+
.mockResolvedValueOnce([])
|
|
278
|
+
.mockResolvedValueOnce(transactionBatch);
|
|
279
|
+
(
|
|
280
|
+
extractor['network'] as ExplorerNetwork
|
|
281
|
+
).getAddressTransactionsWithHeight = addressTxSpy;
|
|
282
|
+
const processSpy = vitest.fn();
|
|
283
|
+
extractor['processTransactionBatch'] = processSpy;
|
|
284
|
+
await extractor['initializeWithExplorer']({
|
|
285
|
+
hash: 'hash',
|
|
286
|
+
height: 1320800,
|
|
287
|
+
});
|
|
288
|
+
expect(addressTxSpy).toHaveBeenCalledWith('address', 0, 1320800);
|
|
289
|
+
expect(addressTxSpy).toHaveBeenCalledWith('address', 0, 660400);
|
|
290
|
+
expect(addressTxSpy).toHaveBeenLastCalledWith('address', 660401, 1320800);
|
|
291
|
+
expect(processSpy).toHaveBeenCalledTimes(1);
|
|
292
|
+
expect(processSpy).toHaveBeenCalledWith(transactionBatch);
|
|
293
|
+
});
|
|
241
294
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
295
|
+
/**
|
|
296
|
+
* @target initializeWithExplorer should process all block transactions when
|
|
297
|
+
* the number of transactions in the block is more than API_LIMIT
|
|
298
|
+
* @dependencies
|
|
299
|
+
* - explorer network
|
|
300
|
+
* @scenario
|
|
301
|
+
* - mock extractor
|
|
302
|
+
* - mock `initWithRetrial` to run the job once
|
|
303
|
+
* - mock `getAddressTransactionsWithHeight` to return 100 transactions in one block
|
|
304
|
+
* - spy all other functions to check the calls
|
|
305
|
+
* - run test (call `initializeWithExplorer`)
|
|
306
|
+
* @expected
|
|
307
|
+
* - to process all transactions in block 1320000
|
|
308
|
+
* - not to stuck at a large block and complete the process
|
|
309
|
+
*/
|
|
310
|
+
it(`should process all block transactions when the number of transactions in
|
|
311
|
+
the block is more than API_LIMIT`, async () => {
|
|
312
|
+
// mock extractor
|
|
313
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
314
|
+
ErgoNetworkType.Explorer,
|
|
315
|
+
'explorer_url',
|
|
316
|
+
'address'
|
|
317
|
+
);
|
|
318
|
+
// mock `initWithRetrial` to run the job once
|
|
319
|
+
extractor['initWithRetrial'] = async (job: () => Promise<void>) => job();
|
|
320
|
+
// mock `getAddressTransactionsWithHeight` to return 100 transactions in one block
|
|
321
|
+
const exNetwork = extractor['network'] as ExplorerNetwork;
|
|
322
|
+
const addressTxSpy = vitest
|
|
323
|
+
.fn()
|
|
324
|
+
.mockImplementation(
|
|
325
|
+
(address: string, fromHeight: number, toHeight: number) => {
|
|
326
|
+
if (fromHeight <= 1320000 && toHeight >= 1320000)
|
|
327
|
+
return new Array(100).fill(transactionBatch[0]);
|
|
328
|
+
return [];
|
|
329
|
+
}
|
|
330
|
+
);
|
|
331
|
+
exNetwork.getAddressTransactionsWithHeight = addressTxSpy;
|
|
332
|
+
// spy all other functions to check the calls
|
|
333
|
+
const blockIdSpy = vi.fn().mockResolvedValue('blockId');
|
|
334
|
+
const blockTxsSpy = vi.fn().mockResolvedValue([]);
|
|
335
|
+
exNetwork.getBlockIdAtHeight = blockIdSpy;
|
|
336
|
+
exNetwork.getBlockTxs = blockTxsSpy;
|
|
337
|
+
const processSpy = vitest.fn();
|
|
338
|
+
const processBatchSpy = vitest.fn();
|
|
339
|
+
extractor.processTransactions = processSpy;
|
|
340
|
+
extractor['processTransactionBatch'] = processBatchSpy;
|
|
341
|
+
// run test (call `initializeWithExplorer`)
|
|
342
|
+
await extractor['initializeWithExplorer']({
|
|
343
|
+
hash: 'hash',
|
|
344
|
+
height: 1320800,
|
|
345
|
+
});
|
|
346
|
+
expect(blockIdSpy).toHaveBeenCalledWith(1320000);
|
|
347
|
+
expect(blockTxsSpy).toHaveBeenCalledWith('blockId');
|
|
348
|
+
expect(processSpy).toHaveBeenCalledWith([], {
|
|
349
|
+
hash: 'blockId',
|
|
350
|
+
height: 1320000,
|
|
351
|
+
});
|
|
352
|
+
expect(processBatchSpy).not.toBeCalled();
|
|
245
353
|
});
|
|
246
354
|
});
|
|
247
355
|
});
|