@rosen-bridge/abstract-extractor 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/ergo/AbstractErgoExtractor.d.ts +31 -8
- package/dist/ergo/AbstractErgoExtractor.d.ts.map +1 -1
- package/dist/ergo/AbstractErgoExtractor.js +73 -8
- package/dist/ergo/AbstractErgoExtractorAction.d.ts +38 -10
- package/dist/ergo/AbstractErgoExtractorAction.d.ts.map +1 -1
- package/dist/ergo/AbstractErgoExtractorAction.js +134 -1
- package/dist/ergo/AbstractErgoExtractorEntity.d.ts +11 -0
- package/dist/ergo/AbstractErgoExtractorEntity.d.ts.map +1 -0
- package/dist/ergo/AbstractErgoExtractorEntity.js +57 -0
- package/dist/ergo/index.d.ts +1 -0
- package/dist/ergo/index.d.ts.map +1 -1
- package/dist/ergo/index.js +2 -1
- package/dist/ergo/initializable/AbstractInitializable.d.ts +4 -3
- package/dist/ergo/initializable/AbstractInitializable.d.ts.map +1 -1
- package/dist/ergo/initializable/AbstractInitializable.js +9 -5
- package/dist/ergo/initializable/AbstractInitializableAction.d.ts +7 -2
- package/dist/ergo/initializable/AbstractInitializableAction.d.ts.map +1 -1
- package/dist/ergo/initializable/AbstractInitializableAction.js +11 -1
- package/dist/ergo/interfaces.d.ts +21 -7
- package/dist/ergo/interfaces.d.ts.map +1 -1
- package/dist/ergo/interfaces.js +8 -1
- package/lib/ergo/AbstractErgoExtractor.ts +107 -23
- package/lib/ergo/AbstractErgoExtractorAction.ts +187 -18
- package/lib/ergo/AbstractErgoExtractorEntity.ts +28 -0
- package/lib/ergo/index.ts +1 -0
- package/lib/ergo/initializable/AbstractInitializable.ts +22 -9
- package/lib/ergo/initializable/AbstractInitializableAction.ts +19 -3
- package/lib/ergo/interfaces.ts +25 -7
- package/package.json +6 -2
- package/tests/{AbstractExtractor.mock.ts → AbstractErgoExtractor.mock.ts} +12 -7
- package/tests/AbstractErgoExtractor.spec.ts +281 -0
- package/tests/AbstractErgoExtractorAction.mock.ts +45 -0
- package/tests/AbstractErgoExtractorAction.spec.ts +269 -0
- package/tests/initializable/AbstractInitializable.mock.ts +15 -8
- package/tests/initializable/AbstractInitializable.spec.ts +37 -5
- package/tests/initializable/AbstractInitializableAction.mock.ts +45 -0
- package/tests/initializable/AbstractInitializableAction.spec.ts +65 -0
- package/tests/testData.ts +38 -2
- package/tests/testUtils.ts +22 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/ergo/initializable/InitializableByAddress.d.ts +0 -19
- package/dist/ergo/initializable/InitializableByAddress.d.ts.map +0 -1
- package/dist/ergo/initializable/InitializableByAddress.js +0 -30
- package/dist/ergo/initializable/InitializableByToken.d.ts +0 -19
- package/dist/ergo/initializable/InitializableByToken.d.ts.map +0 -1
- package/dist/ergo/initializable/InitializableByToken.js +0 -30
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/tests/AbstractExtractor.spec.ts +0 -106
|
@@ -3,8 +3,9 @@ import { describe, expect, it, vi, vitest } from 'vitest';
|
|
|
3
3
|
import {
|
|
4
4
|
ErgoNetworkType,
|
|
5
5
|
NodeNetwork,
|
|
6
|
-
|
|
6
|
+
AbstractBoxData,
|
|
7
7
|
ExplorerNetwork,
|
|
8
|
+
AbstractErgoExtractorEntity,
|
|
8
9
|
} from '../../lib';
|
|
9
10
|
import { MockedInitializableErgoExtractor } from './AbstractInitializable.mock';
|
|
10
11
|
import { transactionBatch } from './testData';
|
|
@@ -59,7 +60,7 @@ describe('AbstractInitializableErgoExtractor', () => {
|
|
|
59
60
|
'node_url',
|
|
60
61
|
'address'
|
|
61
62
|
);
|
|
62
|
-
const processSpy = vitest.fn();
|
|
63
|
+
const processSpy = vitest.fn().mockResolvedValue(true);
|
|
63
64
|
extractor.processTransactions = processSpy;
|
|
64
65
|
await extractor['processTransactionBatch'](transactionBatch);
|
|
65
66
|
expect(processSpy).toBeCalledTimes(2);
|
|
@@ -75,6 +76,28 @@ describe('AbstractInitializableErgoExtractor', () => {
|
|
|
75
76
|
}
|
|
76
77
|
);
|
|
77
78
|
});
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @target processTransactionBatch should throw error when processing transactions fails for a block
|
|
82
|
+
* @dependencies
|
|
83
|
+
* @scenario
|
|
84
|
+
* - mock extractor
|
|
85
|
+
* - spy `processTransactions` to return false (always fails)
|
|
86
|
+
* - run test (call `processTransactionBatch`)
|
|
87
|
+
* @expected
|
|
88
|
+
* - to throw error
|
|
89
|
+
*/
|
|
90
|
+
it('should throw error when processing transactions fails for a block', async () => {
|
|
91
|
+
const extractor = new MockedInitializableErgoExtractor(
|
|
92
|
+
ErgoNetworkType.Node,
|
|
93
|
+
'node_url',
|
|
94
|
+
'address'
|
|
95
|
+
);
|
|
96
|
+
extractor.processTransactions = vitest.fn().mockResolvedValue(false);
|
|
97
|
+
await expect(() =>
|
|
98
|
+
extractor['processTransactionBatch'](transactionBatch)
|
|
99
|
+
).rejects.toThrowError();
|
|
100
|
+
});
|
|
78
101
|
});
|
|
79
102
|
|
|
80
103
|
describe('initWithRetrial', () => {
|
|
@@ -102,7 +125,10 @@ describe('AbstractInitializableErgoExtractor', () => {
|
|
|
102
125
|
const removeSpy = vitest.fn();
|
|
103
126
|
extractor['actions'] = {
|
|
104
127
|
removeAllData: removeSpy,
|
|
105
|
-
} as unknown as AbstractInitializableErgoExtractorAction<
|
|
128
|
+
} as unknown as AbstractInitializableErgoExtractorAction<
|
|
129
|
+
AbstractBoxData,
|
|
130
|
+
AbstractErgoExtractorEntity
|
|
131
|
+
>;
|
|
106
132
|
const initSpy = vitest.fn();
|
|
107
133
|
await extractor['initWithRetrial'](initSpy);
|
|
108
134
|
expect(removeSpy).not.toHaveBeenCalled();
|
|
@@ -131,7 +157,10 @@ describe('AbstractInitializableErgoExtractor', () => {
|
|
|
131
157
|
const removeSpy = vitest.fn();
|
|
132
158
|
extractor['actions'] = {
|
|
133
159
|
removeAllData: removeSpy,
|
|
134
|
-
} as unknown as AbstractInitializableErgoExtractorAction<
|
|
160
|
+
} as unknown as AbstractInitializableErgoExtractorAction<
|
|
161
|
+
AbstractBoxData,
|
|
162
|
+
AbstractErgoExtractorEntity
|
|
163
|
+
>;
|
|
135
164
|
const initSpy = vitest.fn();
|
|
136
165
|
await extractor['initWithRetrial'](initSpy);
|
|
137
166
|
expect(removeSpy).toHaveBeenCalledOnce();
|
|
@@ -161,7 +190,10 @@ describe('AbstractInitializableErgoExtractor', () => {
|
|
|
161
190
|
const removeSpy = vitest.fn();
|
|
162
191
|
extractor['actions'] = {
|
|
163
192
|
removeAllData: removeSpy,
|
|
164
|
-
} as unknown as AbstractInitializableErgoExtractorAction<
|
|
193
|
+
} as unknown as AbstractInitializableErgoExtractorAction<
|
|
194
|
+
AbstractBoxData,
|
|
195
|
+
AbstractErgoExtractorEntity
|
|
196
|
+
>;
|
|
165
197
|
const initSpy = vitest.fn().mockRejectedValue(0);
|
|
166
198
|
await expect(
|
|
167
199
|
async () => await extractor['initWithRetrial'](initSpy)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { DataSource } from 'typeorm';
|
|
2
|
+
import { pick } from 'lodash-es';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
AbstractErgoExtractorEntity,
|
|
6
|
+
BlockInfo,
|
|
7
|
+
AbstractBoxData,
|
|
8
|
+
AbstractInitializableErgoExtractorAction,
|
|
9
|
+
} from '../../lib';
|
|
10
|
+
import { TestEntity } from '../testUtils';
|
|
11
|
+
|
|
12
|
+
export class TestInitializableErgoExtractorAction extends AbstractInitializableErgoExtractorAction<
|
|
13
|
+
AbstractBoxData,
|
|
14
|
+
AbstractErgoExtractorEntity
|
|
15
|
+
> {
|
|
16
|
+
constructor(dataSource: DataSource) {
|
|
17
|
+
super(dataSource, TestEntity);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* create the test database entity from data and block information
|
|
22
|
+
*/
|
|
23
|
+
createEntity = (
|
|
24
|
+
boxes: AbstractBoxData[],
|
|
25
|
+
block: BlockInfo,
|
|
26
|
+
extractor: string
|
|
27
|
+
): Omit<AbstractErgoExtractorEntity, 'id'>[] => {
|
|
28
|
+
return boxes.map((box) => ({
|
|
29
|
+
boxId: box.boxId,
|
|
30
|
+
block: block.hash,
|
|
31
|
+
height: block.height,
|
|
32
|
+
serialized: box.serialized,
|
|
33
|
+
extractor: extractor,
|
|
34
|
+
}));
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* convert the database entity back to raw data
|
|
39
|
+
*/
|
|
40
|
+
convertEntityToData = (
|
|
41
|
+
entities: AbstractErgoExtractorEntity[]
|
|
42
|
+
): AbstractBoxData[] => {
|
|
43
|
+
return entities.map((data) => pick(data, ['boxId', 'serialized']));
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { DataSource, Repository } from 'typeorm';
|
|
2
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { TestInitializableErgoExtractorAction } from './AbstractInitializableAction.mock';
|
|
5
|
+
import { createDatabase, TestEntity } from '../testUtils';
|
|
6
|
+
import { sampleEntities } from '../testData';
|
|
7
|
+
|
|
8
|
+
describe('AbstractErgoExtractorAction', () => {
|
|
9
|
+
let dataSource: DataSource;
|
|
10
|
+
let action: TestInitializableErgoExtractorAction;
|
|
11
|
+
let repository: Repository<TestEntity>;
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
dataSource = await createDatabase();
|
|
14
|
+
action = new TestInitializableErgoExtractorAction(dataSource);
|
|
15
|
+
repository = dataSource.getRepository(TestEntity);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('removeAllData', () => {
|
|
19
|
+
/**
|
|
20
|
+
* @target removeAllData should remove all available data related to this extractor
|
|
21
|
+
* @dependencies
|
|
22
|
+
* @scenario
|
|
23
|
+
* - insert 4 entities related to this extractor
|
|
24
|
+
* - run test (call `removeAllData`)
|
|
25
|
+
* @expected
|
|
26
|
+
* - to have 4 entities before removing
|
|
27
|
+
* - to have no remaining entities after remove
|
|
28
|
+
*/
|
|
29
|
+
it(`should remove all available data related to this extractor`, async () => {
|
|
30
|
+
await dataSource.getRepository(TestEntity).insert(sampleEntities);
|
|
31
|
+
const countBefore = await repository.count();
|
|
32
|
+
|
|
33
|
+
await action.removeAllData('extractor');
|
|
34
|
+
const countAfter = await repository.count();
|
|
35
|
+
|
|
36
|
+
expect(countBefore).toEqual(4);
|
|
37
|
+
expect(countAfter).toEqual(0);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @target removeAllData should not remove any data related to another extractor
|
|
42
|
+
* @dependencies
|
|
43
|
+
* @scenario
|
|
44
|
+
* - insert 4 entities related to another extractor
|
|
45
|
+
* - run test (call `removeAllData`)
|
|
46
|
+
* @expected
|
|
47
|
+
* - to have 4 entities after removing
|
|
48
|
+
*/
|
|
49
|
+
it(`should not remove any data related to another extractor`, async () => {
|
|
50
|
+
await dataSource.getRepository(TestEntity).insert(
|
|
51
|
+
sampleEntities.map((entity) => ({
|
|
52
|
+
...entity,
|
|
53
|
+
extractor: 'extractor-new',
|
|
54
|
+
}))
|
|
55
|
+
);
|
|
56
|
+
const countBefore = await repository.count();
|
|
57
|
+
|
|
58
|
+
await action.removeAllData('extractor');
|
|
59
|
+
const countAfter = await repository.count();
|
|
60
|
+
|
|
61
|
+
expect(countBefore).toEqual(4);
|
|
62
|
+
expect(countAfter).toEqual(4);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
package/tests/testData.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Block } from '../lib';
|
|
2
|
+
import { TestEntity } from './testUtils';
|
|
2
3
|
|
|
3
4
|
export const tx = {
|
|
4
5
|
id: '3b91fbd2b6f4f3f971098655ffa320841001b071908de057cdf8c425cd3b3e61',
|
|
@@ -100,8 +101,6 @@ export const extractedData = {
|
|
|
100
101
|
boxId: 'boxId1',
|
|
101
102
|
address: 'address1',
|
|
102
103
|
serialized: 'serialized1',
|
|
103
|
-
blockId: 'blockId1',
|
|
104
|
-
height: 98,
|
|
105
104
|
};
|
|
106
105
|
|
|
107
106
|
export const block: Block = {
|
|
@@ -109,3 +108,40 @@ export const block: Block = {
|
|
|
109
108
|
height: 100,
|
|
110
109
|
parentHash: 'parentHash',
|
|
111
110
|
} as Block;
|
|
111
|
+
|
|
112
|
+
export const block2: Block = {
|
|
113
|
+
hash: 'hash2',
|
|
114
|
+
height: 101,
|
|
115
|
+
parentHash: 'parentHash2',
|
|
116
|
+
} as Block;
|
|
117
|
+
|
|
118
|
+
export const sampleEntities: Omit<TestEntity, 'id'>[] = [
|
|
119
|
+
{
|
|
120
|
+
extractor: 'extractor',
|
|
121
|
+
boxId: '1',
|
|
122
|
+
serialized: 'serialized1',
|
|
123
|
+
block: 'blockId1',
|
|
124
|
+
height: 100,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
extractor: 'extractor',
|
|
128
|
+
boxId: '2',
|
|
129
|
+
serialized: 'serialized2',
|
|
130
|
+
block: 'blockId2',
|
|
131
|
+
height: 200,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
extractor: 'extractor',
|
|
135
|
+
boxId: '3',
|
|
136
|
+
serialized: 'serialized3',
|
|
137
|
+
block: 'blockId3',
|
|
138
|
+
height: 300,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
extractor: 'extractor',
|
|
142
|
+
boxId: '4',
|
|
143
|
+
serialized: 'serialized4',
|
|
144
|
+
block: 'blockId4',
|
|
145
|
+
height: 400,
|
|
146
|
+
},
|
|
147
|
+
];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DataSource, Entity } from 'typeorm';
|
|
2
|
+
import { AbstractErgoExtractorEntity } from '../lib';
|
|
3
|
+
|
|
4
|
+
@Entity('test_entity')
|
|
5
|
+
export class TestEntity extends AbstractErgoExtractorEntity {}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* generates a dataSource with in memory database for testing
|
|
9
|
+
*/
|
|
10
|
+
export const createDatabase = async (): Promise<DataSource> => {
|
|
11
|
+
const dataSource = new DataSource({
|
|
12
|
+
type: 'sqlite',
|
|
13
|
+
database: `:memory:`,
|
|
14
|
+
entities: [TestEntity],
|
|
15
|
+
migrations: [],
|
|
16
|
+
synchronize: true,
|
|
17
|
+
logging: false,
|
|
18
|
+
});
|
|
19
|
+
await dataSource.initialize();
|
|
20
|
+
await dataSource.runMigrations();
|
|
21
|
+
return dataSource;
|
|
22
|
+
};
|