@subql/node-starknet 6.0.2-0 → 6.0.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.
- package/CHANGELOG.md +6 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/blockchain.service.js.map +1 -1
- package/dist/indexer/types.js +1 -1
- package/dist/indexer/types.js.map +1 -1
- package/dist/starknet/api.starknet.d.ts +1 -1
- package/dist/starknet/api.starknet.js +1 -6
- package/dist/starknet/api.starknet.js.map +1 -1
- package/dist/starknet/decodeCalldata.d.ts +1 -1
- package/dist/starknet/decodeCalldata.js.map +1 -1
- package/dist/starknet/finalized.block.starknet.d.ts +1 -1
- package/dist/starknet/finalized.block.starknet.js.map +1 -1
- package/dist/starknet/safe-api.d.ts +4 -5
- package/dist/starknet/safe-api.js.map +1 -1
- package/dist/starknet/utils.starknet.d.ts +3 -2
- package/dist/starknet/utils.starknet.js +7 -2
- package/dist/starknet/utils.starknet.js.map +1 -1
- package/package.json +16 -6
- package/test/projectFixture/template-v1.0.0/package.json +30 -0
- package/test/projectFixture/v1.0.0/package.json +30 -0
- package/dist/blockchain.service.spec.d.ts +0 -1
- package/dist/blockchain.service.spec.js +0 -27
- package/dist/blockchain.service.spec.js.map +0 -1
- package/dist/indexer/dictionary/v1/starknetDictionaryV1.spec.d.ts +0 -1
- package/dist/indexer/dictionary/v1/starknetDictionaryV1.spec.js +0 -189
- package/dist/indexer/dictionary/v1/starknetDictionaryV1.spec.js.map +0 -1
- package/dist/starknet/api.service.starknet.spec.d.ts +0 -1
- package/dist/starknet/api.service.starknet.spec.js +0 -79
- package/dist/starknet/api.service.starknet.spec.js.map +0 -1
- package/dist/starknet/api.starknet.test.d.ts +0 -1
- package/dist/starknet/api.starknet.test.js +0 -183
- package/dist/starknet/api.starknet.test.js.map +0 -1
- package/dist/starknet/block.starknet.spec.d.ts +0 -1
- package/dist/starknet/block.starknet.spec.js +0 -158
- package/dist/starknet/block.starknet.spec.js.map +0 -1
- package/dist/starknet/decodeCalldata.spec.d.ts +0 -1
- package/dist/starknet/decodeCalldata.spec.js +0 -112
- package/dist/starknet/decodeCalldata.spec.js.map +0 -1
- package/dist/starknet/finalized.block.starknet.spec.d.ts +0 -1
- package/dist/starknet/finalized.block.starknet.spec.js +0 -112
- package/dist/starknet/finalized.block.starknet.spec.js.map +0 -1
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
6
|
-
const api_starknet_1 = require("./api.starknet");
|
|
7
|
-
const block_starknet_1 = require("./block.starknet");
|
|
8
|
-
const utils_starknet_1 = require("./utils.starknet");
|
|
9
|
-
const HTTP_ENDPOINT = 'https://free-rpc.nethermind.io/mainnet-juno/v0_7';
|
|
10
|
-
jest.setTimeout(100000);
|
|
11
|
-
describe('block filters', () => {
|
|
12
|
-
let strkApi;
|
|
13
|
-
const eventEmitter = new event_emitter_1.EventEmitter2();
|
|
14
|
-
const fetchBlock = async (height) => {
|
|
15
|
-
const block = await strkApi.fetchBlock(height);
|
|
16
|
-
return block.block;
|
|
17
|
-
};
|
|
18
|
-
beforeAll(async () => {
|
|
19
|
-
strkApi = new api_starknet_1.StarknetApi(HTTP_ENDPOINT, eventEmitter);
|
|
20
|
-
await strkApi.init();
|
|
21
|
-
});
|
|
22
|
-
describe('Filter transactions', () => {
|
|
23
|
-
it('filter with invoke tx', async () => {
|
|
24
|
-
// https://starkscan.co/tx/0x00b3173b7a65b32fc8669da8f4676a7ef10c6f58ddd3159db7c0cd3de1025443
|
|
25
|
-
const block = await fetchBlock(986480);
|
|
26
|
-
const tx = block.transactions.find((tx) => tx.hash ===
|
|
27
|
-
'0xb3173b7a65b32fc8669da8f4676a7ef10c6f58ddd3159db7c0cd3de1025443');
|
|
28
|
-
// Filter by address
|
|
29
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
30
|
-
type: 'INVOKE',
|
|
31
|
-
// StarkGate: STRK Token Transfer
|
|
32
|
-
function: '0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e',
|
|
33
|
-
}, '0x0xxxxx')).toBeFalsy();
|
|
34
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
35
|
-
type: 'INVOKE',
|
|
36
|
-
}, '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d')).toBeTruthy();
|
|
37
|
-
// Expect filtered match transaction will attach will decodedCalls
|
|
38
|
-
expect(tx.decodedCalls?.length).toBe(4);
|
|
39
|
-
// filter function selector with both text and hex
|
|
40
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
41
|
-
function: 'approve',
|
|
42
|
-
}, '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d')).toBeFalsy();
|
|
43
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
44
|
-
function: '0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e',
|
|
45
|
-
}, '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d')).toBeTruthy();
|
|
46
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
47
|
-
function: 'transfer',
|
|
48
|
-
}, '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d')).toBeTruthy();
|
|
49
|
-
//Filter with "to"
|
|
50
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
51
|
-
to: '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d',
|
|
52
|
-
})).toBeTruthy();
|
|
53
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
54
|
-
to: '0x047aaaaad',
|
|
55
|
-
})).toBeFalsy();
|
|
56
|
-
//Filter with function is "null"
|
|
57
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
58
|
-
function: null,
|
|
59
|
-
})).toBeFalsy();
|
|
60
|
-
//Filter with to is "null"
|
|
61
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
62
|
-
to: null,
|
|
63
|
-
})).toBeFalsy();
|
|
64
|
-
});
|
|
65
|
-
it('filter with tx function or to is null', () => {
|
|
66
|
-
const mockTx1 = {
|
|
67
|
-
calldata: ['0xmock', null],
|
|
68
|
-
parseCallData: jest.fn(),
|
|
69
|
-
};
|
|
70
|
-
//Filter with function is "null"
|
|
71
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(mockTx1, {
|
|
72
|
-
function: null,
|
|
73
|
-
})).toBeTruthy();
|
|
74
|
-
//Filter with to is "null"
|
|
75
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(mockTx1, {
|
|
76
|
-
to: null,
|
|
77
|
-
})).toBeTruthy();
|
|
78
|
-
// test with decode calls
|
|
79
|
-
const mockTx2 = {
|
|
80
|
-
parseCallData: () => {
|
|
81
|
-
return [{ to: null, selector: null, calldata: [] }];
|
|
82
|
-
},
|
|
83
|
-
};
|
|
84
|
-
//Filter with function is "null"
|
|
85
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(mockTx2, {
|
|
86
|
-
function: null,
|
|
87
|
-
})).toBeTruthy();
|
|
88
|
-
//Filter with to is "null"
|
|
89
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(mockTx2, {
|
|
90
|
-
to: null,
|
|
91
|
-
})).toBeTruthy();
|
|
92
|
-
});
|
|
93
|
-
it('should filter tx with multiple conditions', async () => {
|
|
94
|
-
const block_997058 = await fetchBlock(997058);
|
|
95
|
-
// https://starkscan.co/tx/0x055588e82f864f830c4d1d1117e6e8d61a917ef18cf79961af001dc321d96cb3
|
|
96
|
-
const txWithdraw = block_997058.transactions.find((tx) => tx.hash ===
|
|
97
|
-
'0x55588e82f864f830c4d1d1117e6e8d61a917ef18cf79961af001dc321d96cb3');
|
|
98
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(txWithdraw, {
|
|
99
|
-
to: '0x04c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
100
|
-
function: 'withdraw',
|
|
101
|
-
type: 'INVOKE',
|
|
102
|
-
})).toBeTruthy();
|
|
103
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(txWithdraw, {
|
|
104
|
-
to: '0x04c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
105
|
-
function: '0x015511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77', // with extra 0 padding
|
|
106
|
-
type: 'INVOKE',
|
|
107
|
-
})).toBeTruthy();
|
|
108
|
-
});
|
|
109
|
-
it('decodeCalls only on filtered tx', async () => {
|
|
110
|
-
// https://starkscan.co/tx/0x00b3173b7a65b32fc8669da8f4676a7ef10c6f58ddd3159db7c0cd3de1025443
|
|
111
|
-
const block = await fetchBlock(986480);
|
|
112
|
-
const tx = block.transactions.find((tx) => tx.hash ===
|
|
113
|
-
'0xb3173b7a65b32fc8669da8f4676a7ef10c6f58ddd3159db7c0cd3de1025443');
|
|
114
|
-
// Filter should be failed, and it should not decode calls
|
|
115
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
116
|
-
type: 'INVOKE',
|
|
117
|
-
function: 'mockFn',
|
|
118
|
-
}, '0x0xxxxx')).toBeFalsy();
|
|
119
|
-
expect(tx.decodedCalls).toBeUndefined();
|
|
120
|
-
});
|
|
121
|
-
it('filter L1 / Invoke v0 transaction', async () => {
|
|
122
|
-
// https://starkscan.co/tx/0x043ce8e6e2ad703a81701f85ce26a8fb32ad54cc2fac7685ed0b1367a4813ade
|
|
123
|
-
const block = await fetchBlock(981920);
|
|
124
|
-
const tx = block.transactions.find((tx) => (0, utils_starknet_1.hexEq)(tx.hash, '0x043ce8e6e2ad703a81701f85ce26a8fb32ad54cc2fac7685ed0b1367a4813ade'));
|
|
125
|
-
// Filter by address
|
|
126
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
127
|
-
type: 'L1_HANDLER',
|
|
128
|
-
}, '0x073314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82')).toBeTruthy();
|
|
129
|
-
// Filter by Selector
|
|
130
|
-
expect((0, block_starknet_1.filterTransactionsProcessor)(tx, {
|
|
131
|
-
function: '0x01b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19',
|
|
132
|
-
}, '0x073314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82')).toBeTruthy();
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
describe('Filter logs', () => {
|
|
136
|
-
it('filter events with plain text also hex', async () => {
|
|
137
|
-
// https://starkscan.co/tx/0x04b546ff4375c16c30c03bd92d2d9082041e5e9397f5bda4f832661d6c029655#events
|
|
138
|
-
const block = await fetchBlock(986480);
|
|
139
|
-
const testLog = block.logs[2];
|
|
140
|
-
expect(testLog.transaction.hash).toEqual('0x4b546ff4375c16c30c03bd92d2d9082041e5e9397f5bda4f832661d6c029655');
|
|
141
|
-
// Filter with "address"
|
|
142
|
-
expect((0, block_starknet_1.filterLogsProcessor)(block.logs[2], {}, '0x06a9e4c6f0799160ea8ddc43ff982a5f83d7f633e9732ce42701de1288ff705f')).toBeTruthy();
|
|
143
|
-
expect((0, block_starknet_1.filterLogsProcessor)(block.logs[2], {
|
|
144
|
-
topics: ['Transfer'],
|
|
145
|
-
})).toBeFalsy();
|
|
146
|
-
// Event name can be in plain text or hex
|
|
147
|
-
expect((0, block_starknet_1.filterLogsProcessor)(block.logs[2], {
|
|
148
|
-
topics: [
|
|
149
|
-
'0x1a2f334228cee715f1f0f54053bb6b5eac54fa336e0bc1aacf7516decb0471d',
|
|
150
|
-
],
|
|
151
|
-
})).toBeTruthy();
|
|
152
|
-
expect((0, block_starknet_1.filterLogsProcessor)(block.logs[2], {
|
|
153
|
-
topics: ['StoreSetRecord'],
|
|
154
|
-
})).toBeTruthy();
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
//# sourceMappingURL=block.starknet.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"block.starknet.spec.js","sourceRoot":"","sources":["../../src/starknet/block.starknet.spec.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { StarknetBlock, StarknetTransaction } from '@subql/types-starknet';\nimport { StarknetApi } from './api.starknet';\nimport {\n filterLogsProcessor,\n filterTransactionsProcessor,\n} from './block.starknet';\nimport { hexEq } from './utils.starknet';\n\nconst HTTP_ENDPOINT = 'https://free-rpc.nethermind.io/mainnet-juno/v0_7';\n\njest.setTimeout(100000);\n\ndescribe('block filters', () => {\n let strkApi: StarknetApi;\n const eventEmitter = new EventEmitter2();\n\n const fetchBlock = async (height: number) => {\n const block = await strkApi.fetchBlock(height);\n\n return block.block as StarknetBlock;\n };\n\n beforeAll(async () => {\n strkApi = new StarknetApi(HTTP_ENDPOINT, eventEmitter);\n await strkApi.init();\n });\n\n describe('Filter transactions', () => {\n it('filter with invoke tx', async () => {\n // https://starkscan.co/tx/0x00b3173b7a65b32fc8669da8f4676a7ef10c6f58ddd3159db7c0cd3de1025443\n const block = await fetchBlock(986480);\n const tx = block.transactions.find(\n (tx) =>\n tx.hash ===\n '0xb3173b7a65b32fc8669da8f4676a7ef10c6f58ddd3159db7c0cd3de1025443',\n );\n // Filter by address\n expect(\n filterTransactionsProcessor(\n tx!,\n {\n type: 'INVOKE',\n // StarkGate: STRK Token Transfer\n function:\n '0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e',\n },\n '0x0xxxxx',\n ),\n ).toBeFalsy();\n\n expect(\n filterTransactionsProcessor(\n tx!,\n {\n type: 'INVOKE',\n },\n '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d',\n ),\n ).toBeTruthy();\n\n // Expect filtered match transaction will attach will decodedCalls\n expect(tx!.decodedCalls?.length).toBe(4);\n\n // filter function selector with both text and hex\n expect(\n filterTransactionsProcessor(\n tx!,\n {\n function: 'approve',\n },\n '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d',\n ),\n ).toBeFalsy();\n\n expect(\n filterTransactionsProcessor(\n tx!,\n {\n function:\n '0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e',\n },\n '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d',\n ),\n ).toBeTruthy();\n\n expect(\n filterTransactionsProcessor(\n tx!,\n {\n function: 'transfer',\n },\n '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d',\n ),\n ).toBeTruthy();\n\n //Filter with \"to\"\n expect(\n filterTransactionsProcessor(tx!, {\n to: '0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d',\n }),\n ).toBeTruthy();\n\n expect(\n filterTransactionsProcessor(tx!, {\n to: '0x047aaaaad',\n }),\n ).toBeFalsy();\n\n //Filter with function is \"null\"\n expect(\n filterTransactionsProcessor(tx!, {\n function: null,\n }),\n ).toBeFalsy();\n\n //Filter with to is \"null\"\n expect(\n filterTransactionsProcessor(tx!, {\n to: null,\n }),\n ).toBeFalsy();\n });\n\n it('filter with tx function or to is null', () => {\n const mockTx1 = {\n calldata: ['0xmock', null],\n parseCallData: jest.fn(),\n } as unknown as StarknetTransaction;\n //Filter with function is \"null\"\n expect(\n filterTransactionsProcessor(mockTx1, {\n function: null,\n }),\n ).toBeTruthy();\n\n //Filter with to is \"null\"\n expect(\n filterTransactionsProcessor(mockTx1, {\n to: null,\n }),\n ).toBeTruthy();\n\n // test with decode calls\n const mockTx2 = {\n parseCallData: () => {\n return [{ to: null, selector: null, calldata: [] }];\n },\n } as unknown as StarknetTransaction;\n\n //Filter with function is \"null\"\n expect(\n filterTransactionsProcessor(mockTx2, {\n function: null,\n }),\n ).toBeTruthy();\n\n //Filter with to is \"null\"\n expect(\n filterTransactionsProcessor(mockTx2, {\n to: null,\n }),\n ).toBeTruthy();\n });\n\n it('should filter tx with multiple conditions', async () => {\n const block_997058 = await fetchBlock(997058);\n // https://starkscan.co/tx/0x055588e82f864f830c4d1d1117e6e8d61a917ef18cf79961af001dc321d96cb3\n const txWithdraw = block_997058.transactions.find(\n (tx) =>\n tx.hash ===\n '0x55588e82f864f830c4d1d1117e6e8d61a917ef18cf79961af001dc321d96cb3',\n );\n expect(\n filterTransactionsProcessor(txWithdraw!, {\n to: '0x04c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n function: 'withdraw',\n type: 'INVOKE',\n }),\n ).toBeTruthy();\n\n expect(\n filterTransactionsProcessor(txWithdraw!, {\n to: '0x04c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n function:\n '0x015511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77', // with extra 0 padding\n type: 'INVOKE',\n }),\n ).toBeTruthy();\n });\n\n it('decodeCalls only on filtered tx', async () => {\n // https://starkscan.co/tx/0x00b3173b7a65b32fc8669da8f4676a7ef10c6f58ddd3159db7c0cd3de1025443\n const block = await fetchBlock(986480);\n const tx = block.transactions.find(\n (tx) =>\n tx.hash ===\n '0xb3173b7a65b32fc8669da8f4676a7ef10c6f58ddd3159db7c0cd3de1025443',\n );\n // Filter should be failed, and it should not decode calls\n expect(\n filterTransactionsProcessor(\n tx!,\n {\n type: 'INVOKE',\n function: 'mockFn',\n },\n '0x0xxxxx',\n ),\n ).toBeFalsy();\n\n expect(tx!.decodedCalls).toBeUndefined();\n });\n\n it('filter L1 / Invoke v0 transaction', async () => {\n // https://starkscan.co/tx/0x043ce8e6e2ad703a81701f85ce26a8fb32ad54cc2fac7685ed0b1367a4813ade\n const block = await fetchBlock(981920);\n const tx = block.transactions.find((tx) =>\n hexEq(\n tx.hash,\n '0x043ce8e6e2ad703a81701f85ce26a8fb32ad54cc2fac7685ed0b1367a4813ade',\n ),\n );\n\n // Filter by address\n expect(\n filterTransactionsProcessor(\n tx!,\n {\n type: 'L1_HANDLER',\n },\n '0x073314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82',\n ),\n ).toBeTruthy();\n\n // Filter by Selector\n expect(\n filterTransactionsProcessor(\n tx!,\n {\n function:\n '0x01b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19',\n },\n '0x073314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82',\n ),\n ).toBeTruthy();\n });\n });\n\n describe('Filter logs', () => {\n it('filter events with plain text also hex', async () => {\n // https://starkscan.co/tx/0x04b546ff4375c16c30c03bd92d2d9082041e5e9397f5bda4f832661d6c029655#events\n const block = await fetchBlock(986480);\n\n const testLog = block.logs[2]!;\n expect(testLog.transaction.hash).toEqual(\n '0x4b546ff4375c16c30c03bd92d2d9082041e5e9397f5bda4f832661d6c029655',\n );\n // Filter with \"address\"\n expect(\n filterLogsProcessor(\n block.logs[2]!,\n {},\n '0x06a9e4c6f0799160ea8ddc43ff982a5f83d7f633e9732ce42701de1288ff705f',\n ),\n ).toBeTruthy();\n\n expect(\n filterLogsProcessor(block.logs[2]!, {\n topics: ['Transfer'],\n }),\n ).toBeFalsy();\n\n // Event name can be in plain text or hex\n expect(\n filterLogsProcessor(block.logs[2]!, {\n topics: [\n '0x1a2f334228cee715f1f0f54053bb6b5eac54fa336e0bc1aacf7516decb0471d',\n ],\n }),\n ).toBeTruthy();\n\n expect(\n filterLogsProcessor(block.logs[2]!, {\n topics: ['StoreSetRecord'],\n }),\n ).toBeTruthy();\n });\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
const decodeCalldata_1 = require("./decodeCalldata");
|
|
6
|
-
describe('decode', () => {
|
|
7
|
-
// From https://starkscan.co/tx/0x06b8627ba886d457d32cc5a2ef0cc99741fc67b1142ce3f180a29b817b6f5f33
|
|
8
|
-
test('should decode legacy calldata correctly', () => {
|
|
9
|
-
const calldata = [
|
|
10
|
-
'0x3',
|
|
11
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
12
|
-
'0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c',
|
|
13
|
-
'0x0',
|
|
14
|
-
'0x3',
|
|
15
|
-
'0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
16
|
-
'0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01',
|
|
17
|
-
'0x3',
|
|
18
|
-
'0x2',
|
|
19
|
-
'0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
20
|
-
'0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda',
|
|
21
|
-
'0x5',
|
|
22
|
-
'0x1',
|
|
23
|
-
'0x6',
|
|
24
|
-
'0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
25
|
-
'0x738a4f05910',
|
|
26
|
-
'0x0',
|
|
27
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
28
|
-
'0x738a4f05910',
|
|
29
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
30
|
-
];
|
|
31
|
-
const decoded = (0, decodeCalldata_1.decodeInvokeCalldata)(calldata);
|
|
32
|
-
expect(decoded).toEqual([
|
|
33
|
-
{
|
|
34
|
-
calldata: [
|
|
35
|
-
'0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
36
|
-
'0x738a4f05910',
|
|
37
|
-
'0x0',
|
|
38
|
-
],
|
|
39
|
-
selector: '0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c',
|
|
40
|
-
to: '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
calldata: [
|
|
44
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
45
|
-
'0x738a4f05910',
|
|
46
|
-
],
|
|
47
|
-
selector: '0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01',
|
|
48
|
-
to: '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
calldata: [
|
|
52
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
53
|
-
],
|
|
54
|
-
selector: '0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda',
|
|
55
|
-
to: '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
56
|
-
},
|
|
57
|
-
]);
|
|
58
|
-
});
|
|
59
|
-
// From https://starkscan.co/tx/0x06a031ca9916acc3a3723f2f15c2a0c32e756c887b33271d914b1309f57be0f0
|
|
60
|
-
test('should decode new calldata correctly', () => {
|
|
61
|
-
const calldata = [
|
|
62
|
-
'0x3',
|
|
63
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
64
|
-
'0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c',
|
|
65
|
-
'0x3',
|
|
66
|
-
'0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
67
|
-
'0x1dccd9ffaff50',
|
|
68
|
-
'0x0',
|
|
69
|
-
'0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
70
|
-
'0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01',
|
|
71
|
-
'0x2',
|
|
72
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
73
|
-
'0x1dccd9ffaff50',
|
|
74
|
-
'0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
75
|
-
'0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda',
|
|
76
|
-
'0x1',
|
|
77
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
78
|
-
];
|
|
79
|
-
const decoded = (0, decodeCalldata_1.decodeInvokeCalldata)(calldata);
|
|
80
|
-
expect(decoded).toEqual([
|
|
81
|
-
{
|
|
82
|
-
calldata: [
|
|
83
|
-
'0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
84
|
-
'0x1dccd9ffaff50',
|
|
85
|
-
'0x0',
|
|
86
|
-
],
|
|
87
|
-
selector: '0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c',
|
|
88
|
-
to: '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
calldata: [
|
|
92
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
93
|
-
'0x1dccd9ffaff50',
|
|
94
|
-
],
|
|
95
|
-
selector: '0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01',
|
|
96
|
-
to: '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
calldata: [
|
|
100
|
-
'0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
101
|
-
],
|
|
102
|
-
selector: '0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda',
|
|
103
|
-
to: '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',
|
|
104
|
-
},
|
|
105
|
-
]);
|
|
106
|
-
});
|
|
107
|
-
test('should throw DecodeCalldataError for invalid calldata', () => {
|
|
108
|
-
const invalidCalldata = ['0x1', 'invalid_field_element'];
|
|
109
|
-
expect(() => (0, decodeCalldata_1.decodeInvokeCalldata)(invalidCalldata)).toThrow(decodeCalldata_1.DecodeCalldataError);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
//# sourceMappingURL=decodeCalldata.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decodeCalldata.spec.js","sourceRoot":"","sources":["../../src/starknet/decodeCalldata.spec.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;AAEnC,qDAA6E;AAE7E,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,kGAAkG;IAClG,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACnD,MAAM,QAAQ,GAAG;YACf,KAAK;YACL,mEAAmE;YACnE,mEAAmE;YACnE,KAAK;YACL,KAAK;YACL,mEAAmE;YACnE,kEAAkE;YAClE,KAAK;YACL,KAAK;YACL,mEAAmE;YACnE,mEAAmE;YACnE,KAAK;YACL,KAAK;YACL,KAAK;YACL,mEAAmE;YACnE,eAAe;YACf,KAAK;YACL,mEAAmE;YACnE,eAAe;YACf,mEAAmE;SACpE,CAAC;QAEF,MAAM,OAAO,GAAG,IAAA,qCAAoB,EAAC,QAAQ,CAAC,CAAC;QAE/C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YACtB;gBACE,QAAQ,EAAE;oBACR,mEAAmE;oBACnE,eAAe;oBACf,KAAK;iBACN;gBACD,QAAQ,EACN,mEAAmE;gBACrE,EAAE,EAAE,mEAAmE;aACxE;YACD;gBACE,QAAQ,EAAE;oBACR,mEAAmE;oBACnE,eAAe;iBAChB;gBACD,QAAQ,EACN,kEAAkE;gBACpE,EAAE,EAAE,mEAAmE;aACxE;YACD;gBACE,QAAQ,EAAE;oBACR,mEAAmE;iBACpE;gBACD,QAAQ,EACN,mEAAmE;gBACrE,EAAE,EAAE,mEAAmE;aACxE;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,kGAAkG;IAClG,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAChD,MAAM,QAAQ,GAAG;YACf,KAAK;YACL,mEAAmE;YACnE,mEAAmE;YACnE,KAAK;YACL,mEAAmE;YACnE,iBAAiB;YACjB,KAAK;YACL,mEAAmE;YACnE,kEAAkE;YAClE,KAAK;YACL,mEAAmE;YACnE,iBAAiB;YACjB,mEAAmE;YACnE,mEAAmE;YACnE,KAAK;YACL,mEAAmE;SACpE,CAAC;QAEF,MAAM,OAAO,GAAG,IAAA,qCAAoB,EAAC,QAAQ,CAAC,CAAC;QAE/C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YACtB;gBACE,QAAQ,EAAE;oBACR,mEAAmE;oBACnE,iBAAiB;oBACjB,KAAK;iBACN;gBACD,QAAQ,EACN,mEAAmE;gBACrE,EAAE,EAAE,mEAAmE;aACxE;YACD;gBACE,QAAQ,EAAE;oBACR,mEAAmE;oBACnE,iBAAiB;iBAClB;gBACD,QAAQ,EACN,kEAAkE;gBACpE,EAAE,EAAE,mEAAmE;aACxE;YACD;gBACE,QAAQ,EAAE;oBACR,mEAAmE;iBACpE;gBACD,QAAQ,EACN,mEAAmE;gBACrE,EAAE,EAAE,mEAAmE;aACxE;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;QACjE,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;QACzD,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,qCAAoB,EAAC,eAAe,CAAC,CAAC,CAAC,OAAO,CACzD,oCAAmB,CACpB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { decodeInvokeCalldata, DecodeCalldataError } from './decodeCalldata';\n\ndescribe('decode', () => {\n // From https://starkscan.co/tx/0x06b8627ba886d457d32cc5a2ef0cc99741fc67b1142ce3f180a29b817b6f5f33\n test('should decode legacy calldata correctly', () => {\n const calldata = [\n '0x3',\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n '0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c',\n '0x0',\n '0x3',\n '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n '0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01',\n '0x3',\n '0x2',\n '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n '0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda',\n '0x5',\n '0x1',\n '0x6',\n '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n '0x738a4f05910',\n '0x0',\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n '0x738a4f05910',\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n ];\n\n const decoded = decodeInvokeCalldata(calldata);\n\n expect(decoded).toEqual([\n {\n calldata: [\n '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n '0x738a4f05910',\n '0x0',\n ],\n selector:\n '0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c',\n to: '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n },\n {\n calldata: [\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n '0x738a4f05910',\n ],\n selector:\n '0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01',\n to: '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n },\n {\n calldata: [\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n ],\n selector:\n '0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda',\n to: '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n },\n ]);\n });\n\n // From https://starkscan.co/tx/0x06a031ca9916acc3a3723f2f15c2a0c32e756c887b33271d914b1309f57be0f0\n test('should decode new calldata correctly', () => {\n const calldata = [\n '0x3',\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n '0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c',\n '0x3',\n '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n '0x1dccd9ffaff50',\n '0x0',\n '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n '0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01',\n '0x2',\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n '0x1dccd9ffaff50',\n '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n '0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda',\n '0x1',\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n ];\n\n const decoded = decodeInvokeCalldata(calldata);\n\n expect(decoded).toEqual([\n {\n calldata: [\n '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n '0x1dccd9ffaff50',\n '0x0',\n ],\n selector:\n '0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c',\n to: '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n },\n {\n calldata: [\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n '0x1dccd9ffaff50',\n ],\n selector:\n '0xc73f681176fc7b3f9693986fd7b14581e8d540519e27400e88b8713932be01',\n to: '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n },\n {\n calldata: [\n '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',\n ],\n selector:\n '0x271680756697a04d1447ad4c21d53bdf15966bdc5b78bd52d4fc2153aa76bda',\n to: '0x4c0a5193d58f74fbace4b74dcf65481e734ed1714121bdc571da345540efa05',\n },\n ]);\n });\n\n test('should throw DecodeCalldataError for invalid calldata', () => {\n const invalidCalldata = ['0x1', 'invalid_field_element'];\n expect(() => decodeInvokeCalldata(invalidCalldata)).toThrow(\n DecodeCalldataError,\n );\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0
|
|
4
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
-
};
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
const pino_1 = __importDefault(require("pino"));
|
|
9
|
-
const finalized_block_starknet_1 = require("./finalized.block.starknet");
|
|
10
|
-
const createMockBlock = (block_number, status) => ({
|
|
11
|
-
block_number,
|
|
12
|
-
status,
|
|
13
|
-
block_hash: `0xabc${block_number}`,
|
|
14
|
-
parent_hash: `0xparent${block_number - 1}`,
|
|
15
|
-
new_root: `0xnewroot${block_number}`,
|
|
16
|
-
timestamp: 1700000000 + block_number,
|
|
17
|
-
sequencer_address: `0xsequencer${block_number}`,
|
|
18
|
-
transactions: [],
|
|
19
|
-
starknet_version: '',
|
|
20
|
-
l1_da_mode: 'BLOB',
|
|
21
|
-
l1_gas_price: { price_in_wei: '0', price_in_fri: '0' },
|
|
22
|
-
l1_data_gas_price: { price_in_wei: '0', price_in_fri: '0' },
|
|
23
|
-
});
|
|
24
|
-
// **Mock blocks**
|
|
25
|
-
const mockBlocks = {
|
|
26
|
-
latest: createMockBlock(10, 'ACCEPTED_ON_L2'),
|
|
27
|
-
10: createMockBlock(10, 'ACCEPTED_ON_L2'),
|
|
28
|
-
9: createMockBlock(9, 'ACCEPTED_ON_L2'),
|
|
29
|
-
8: createMockBlock(8, 'ACCEPTED_ON_L2'),
|
|
30
|
-
7: createMockBlock(7, 'ACCEPTED_ON_L1'), // latest ACCEPTED_ON_L1
|
|
31
|
-
6: createMockBlock(6, 'ACCEPTED_ON_L1'),
|
|
32
|
-
5: createMockBlock(5, 'ACCEPTED_ON_L1'),
|
|
33
|
-
4: createMockBlock(4, 'ACCEPTED_ON_L1'),
|
|
34
|
-
3: createMockBlock(3, 'ACCEPTED_ON_L1'),
|
|
35
|
-
2: createMockBlock(2, 'ACCEPTED_ON_L1'),
|
|
36
|
-
1: createMockBlock(1, 'ACCEPTED_ON_L1'),
|
|
37
|
-
0: createMockBlock(0, 'ACCEPTED_ON_L1'),
|
|
38
|
-
};
|
|
39
|
-
const mockBlockService = {
|
|
40
|
-
async getBlock(heightOrHash) {
|
|
41
|
-
if (mockBlocks[heightOrHash] !== undefined) {
|
|
42
|
-
return Promise.resolve(mockBlocks[heightOrHash]);
|
|
43
|
-
}
|
|
44
|
-
return Promise.reject(new Error(`Block ${heightOrHash} not found`));
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
// **initialize logger**
|
|
48
|
-
const mockLogger = (0, pino_1.default)({ level: 'debug' });
|
|
49
|
-
describe('FinalizedBlockService', () => {
|
|
50
|
-
let service;
|
|
51
|
-
beforeEach(() => {
|
|
52
|
-
service = new finalized_block_starknet_1.FinalizedBlockService(mockBlockService.getBlock, mockLogger);
|
|
53
|
-
});
|
|
54
|
-
// **Test 1: `findFirstAcceptedOnL1`**
|
|
55
|
-
it('should find the first ACCEPTED_ON_L1 block', async () => {
|
|
56
|
-
const result = await service.findFirstAcceptedOnL1();
|
|
57
|
-
expect(result).toBeDefined();
|
|
58
|
-
expect(result?.block_number).toBe(0);
|
|
59
|
-
expect(result?.status).toBe('ACCEPTED_ON_L1');
|
|
60
|
-
});
|
|
61
|
-
// **Test 2: `binarySearchAcceptedOnL1`**
|
|
62
|
-
it('should find the latest ACCEPTED_ON_L1 block via binary search', async () => {
|
|
63
|
-
const result = await service.binarySearchAcceptedOnL1(1, 10);
|
|
64
|
-
expect(result).toBeDefined();
|
|
65
|
-
expect(result?.block_number).toBe(7);
|
|
66
|
-
expect(result?.status).toBe('ACCEPTED_ON_L1');
|
|
67
|
-
});
|
|
68
|
-
// **Test 3: `getFinalizedBlock` - First call (initialize cache)**
|
|
69
|
-
it('should initialize latestAcceptedBlock and return the correct block', async () => {
|
|
70
|
-
const result = await service.getFinalizedBlock();
|
|
71
|
-
expect(result).toBeDefined();
|
|
72
|
-
expect(result.block_number).toBe(7);
|
|
73
|
-
expect(result.status).toBe('ACCEPTED_ON_L1');
|
|
74
|
-
});
|
|
75
|
-
// **Test 4: `getFinalizedBlock` - Return cached block and verify `getBlock` is not called**
|
|
76
|
-
it('should return cached block if next block remains ACCEPTED_ON_L2 and not call `getBlock`', async () => {
|
|
77
|
-
const getBlockSpy = jest.spyOn(mockBlockService, 'getBlock');
|
|
78
|
-
let result = await service.getFinalizedBlock(); // First call - initializes cache
|
|
79
|
-
expect(result.block_number).toBe(7); // Should return cached block 3
|
|
80
|
-
jest.clearAllMocks(); // Reset call count for the second invocation
|
|
81
|
-
result = await service.getFinalizedBlock(); // Second call - should use cache
|
|
82
|
-
expect(result).toBeDefined();
|
|
83
|
-
expect(result.block_number).toBe(7); // Should return cached block 3
|
|
84
|
-
expect(getBlockSpy).not.toHaveBeenCalled(); // Ensure `getBlock` was NOT called again
|
|
85
|
-
});
|
|
86
|
-
// **Test 5: `getFinalizedBlock` - Update when next block becomes L1**
|
|
87
|
-
it('should update latestAcceptedBlock if next block changes to ACCEPTED_ON_L1', async () => {
|
|
88
|
-
await service.getFinalizedBlock(); // Initialize cache
|
|
89
|
-
mockBlocks[8].status = 'ACCEPTED_ON_L1'; // Change block 8 to L1
|
|
90
|
-
const result = await service.getFinalizedBlock();
|
|
91
|
-
expect(result).toBeDefined();
|
|
92
|
-
expect(result.block_number).toBe(8); // Now should update to block 8
|
|
93
|
-
});
|
|
94
|
-
// No blocks are accepted on L1 with devnets
|
|
95
|
-
it('works with devnet', async () => {
|
|
96
|
-
const blocks = {
|
|
97
|
-
latest: createMockBlock(4, 'ACCEPTED_ON_L2'),
|
|
98
|
-
4: createMockBlock(4, 'ACCEPTED_ON_L2'),
|
|
99
|
-
3: createMockBlock(3, 'ACCEPTED_ON_L2'),
|
|
100
|
-
2: createMockBlock(2, 'ACCEPTED_ON_L2'),
|
|
101
|
-
1: createMockBlock(1, 'ACCEPTED_ON_L2'),
|
|
102
|
-
0: createMockBlock(0, 'ACCEPTED_ON_L2'),
|
|
103
|
-
};
|
|
104
|
-
service = new finalized_block_starknet_1.FinalizedBlockService((hashOrNumber) => {
|
|
105
|
-
return blocks[hashOrNumber];
|
|
106
|
-
}, mockLogger);
|
|
107
|
-
const result = await service.getFinalizedBlock();
|
|
108
|
-
expect(result).toBeDefined();
|
|
109
|
-
expect(result.block_number).toBe(0);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
//# sourceMappingURL=finalized.block.starknet.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"finalized.block.starknet.spec.js","sourceRoot":"","sources":["../../src/starknet/finalized.block.starknet.spec.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport P from 'pino';\nimport { SPEC } from 'starknet-types-07';\nimport { FinalizedBlockService } from './finalized.block.starknet';\n\nconst createMockBlock = (\n block_number: number,\n status: 'ACCEPTED_ON_L1' | 'ACCEPTED_ON_L2',\n): SPEC.BLOCK_WITH_RECEIPTS => ({\n block_number,\n status,\n block_hash: `0xabc${block_number}`,\n parent_hash: `0xparent${block_number - 1}`,\n new_root: `0xnewroot${block_number}`,\n timestamp: 1700000000 + block_number,\n sequencer_address: `0xsequencer${block_number}`,\n transactions: [],\n starknet_version: '',\n l1_da_mode: 'BLOB',\n l1_gas_price: { price_in_wei: '0', price_in_fri: '0' },\n l1_data_gas_price: { price_in_wei: '0', price_in_fri: '0' },\n});\n\n// **Mock blocks**\nconst mockBlocks: Record<number | string, SPEC.BLOCK_WITH_RECEIPTS> = {\n latest: createMockBlock(10, 'ACCEPTED_ON_L2'),\n 10: createMockBlock(10, 'ACCEPTED_ON_L2'),\n 9: createMockBlock(9, 'ACCEPTED_ON_L2'),\n 8: createMockBlock(8, 'ACCEPTED_ON_L2'),\n 7: createMockBlock(7, 'ACCEPTED_ON_L1'), // latest ACCEPTED_ON_L1\n 6: createMockBlock(6, 'ACCEPTED_ON_L1'),\n 5: createMockBlock(5, 'ACCEPTED_ON_L1'),\n 4: createMockBlock(4, 'ACCEPTED_ON_L1'),\n 3: createMockBlock(3, 'ACCEPTED_ON_L1'),\n 2: createMockBlock(2, 'ACCEPTED_ON_L1'),\n 1: createMockBlock(1, 'ACCEPTED_ON_L1'),\n 0: createMockBlock(0, 'ACCEPTED_ON_L1'),\n};\n\nconst mockBlockService = {\n async getBlock(\n heightOrHash: number | string,\n ): Promise<SPEC.BLOCK_WITH_RECEIPTS> {\n if (mockBlocks[heightOrHash] !== undefined) {\n return Promise.resolve(mockBlocks[heightOrHash]);\n }\n return Promise.reject(new Error(`Block ${heightOrHash} not found`));\n },\n};\n\n// **initialize logger**\nconst mockLogger = P({ level: 'debug' });\n\ndescribe('FinalizedBlockService', () => {\n let service: FinalizedBlockService;\n\n beforeEach(() => {\n service = new FinalizedBlockService(mockBlockService.getBlock, mockLogger);\n });\n\n // **Test 1: `findFirstAcceptedOnL1`**\n it('should find the first ACCEPTED_ON_L1 block', async () => {\n const result = await (service as any).findFirstAcceptedOnL1();\n expect(result).toBeDefined();\n expect(result?.block_number).toBe(0);\n expect(result?.status).toBe('ACCEPTED_ON_L1');\n });\n\n // **Test 2: `binarySearchAcceptedOnL1`**\n it('should find the latest ACCEPTED_ON_L1 block via binary search', async () => {\n const result = await (service as any).binarySearchAcceptedOnL1(1, 10);\n expect(result).toBeDefined();\n expect(result?.block_number).toBe(7);\n expect(result?.status).toBe('ACCEPTED_ON_L1');\n });\n\n // **Test 3: `getFinalizedBlock` - First call (initialize cache)**\n it('should initialize latestAcceptedBlock and return the correct block', async () => {\n const result = await service.getFinalizedBlock();\n expect(result).toBeDefined();\n expect(result.block_number).toBe(7);\n expect(result.status).toBe('ACCEPTED_ON_L1');\n });\n\n // **Test 4: `getFinalizedBlock` - Return cached block and verify `getBlock` is not called**\n it('should return cached block if next block remains ACCEPTED_ON_L2 and not call `getBlock`', async () => {\n const getBlockSpy = jest.spyOn(mockBlockService, 'getBlock');\n\n let result = await service.getFinalizedBlock(); // First call - initializes cache\n expect(result.block_number).toBe(7); // Should return cached block 3\n\n jest.clearAllMocks(); // Reset call count for the second invocation\n\n result = await service.getFinalizedBlock(); // Second call - should use cache\n\n expect(result).toBeDefined();\n expect(result.block_number).toBe(7); // Should return cached block 3\n expect(getBlockSpy).not.toHaveBeenCalled(); // Ensure `getBlock` was NOT called again\n });\n\n // **Test 5: `getFinalizedBlock` - Update when next block becomes L1**\n it('should update latestAcceptedBlock if next block changes to ACCEPTED_ON_L1', async () => {\n await service.getFinalizedBlock(); // Initialize cache\n mockBlocks[8].status = 'ACCEPTED_ON_L1'; // Change block 8 to L1\n const result = await service.getFinalizedBlock();\n expect(result).toBeDefined();\n expect(result.block_number).toBe(8); // Now should update to block 8\n });\n\n // No blocks are accepted on L1 with devnets\n it('works with devnet', async () => {\n const blocks = {\n latest: createMockBlock(4, 'ACCEPTED_ON_L2'),\n 4: createMockBlock(4, 'ACCEPTED_ON_L2'),\n 3: createMockBlock(3, 'ACCEPTED_ON_L2'),\n 2: createMockBlock(2, 'ACCEPTED_ON_L2'),\n 1: createMockBlock(1, 'ACCEPTED_ON_L2'),\n 0: createMockBlock(0, 'ACCEPTED_ON_L2'),\n };\n\n service = new FinalizedBlockService(\n (hashOrNumber: number | string): any => {\n return blocks[hashOrNumber];\n },\n mockLogger,\n );\n\n const result = await service.getFinalizedBlock();\n expect(result).toBeDefined();\n expect(result.block_number).toBe(0);\n });\n});\n"]}
|