@subql/node-solana 6.0.5 → 6.0.6
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 +3 -2
- package/dist/blockchain.service.js.map +1 -1
- package/dist/indexer/fetch.module.js +2 -1
- package/dist/indexer/fetch.module.js.map +1 -1
- package/dist/indexer/indexer.manager.d.ts +2 -1
- package/dist/indexer/indexer.manager.js +2 -1
- package/dist/indexer/indexer.manager.js.map +1 -1
- package/dist/indexer/unfinalizedBlocks.service.d.ts +38 -0
- package/dist/indexer/unfinalizedBlocks.service.js +286 -0
- package/dist/indexer/unfinalizedBlocks.service.js.map +1 -0
- package/dist/indexer/unfinalizedBlocks.service.spec.d.ts +1 -0
- package/dist/indexer/unfinalizedBlocks.service.spec.js +90 -0
- package/dist/indexer/unfinalizedBlocks.service.spec.js.map +1 -0
- package/dist/solana/api.solana.d.ts +1 -1
- package/dist/solana/api.solana.js +6 -10
- package/dist/solana/api.solana.js.map +1 -1
- package/dist/subcommands/reindex.module.js +2 -1
- package/dist/subcommands/reindex.module.js.map +1 -1
- package/dist/subcommands/testing.module.js +2 -1
- package/dist/subcommands/testing.module.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,90 @@
|
|
|
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 node_core_1 = require("@subql/node-core");
|
|
6
|
+
const unfinalizedBlocks_service_1 = require("./unfinalizedBlocks.service");
|
|
7
|
+
const getMockStoreModelProvider = () => {
|
|
8
|
+
const meta = {};
|
|
9
|
+
return {
|
|
10
|
+
metadata: {
|
|
11
|
+
set: (key, value) => {
|
|
12
|
+
meta[key] = value;
|
|
13
|
+
return Promise.resolve();
|
|
14
|
+
},
|
|
15
|
+
find: (key) => Promise.resolve(meta[key]),
|
|
16
|
+
},
|
|
17
|
+
poi: null,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
const headerFromHeight = (height, finalized = false, parentFinalized = false) => ({
|
|
21
|
+
blockHeight: height,
|
|
22
|
+
blockHash: `0x${height}${finalized ? 'f' : ''}`,
|
|
23
|
+
parentHash: `0x${height - 1}${parentFinalized ? 'f' : ''}`,
|
|
24
|
+
timestamp: new Date('2025-08-27T23:07:53.486Z'),
|
|
25
|
+
});
|
|
26
|
+
const getMockBlockchainService = (finalizedHeight = 100, skippedSlots = []) => {
|
|
27
|
+
let _finalizedHeight = finalizedHeight;
|
|
28
|
+
let _skippedSlots = new Set(skippedSlots);
|
|
29
|
+
return {
|
|
30
|
+
getFinalizedHeader: () => Promise.resolve(headerFromHeight(_finalizedHeight, true)),
|
|
31
|
+
getHeaderForHeight: (height) => {
|
|
32
|
+
// Same behaviour as in SolanaApi
|
|
33
|
+
if (_skippedSlots.has(height)) {
|
|
34
|
+
// No block for that slot
|
|
35
|
+
throw new node_core_1.BlockUnavailableError();
|
|
36
|
+
}
|
|
37
|
+
return Promise.resolve(headerFromHeight(height, height <= _finalizedHeight, height < _finalizedHeight));
|
|
38
|
+
},
|
|
39
|
+
setFinalizedHeight: (newHeight) => (_finalizedHeight = newHeight),
|
|
40
|
+
setSkippedSlots: (slots) => (_skippedSlots = new Set(slots)),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
describe('Unfinalized blocks', () => {
|
|
44
|
+
it('correctly detects forks', async () => {
|
|
45
|
+
const store = getMockStoreModelProvider();
|
|
46
|
+
const blockchain = getMockBlockchainService(100);
|
|
47
|
+
const unfinalizedBlocks = new unfinalizedBlocks_service_1.UnfinalizedBlocksService(new node_core_1.NodeConfig({}), store, blockchain);
|
|
48
|
+
const reindex = jest.fn();
|
|
49
|
+
await unfinalizedBlocks.init(reindex);
|
|
50
|
+
let height = 101;
|
|
51
|
+
const forkHeight = 108;
|
|
52
|
+
while (height <= 110) {
|
|
53
|
+
if (height === forkHeight) {
|
|
54
|
+
blockchain.setFinalizedHeight(forkHeight);
|
|
55
|
+
unfinalizedBlocks.registerFinalizedBlock(headerFromHeight(forkHeight, true, true));
|
|
56
|
+
}
|
|
57
|
+
const rewindTo = await unfinalizedBlocks.processUnfinalizedBlockHeader(await blockchain.getHeaderForHeight(height));
|
|
58
|
+
if (rewindTo) {
|
|
59
|
+
reindex(rewindTo);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
height++;
|
|
63
|
+
}
|
|
64
|
+
expect(reindex).toHaveBeenCalledWith(headerFromHeight(100, true, true));
|
|
65
|
+
});
|
|
66
|
+
it('handles block forks when there are missed slots', async () => {
|
|
67
|
+
const store = getMockStoreModelProvider();
|
|
68
|
+
const blockchain = getMockBlockchainService(100);
|
|
69
|
+
const unfinalizedBlocks = new unfinalizedBlocks_service_1.UnfinalizedBlocksService(new node_core_1.NodeConfig({}), store, blockchain);
|
|
70
|
+
const reindex = jest.fn();
|
|
71
|
+
await unfinalizedBlocks.init(reindex);
|
|
72
|
+
let height = 101;
|
|
73
|
+
const forkHeight = 108;
|
|
74
|
+
while (height <= 110) {
|
|
75
|
+
if (height === forkHeight) {
|
|
76
|
+
blockchain.setSkippedSlots([103]);
|
|
77
|
+
blockchain.setFinalizedHeight(forkHeight);
|
|
78
|
+
unfinalizedBlocks.registerFinalizedBlock(headerFromHeight(forkHeight, true, true));
|
|
79
|
+
}
|
|
80
|
+
const rewindTo = await unfinalizedBlocks.processUnfinalizedBlockHeader(await blockchain.getHeaderForHeight(height));
|
|
81
|
+
if (rewindTo) {
|
|
82
|
+
reindex(rewindTo);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
height++;
|
|
86
|
+
}
|
|
87
|
+
expect(reindex).toHaveBeenCalledWith(headerFromHeight(100, true, true));
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=unfinalizedBlocks.service.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unfinalizedBlocks.service.spec.js","sourceRoot":"","sources":["../../src/indexer/unfinalizedBlocks.service.spec.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;AAEnC,gDAM0B;AAC1B,2EAAuE;AAEvE,MAAM,yBAAyB,GAAG,GAAwB,EAAE;IAC1D,MAAM,IAAI,GAAwB,EAAE,CAAC;IAErC,OAAO;QACL,QAAQ,EAAE;YACR,GAAG,EAAE,CAAC,GAAW,EAAE,KAAU,EAAE,EAAE;gBAC/B,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBAClB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,CAAC;YACD,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAC1C;QACD,GAAG,EAAE,IAAI;KACH,CAAC;AACX,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CACvB,MAAc,EACd,SAAS,GAAG,KAAK,EACjB,eAAe,GAAG,KAAK,EACf,EAAE,CAAC,CAAC;IACZ,WAAW,EAAE,MAAM;IACnB,SAAS,EAAE,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;IAC/C,UAAU,EAAE,KAAK,MAAM,GAAG,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;IAC1D,SAAS,EAAE,IAAI,IAAI,CAAC,0BAA0B,CAAC;CAChD,CAAC,CAAC;AAEH,MAAM,wBAAwB,GAAG,CAC/B,eAAe,GAAG,GAAG,EACrB,eAAyB,EAAE,EAI3B,EAAE;IACF,IAAI,gBAAgB,GAAG,eAAe,CAAC;IACvC,IAAI,aAAa,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAE1C,OAAO;QACL,kBAAkB,EAAE,GAAG,EAAE,CACvB,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;QAC3D,kBAAkB,EAAE,CAAC,MAAc,EAAE,EAAE;YACrC,iCAAiC;YACjC,IAAI,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,yBAAyB;gBACzB,MAAM,IAAI,iCAAqB,EAAE,CAAC;YACpC,CAAC;YACD,OAAO,OAAO,CAAC,OAAO,CACpB,gBAAgB,CACd,MAAM,EACN,MAAM,IAAI,gBAAgB,EAC1B,MAAM,GAAG,gBAAgB,CAC1B,CACF,CAAC;QACJ,CAAC;QACD,kBAAkB,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,gBAAgB,GAAG,SAAS,CAAC;QACzE,eAAe,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,CAAC,aAAa,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;KAChE,CAAC;AACX,CAAC,CAAC;AAEF,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,KAAK,GAAG,yBAAyB,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,iBAAiB,GAAG,IAAI,oDAAwB,CACpD,IAAI,sBAAU,CAAC,EAAS,CAAC,EACzB,KAAK,EACL,UAAU,CACX,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC1B,MAAM,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEtC,IAAI,MAAM,GAAG,GAAG,CAAC;QACjB,MAAM,UAAU,GAAG,GAAG,CAAC;QACvB,OAAO,MAAM,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;gBAC1C,iBAAiB,CAAC,sBAAsB,CACtC,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,CACzC,CAAC;YACJ,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,6BAA6B,CACpE,MAAM,UAAU,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAC5C,CAAC;YACF,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAClB,MAAM;YACR,CAAC;YACD,MAAM,EAAE,CAAC;QACX,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,KAAK,GAAG,yBAAyB,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,iBAAiB,GAAG,IAAI,oDAAwB,CACpD,IAAI,sBAAU,CAAC,EAAS,CAAC,EACzB,KAAK,EACL,UAAU,CACX,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC1B,MAAM,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEtC,IAAI,MAAM,GAAG,GAAG,CAAC;QACjB,MAAM,UAAU,GAAG,GAAG,CAAC;QACvB,OAAO,MAAM,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,UAAU,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClC,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;gBAC1C,iBAAiB,CAAC,sBAAsB,CACtC,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,CACzC,CAAC;YACJ,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,6BAA6B,CACpE,MAAM,UAAU,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAC5C,CAAC;YACF,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAClB,MAAM;YACR,CAAC;YACD,MAAM,EAAE,CAAC;QACX,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1E,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 {\n BlockUnavailableError,\n Header,\n IBlockchainService,\n IStoreModelProvider,\n NodeConfig,\n} from '@subql/node-core';\nimport { UnfinalizedBlocksService } from './unfinalizedBlocks.service';\n\nconst getMockStoreModelProvider = (): IStoreModelProvider => {\n const meta: Record<string, any> = {};\n\n return {\n metadata: {\n set: (key: string, value: any) => {\n meta[key] = value;\n return Promise.resolve();\n },\n find: (key) => Promise.resolve(meta[key]),\n },\n poi: null,\n } as any;\n};\n\nconst headerFromHeight = (\n height: number,\n finalized = false,\n parentFinalized = false,\n): Header => ({\n blockHeight: height,\n blockHash: `0x${height}${finalized ? 'f' : ''}`,\n parentHash: `0x${height - 1}${parentFinalized ? 'f' : ''}`,\n timestamp: new Date('2025-08-27T23:07:53.486Z'),\n});\n\nconst getMockBlockchainService = (\n finalizedHeight = 100,\n skippedSlots: number[] = [],\n): IBlockchainService & {\n setFinalizedHeight: (newHeight: number) => void;\n setSkippedSlots: (slots: number[]) => void;\n} => {\n let _finalizedHeight = finalizedHeight;\n let _skippedSlots = new Set(skippedSlots);\n\n return {\n getFinalizedHeader: () =>\n Promise.resolve(headerFromHeight(_finalizedHeight, true)),\n getHeaderForHeight: (height: number) => {\n // Same behaviour as in SolanaApi\n if (_skippedSlots.has(height)) {\n // No block for that slot\n throw new BlockUnavailableError();\n }\n return Promise.resolve(\n headerFromHeight(\n height,\n height <= _finalizedHeight,\n height < _finalizedHeight,\n ),\n );\n },\n setFinalizedHeight: (newHeight: number) => (_finalizedHeight = newHeight),\n setSkippedSlots: (slots: number[]) => (_skippedSlots = new Set(slots)),\n } as any;\n};\n\ndescribe('Unfinalized blocks', () => {\n it('correctly detects forks', async () => {\n const store = getMockStoreModelProvider();\n const blockchain = getMockBlockchainService(100);\n const unfinalizedBlocks = new UnfinalizedBlocksService(\n new NodeConfig({} as any),\n store,\n blockchain,\n );\n\n const reindex = jest.fn();\n await unfinalizedBlocks.init(reindex);\n\n let height = 101;\n const forkHeight = 108;\n while (height <= 110) {\n if (height === forkHeight) {\n blockchain.setFinalizedHeight(forkHeight);\n unfinalizedBlocks.registerFinalizedBlock(\n headerFromHeight(forkHeight, true, true),\n );\n }\n const rewindTo = await unfinalizedBlocks.processUnfinalizedBlockHeader(\n await blockchain.getHeaderForHeight(height),\n );\n if (rewindTo) {\n reindex(rewindTo);\n break;\n }\n height++;\n }\n\n expect(reindex).toHaveBeenCalledWith(headerFromHeight(100, true, true));\n });\n\n it('handles block forks when there are missed slots', async () => {\n const store = getMockStoreModelProvider();\n const blockchain = getMockBlockchainService(100);\n const unfinalizedBlocks = new UnfinalizedBlocksService(\n new NodeConfig({} as any),\n store,\n blockchain,\n );\n\n const reindex = jest.fn();\n await unfinalizedBlocks.init(reindex);\n\n let height = 101;\n const forkHeight = 108;\n while (height <= 110) {\n if (height === forkHeight) {\n blockchain.setSkippedSlots([103]);\n blockchain.setFinalizedHeight(forkHeight);\n unfinalizedBlocks.registerFinalizedBlock(\n headerFromHeight(forkHeight, true, true),\n );\n }\n const rewindTo = await unfinalizedBlocks.processUnfinalizedBlockHeader(\n await blockchain.getHeaderForHeight(height),\n );\n if (rewindTo) {\n reindex(rewindTo);\n break;\n }\n height++;\n }\n\n expect(reindex).toHaveBeenCalledWith(headerFromHeight(100, true, true));\n });\n});\n"]}
|
|
@@ -23,7 +23,7 @@ export declare class SolanaApi {
|
|
|
23
23
|
getRuntimeChain(): string;
|
|
24
24
|
getGenesisHash(): string;
|
|
25
25
|
getSpecName(): string;
|
|
26
|
-
|
|
26
|
+
getHeaderByHeight(height: number | bigint): Promise<Header>;
|
|
27
27
|
fetchBlock(blockNumber: number): Promise<IBlock<SolanaBlock>>;
|
|
28
28
|
fetchBlocks(bufferBlocks: number[]): Promise<IBlock<SolanaBlock>[]>;
|
|
29
29
|
get api(): Rpc<SolanaRpcApi>;
|
|
@@ -61,7 +61,7 @@ class SolanaApi {
|
|
|
61
61
|
try {
|
|
62
62
|
const height = await this.getFinalizedBlockHeight();
|
|
63
63
|
// This needs retries becasue if the endpoint is load balanced you might get a different node that doesn't yet have this block
|
|
64
|
-
const header = await (0, node_core_1.backoffRetry)(() => this.
|
|
64
|
+
const header = await (0, node_core_1.backoffRetry)(() => this.getHeaderByHeight(height));
|
|
65
65
|
return header;
|
|
66
66
|
}
|
|
67
67
|
catch (e) {
|
|
@@ -108,23 +108,19 @@ class SolanaApi {
|
|
|
108
108
|
getSpecName() {
|
|
109
109
|
return 'solana';
|
|
110
110
|
}
|
|
111
|
-
async
|
|
112
|
-
|
|
113
|
-
// heightOrHash = hexValue(heightOrHash);
|
|
114
|
-
// }
|
|
115
|
-
if (typeof heightOrHash === 'string') {
|
|
116
|
-
throw new Error('Hash not supported'); // TODO find a workaround
|
|
117
|
-
}
|
|
118
|
-
const slot = typeof heightOrHash === 'number' ? BigInt(heightOrHash) : heightOrHash;
|
|
111
|
+
async getHeaderByHeight(height) {
|
|
112
|
+
const slot = typeof height === 'number' ? BigInt(height) : height;
|
|
119
113
|
const block = await this.#client
|
|
120
114
|
.getBlock(slot, {
|
|
121
115
|
maxSupportedTransactionVersion: 0,
|
|
122
116
|
transactionDetails: 'none',
|
|
123
117
|
rewards: false,
|
|
118
|
+
commitment: 'confirmed', // This is used by unfinalized blocks
|
|
124
119
|
})
|
|
125
120
|
.send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });
|
|
126
121
|
if (!block) {
|
|
127
|
-
|
|
122
|
+
// No block for that slot
|
|
123
|
+
throw new node_core_1.BlockUnavailableError();
|
|
128
124
|
}
|
|
129
125
|
return (0, block_solana_1.solanaBlockToHeader)(block);
|
|
130
126
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.solana.js","sourceRoot":"","sources":["../../src/solana/api.solana.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 { assertIsAddress } from '@solana/addresses';\nimport { createSolanaRpc, Rpc } from '@solana/kit';\nimport { SolanaRpcApi } from '@solana/rpc-api';\nimport {\n backoffRetry,\n BlockUnavailableError,\n delay,\n getLogger,\n Header,\n IBlock,\n} from '@subql/node-core';\nimport { SolanaBlock, ISolanaEndpointConfig } from '@subql/types-solana';\nimport {\n formatBlockUtil,\n solanaBlockToHeader,\n transformBlock,\n} from './block.solana';\nimport { SolanaDecoder } from './decoder';\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version: packageVersion } = require('../../package.json');\n\nconst logger = getLogger('api.ethereum');\n\nexport type SolanaSafeApi = undefined;\n\nconst REQUEST_TIMEOUT = 30_000;\n\nexport class SolanaApi {\n #client: Rpc<SolanaRpcApi>;\n\n // This is used within the sandbox when HTTP is used\n #genesisBlockHash: string;\n #requestTimeout: number;\n\n /**\n * @param {string} endpoint - The endpoint of the RPC provider\n * @param {number} blockConfirmations - Used to determine how many blocks behind the head a block is considered finalized. Not used if the network has a concrete finalization mechanism.\n * @param {object} eventEmitter - Used to monitor the number of RPC requests\n */\n private constructor(\n client: Rpc<SolanaRpcApi>,\n genesisHash: string,\n private endpoint: string,\n private eventEmitter: EventEmitter2,\n readonly decoder: SolanaDecoder,\n requestTimeout: number = REQUEST_TIMEOUT,\n ) {\n this.#client = client;\n this.#genesisBlockHash = genesisHash;\n this.#requestTimeout = requestTimeout;\n }\n\n static async create(\n endpoint: string,\n eventEmitter: EventEmitter2,\n decoder: SolanaDecoder,\n config?: ISolanaEndpointConfig,\n ): Promise<SolanaApi> {\n try {\n // Keep-Alive is enabled by default, for more details see:\n // https://github.com/anza-xyz/kit/tree/main/packages/rpc-transport-http#config\n const client = createSolanaRpc(endpoint, {\n headers: {\n userAgent: `SubQuery Node ${packageVersion}`,\n ...(config?.headers as any), // TYPES ISSUE\n },\n });\n\n const genesisBlockHash = await client\n .getGenesisHash()\n .send({\n abortSignal: AbortSignal.timeout(\n config?.requestTimeout ?? REQUEST_TIMEOUT,\n ),\n })\n .catch((e) => {\n throw new Error('Failed to get genesis hash', { cause: e });\n });\n\n return new SolanaApi(\n client,\n genesisBlockHash,\n endpoint,\n eventEmitter,\n decoder,\n config?.requestTimeout,\n );\n } catch (e) {\n console.error('CrateSoalana API', e);\n throw e;\n }\n }\n\n async getFinalizedBlockHeader(): Promise<Header> {\n try {\n const height = await this.getFinalizedBlockHeight();\n // This needs retries becasue if the endpoint is load balanced you might get a different node that doesn't yet have this block\n const header = await backoffRetry(() =>\n this.getHeaderByHeightOrHash(height),\n );\n return header;\n } catch (e) {\n throw new Error('Failed to get finalized header', { cause: e });\n }\n }\n\n async getFinalizedBlockHeight(): Promise<number> {\n try {\n const finalizedHeight = await this.#client\n .getSlot({ commitment: 'finalized' })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n return Number(finalizedHeight);\n } catch (e) {\n throw new Error('Failed to get finalized height', { cause: e });\n }\n }\n\n async getBestBlockHeight(): Promise<number> {\n try {\n const confirmedHeight = await this.#client\n .getSlot({ commitment: 'confirmed' })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n return Number(confirmedHeight);\n } catch (e) {\n throw new Error('Failed to get best height', { cause: e });\n }\n }\n\n getRuntimeChain(): string {\n switch (this.#genesisBlockHash) {\n case '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d':\n return 'mainnet';\n case 'EKLxEB4xoEDq9AAn5HhFiP5WqdhNVc4An2HvJyzHzx7u': // Not tested\n return 'testnet;';\n case 'GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC':\n return 'devnet';\n default:\n return 'unknown';\n }\n }\n\n getGenesisHash(): string {\n return this.#genesisBlockHash;\n }\n\n getSpecName(): string {\n return 'solana';\n }\n\n async getHeaderByHeightOrHash(\n heightOrHash: number | string | bigint,\n ): Promise<Header> {\n // if (typeof heightOrHash === 'number') {\n // heightOrHash = hexValue(heightOrHash);\n // }\n if (typeof heightOrHash === 'string') {\n throw new Error('Hash not supported'); // TODO find a workaround\n }\n const slot =\n typeof heightOrHash === 'number' ? BigInt(heightOrHash) : heightOrHash;\n const block = await this.#client\n .getBlock(slot, {\n maxSupportedTransactionVersion: 0,\n transactionDetails: 'none',\n rewards: false,\n })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n if (!block) {\n throw new Error(`Unable to get block: ${heightOrHash}`);\n }\n\n return solanaBlockToHeader(block);\n }\n\n async fetchBlock(blockNumber: number): Promise<IBlock<SolanaBlock>> {\n try {\n const rawBlock = await this.#client\n .getBlock(BigInt(blockNumber), {\n encoding: 'json',\n transactionDetails: 'full',\n maxSupportedTransactionVersion: 0,\n })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n if (!rawBlock) {\n // No block for that slot\n throw new BlockUnavailableError();\n }\n\n this.eventEmitter.emit('fetchBlock');\n return formatBlockUtil(transformBlock(rawBlock, this.decoder));\n } catch (e: any) {\n console.log('Failed to fetch block', blockNumber, e.message);\n throw this.handleError(e);\n }\n }\n\n async fetchBlocks(bufferBlocks: number[]): Promise<IBlock<SolanaBlock>[]> {\n return Promise.all(bufferBlocks.map(async (num) => this.fetchBlock(num)));\n }\n\n get api(): Rpc<SolanaRpcApi> {\n return this.#client;\n }\n\n getSafeApi(blockHeight: number): SolanaSafeApi {\n return;\n // throw new Error('Safe Api is not supported');\n }\n\n // This method is designed to be compatible with @solana/web3.js so that @coral-xyz/anchor IDLs can be fetched.\n async getAccountInfo(address: unknown): Promise<{ data: Buffer } | null> {\n const addressStr =\n typeof address === 'string' ? address : (address as any).toBase58();\n assertIsAddress(addressStr);\n\n const res = await this.#client\n .getAccountInfo(addressStr, {\n encoding: 'base64',\n })\n .send({ abortSignal: AbortSignal.timeout(REQUEST_TIMEOUT) });\n\n if (res.value) {\n return {\n data: Buffer.from(res.value.data[0], 'base64'),\n };\n }\n\n return null;\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async connect(): Promise<void> {\n logger.error('Ethereum API connect is not implemented');\n throw new Error('Not implemented: connect');\n }\n\n async disconnect(): Promise<void> {\n // NO-OP\n // TODO implement if websockets are supported\n // if (this.client instanceof WebSocketProvider) {\n // await this.client.destroy();\n // } else {\n // logger.warn('Disconnect called on HTTP provider');\n // }\n }\n\n handleError(e: Error): Error {\n if ((e as any)?.context?.statusCode === 429) {\n const { hostname } = new URL(this.endpoint);\n return new Error(`Rate Limited at endpoint: ${hostname}`);\n }\n\n return e;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"api.solana.js","sourceRoot":"","sources":["../../src/solana/api.solana.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;AAGnC,iDAAoD;AACpD,qCAAmD;AAEnD,gDAO0B;AAE1B,iDAIwB;AAGxB,8DAA8D;AAC9D,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAElE,MAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,cAAc,CAAC,CAAC;AAIzC,MAAM,eAAe,GAAG,MAAM,CAAC;AAE/B,MAAa,SAAS;IAeV;IACA;IACC;IAhBX,OAAO,CAAoB;IAE3B,oDAAoD;IACpD,iBAAiB,CAAS;IAC1B,eAAe,CAAS;IAExB;;;;OAIG;IACH,YACE,MAAyB,EACzB,WAAmB,EACX,QAAgB,EAChB,YAA2B,EAC1B,OAAsB,EAC/B,iBAAyB,eAAe;QAHhC,aAAQ,GAAR,QAAQ,CAAQ;QAChB,iBAAY,GAAZ,YAAY,CAAe;QAC1B,YAAO,GAAP,OAAO,CAAe;QAG/B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC;QACrC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CACjB,QAAgB,EAChB,YAA2B,EAC3B,OAAsB,EACtB,MAA8B;QAE9B,IAAI,CAAC;YACH,0DAA0D;YAC1D,+EAA+E;YAC/E,MAAM,MAAM,GAAG,IAAA,qBAAe,EAAC,QAAQ,EAAE;gBACvC,OAAO,EAAE;oBACP,SAAS,EAAE,iBAAiB,cAAc,EAAE;oBAC5C,GAAI,MAAM,EAAE,OAAe,EAAE,cAAc;iBAC5C;aACF,CAAC,CAAC;YAEH,MAAM,gBAAgB,GAAG,MAAM,MAAM;iBAClC,cAAc,EAAE;iBAChB,IAAI,CAAC;gBACJ,WAAW,EAAE,WAAW,CAAC,OAAO,CAC9B,MAAM,EAAE,cAAc,IAAI,eAAe,CAC1C;aACF,CAAC;iBACD,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;gBACX,MAAM,IAAI,KAAK,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;YAEL,OAAO,IAAI,SAAS,CAClB,MAAM,EACN,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,MAAM,EAAE,cAAc,CACvB,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACpD,8HAA8H;YAC9H,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAY,EAAC,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;YACxE,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB;QAC3B,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,OAAO;iBACvC,OAAO,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;iBACpC,IAAI,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;YAEpE,OAAO,MAAM,CAAC,eAAe,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,OAAO;iBACvC,OAAO,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;iBACpC,IAAI,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;YAEpE,OAAO,MAAM,CAAC,eAAe,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,eAAe;QACb,QAAQ,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC/B,KAAK,8CAA8C;gBACjD,OAAO,SAAS,CAAC;YACnB,KAAK,8CAA8C,EAAE,aAAa;gBAChE,OAAO,UAAU,CAAC;YACpB,KAAK,8CAA8C;gBACjD,OAAO,QAAQ,CAAC;YAClB;gBACE,OAAO,SAAS,CAAC;QACrB,CAAC;IACH,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;IAED,WAAW;QACT,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,MAAuB;QAC7C,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAClE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO;aAC7B,QAAQ,CAAC,IAAI,EAAE;YACd,8BAA8B,EAAE,CAAC;YACjC,kBAAkB,EAAE,MAAM;YAC1B,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,WAAW,EAAE,qCAAqC;SAC/D,CAAC;aACD,IAAI,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAEpE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,yBAAyB;YACzB,MAAM,IAAI,iCAAqB,EAAE,CAAC;QACpC,CAAC;QAED,OAAO,IAAA,kCAAmB,EAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,WAAmB;QAClC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO;iBAChC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE;gBAC7B,QAAQ,EAAE,MAAM;gBAChB,kBAAkB,EAAE,MAAM;gBAC1B,8BAA8B,EAAE,CAAC;aAClC,CAAC;iBACD,IAAI,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;YAEpE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,yBAAyB;gBACzB,MAAM,IAAI,iCAAqB,EAAE,CAAC;YACpC,CAAC;YAED,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACrC,OAAO,IAAA,8BAAe,EAAC,IAAA,6BAAc,EAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;YAC7D,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,YAAsB;QACtC,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,UAAU,CAAC,WAAmB;QAC5B,OAAO;QACP,gDAAgD;IAClD,CAAC;IAED,+GAA+G;IAC/G,KAAK,CAAC,cAAc,CAAC,OAAgB;QACnC,MAAM,UAAU,GACd,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,OAAe,CAAC,QAAQ,EAAE,CAAC;QACtE,IAAA,2BAAe,EAAC,UAAU,CAAC,CAAC;QAE5B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO;aAC3B,cAAc,CAAC,UAAU,EAAE;YAC1B,QAAQ,EAAE,QAAQ;SACnB,CAAC;aACD,IAAI,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAE/D,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,OAAO;gBACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;aAC/C,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,OAAO;QACX,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,UAAU;QACd,QAAQ;QACR,6CAA6C;QAC7C,kDAAkD;QAClD,iCAAiC;QACjC,WAAW;QACX,uDAAuD;QACvD,IAAI;IACN,CAAC;IAED,WAAW,CAAC,CAAQ;QAClB,IAAK,CAAS,EAAE,OAAO,EAAE,UAAU,KAAK,GAAG,EAAE,CAAC;YAC5C,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5C,OAAO,IAAI,KAAK,CAAC,6BAA6B,QAAQ,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,CAAC,CAAC;IACX,CAAC;CACF;AA9ND,8BA8NC","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { assertIsAddress } from '@solana/addresses';\nimport { createSolanaRpc, Rpc } from '@solana/kit';\nimport { SolanaRpcApi } from '@solana/rpc-api';\nimport {\n backoffRetry,\n BlockUnavailableError,\n delay,\n getLogger,\n Header,\n IBlock,\n} from '@subql/node-core';\nimport { SolanaBlock, ISolanaEndpointConfig } from '@subql/types-solana';\nimport {\n formatBlockUtil,\n solanaBlockToHeader,\n transformBlock,\n} from './block.solana';\nimport { SolanaDecoder } from './decoder';\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version: packageVersion } = require('../../package.json');\n\nconst logger = getLogger('api.ethereum');\n\nexport type SolanaSafeApi = undefined;\n\nconst REQUEST_TIMEOUT = 30_000;\n\nexport class SolanaApi {\n #client: Rpc<SolanaRpcApi>;\n\n // This is used within the sandbox when HTTP is used\n #genesisBlockHash: string;\n #requestTimeout: number;\n\n /**\n * @param {string} endpoint - The endpoint of the RPC provider\n * @param {number} blockConfirmations - Used to determine how many blocks behind the head a block is considered finalized. Not used if the network has a concrete finalization mechanism.\n * @param {object} eventEmitter - Used to monitor the number of RPC requests\n */\n private constructor(\n client: Rpc<SolanaRpcApi>,\n genesisHash: string,\n private endpoint: string,\n private eventEmitter: EventEmitter2,\n readonly decoder: SolanaDecoder,\n requestTimeout: number = REQUEST_TIMEOUT,\n ) {\n this.#client = client;\n this.#genesisBlockHash = genesisHash;\n this.#requestTimeout = requestTimeout;\n }\n\n static async create(\n endpoint: string,\n eventEmitter: EventEmitter2,\n decoder: SolanaDecoder,\n config?: ISolanaEndpointConfig,\n ): Promise<SolanaApi> {\n try {\n // Keep-Alive is enabled by default, for more details see:\n // https://github.com/anza-xyz/kit/tree/main/packages/rpc-transport-http#config\n const client = createSolanaRpc(endpoint, {\n headers: {\n userAgent: `SubQuery Node ${packageVersion}`,\n ...(config?.headers as any), // TYPES ISSUE\n },\n });\n\n const genesisBlockHash = await client\n .getGenesisHash()\n .send({\n abortSignal: AbortSignal.timeout(\n config?.requestTimeout ?? REQUEST_TIMEOUT,\n ),\n })\n .catch((e) => {\n throw new Error('Failed to get genesis hash', { cause: e });\n });\n\n return new SolanaApi(\n client,\n genesisBlockHash,\n endpoint,\n eventEmitter,\n decoder,\n config?.requestTimeout,\n );\n } catch (e) {\n console.error('CrateSoalana API', e);\n throw e;\n }\n }\n\n async getFinalizedBlockHeader(): Promise<Header> {\n try {\n const height = await this.getFinalizedBlockHeight();\n // This needs retries becasue if the endpoint is load balanced you might get a different node that doesn't yet have this block\n const header = await backoffRetry(() => this.getHeaderByHeight(height));\n return header;\n } catch (e) {\n throw new Error('Failed to get finalized header', { cause: e });\n }\n }\n\n async getFinalizedBlockHeight(): Promise<number> {\n try {\n const finalizedHeight = await this.#client\n .getSlot({ commitment: 'finalized' })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n return Number(finalizedHeight);\n } catch (e) {\n throw new Error('Failed to get finalized height', { cause: e });\n }\n }\n\n async getBestBlockHeight(): Promise<number> {\n try {\n const confirmedHeight = await this.#client\n .getSlot({ commitment: 'confirmed' })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n return Number(confirmedHeight);\n } catch (e) {\n throw new Error('Failed to get best height', { cause: e });\n }\n }\n\n getRuntimeChain(): string {\n switch (this.#genesisBlockHash) {\n case '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d':\n return 'mainnet';\n case 'EKLxEB4xoEDq9AAn5HhFiP5WqdhNVc4An2HvJyzHzx7u': // Not tested\n return 'testnet;';\n case 'GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC':\n return 'devnet';\n default:\n return 'unknown';\n }\n }\n\n getGenesisHash(): string {\n return this.#genesisBlockHash;\n }\n\n getSpecName(): string {\n return 'solana';\n }\n\n async getHeaderByHeight(height: number | bigint): Promise<Header> {\n const slot = typeof height === 'number' ? BigInt(height) : height;\n const block = await this.#client\n .getBlock(slot, {\n maxSupportedTransactionVersion: 0,\n transactionDetails: 'none',\n rewards: false,\n commitment: 'confirmed', // This is used by unfinalized blocks\n })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n if (!block) {\n // No block for that slot\n throw new BlockUnavailableError();\n }\n\n return solanaBlockToHeader(block);\n }\n\n async fetchBlock(blockNumber: number): Promise<IBlock<SolanaBlock>> {\n try {\n const rawBlock = await this.#client\n .getBlock(BigInt(blockNumber), {\n encoding: 'json',\n transactionDetails: 'full',\n maxSupportedTransactionVersion: 0,\n })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n if (!rawBlock) {\n // No block for that slot\n throw new BlockUnavailableError();\n }\n\n this.eventEmitter.emit('fetchBlock');\n return formatBlockUtil(transformBlock(rawBlock, this.decoder));\n } catch (e: any) {\n console.log('Failed to fetch block', blockNumber, e.message);\n throw this.handleError(e);\n }\n }\n\n async fetchBlocks(bufferBlocks: number[]): Promise<IBlock<SolanaBlock>[]> {\n return Promise.all(bufferBlocks.map(async (num) => this.fetchBlock(num)));\n }\n\n get api(): Rpc<SolanaRpcApi> {\n return this.#client;\n }\n\n getSafeApi(blockHeight: number): SolanaSafeApi {\n return;\n // throw new Error('Safe Api is not supported');\n }\n\n // This method is designed to be compatible with @solana/web3.js so that @coral-xyz/anchor IDLs can be fetched.\n async getAccountInfo(address: unknown): Promise<{ data: Buffer } | null> {\n const addressStr =\n typeof address === 'string' ? address : (address as any).toBase58();\n assertIsAddress(addressStr);\n\n const res = await this.#client\n .getAccountInfo(addressStr, {\n encoding: 'base64',\n })\n .send({ abortSignal: AbortSignal.timeout(REQUEST_TIMEOUT) });\n\n if (res.value) {\n return {\n data: Buffer.from(res.value.data[0], 'base64'),\n };\n }\n\n return null;\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async connect(): Promise<void> {\n logger.error('Ethereum API connect is not implemented');\n throw new Error('Not implemented: connect');\n }\n\n async disconnect(): Promise<void> {\n // NO-OP\n // TODO implement if websockets are supported\n // if (this.client instanceof WebSocketProvider) {\n // await this.client.destroy();\n // } else {\n // logger.warn('Disconnect called on HTTP provider');\n // }\n }\n\n handleError(e: Error): Error {\n if ((e as any)?.context?.statusCode === 429) {\n const { hostname } = new URL(this.endpoint);\n return new Error(`Rate Limited at endpoint: ${hostname}`);\n }\n\n return e;\n }\n}\n"]}
|
|
@@ -16,6 +16,7 @@ const node_core_1 = require("@subql/node-core");
|
|
|
16
16
|
const x_sequelize_1 = require("@subql/x-sequelize");
|
|
17
17
|
const blockchain_service_1 = require("../blockchain.service");
|
|
18
18
|
const configure_module_1 = require("../configure/configure.module");
|
|
19
|
+
const unfinalizedBlocks_service_1 = require("../indexer/unfinalizedBlocks.service");
|
|
19
20
|
const solana_1 = require("../solana");
|
|
20
21
|
let ReindexFeatureModule = class ReindexFeatureModule {
|
|
21
22
|
};
|
|
@@ -34,7 +35,7 @@ exports.ReindexFeatureModule = ReindexFeatureModule = __decorate([
|
|
|
34
35
|
node_core_1.ForceCleanService,
|
|
35
36
|
{
|
|
36
37
|
provide: 'UnfinalizedBlocksService',
|
|
37
|
-
useClass:
|
|
38
|
+
useClass: unfinalizedBlocks_service_1.UnfinalizedBlocksService,
|
|
38
39
|
},
|
|
39
40
|
{
|
|
40
41
|
provide: 'DynamicDsService',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reindex.module.js","sourceRoot":"","sources":["../../src/subcommands/reindex.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAA0E;AAC1E,+CAAqD;AACrD,
|
|
1
|
+
{"version":3,"file":"reindex.module.js","sourceRoot":"","sources":["../../src/subcommands/reindex.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAA0E;AAC1E,+CAAqD;AACrD,gDAa0B;AAC1B,oDAA+C;AAC/C,8DAA0D;AAC1D,oEAAgE;AAChE,oFAAgF;AAChF,sCAA6C;AA2CtC,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAAG,CAAA;AAAvB,oDAAoB;+BAApB,oBAAoB;IAzChC,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,qBAAqB;gBAC9B,UAAU,EAAE,6BAAiB;gBAC7B,MAAM,EAAE,CAAC,sBAAU,EAAE,6BAAa,EAAE,uBAAS,CAAC;aAC/C;YACD,wBAAY;YACZ,0BAAc;YACd,sBAAU;YACV,6BAAiB;YACjB;gBACE,OAAO,EAAE,0BAA0B;gBACnC,QAAQ,EAAE,oDAAwB;aACnC;YACD;gBACE,OAAO,EAAE,kBAAkB;gBAC3B,QAAQ,EAAE,4BAAgB;aAC3B;YACD,8BAAkB;YAClB,sCAA0B;YAC1B,iCAAqB;YACrB;gBACE,OAAO,EAAE,YAAY;gBACrB,UAAU,EAAE,yBAAgB,CAAC,IAAI;gBACjC,MAAM,EAAE;oBACN,kBAAkB;oBAClB,iCAAqB;oBACrB,6BAAa;oBACb,sBAAU;iBACX;aACF;YACD;gBACE,OAAO,EAAE,oBAAoB;gBAC7B,QAAQ,EAAE,sCAAiB;aAC5B;YACD,mCAAuB;YACvB,4BAAiB;SAClB;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,oBAAoB,CAAG;AAW7B,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IATzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,oBAAQ,CAAC,OAAO,EAAE;YAClB,kCAAe,CAAC,QAAQ,EAAE;YAC1B,oBAAoB;YACpB,kCAAkB,CAAC,OAAO,EAAE;SAC7B;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,aAAa,CAAG","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Module } from '@nestjs/common';\nimport { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';\nimport { SchedulerRegistry } from '@nestjs/schedule';\nimport {\n DbModule,\n ForceCleanService,\n StoreService,\n ReindexService,\n PoiService,\n NodeConfig,\n storeModelFactory,\n ConnectionPoolService,\n ConnectionPoolStateManager,\n DynamicDsService,\n DsProcessorService,\n MultiChainRewindService,\n} from '@subql/node-core';\nimport { Sequelize } from '@subql/x-sequelize';\nimport { BlockchainService } from '../blockchain.service';\nimport { ConfigureModule } from '../configure/configure.module';\nimport { UnfinalizedBlocksService } from '../indexer/unfinalizedBlocks.service';\nimport { SolanaApiService } from '../solana';\n\n@Module({\n providers: [\n {\n provide: 'IStoreModelProvider',\n useFactory: storeModelFactory,\n inject: [NodeConfig, EventEmitter2, Sequelize],\n },\n StoreService,\n ReindexService,\n PoiService,\n ForceCleanService,\n {\n provide: 'UnfinalizedBlocksService',\n useClass: UnfinalizedBlocksService,\n },\n {\n provide: 'DynamicDsService',\n useClass: DynamicDsService,\n },\n DsProcessorService,\n ConnectionPoolStateManager,\n ConnectionPoolService,\n {\n provide: 'APIService',\n useFactory: SolanaApiService.init,\n inject: [\n 'ISubqueryProject',\n ConnectionPoolService,\n EventEmitter2,\n NodeConfig,\n ],\n },\n {\n provide: 'IBlockchainService',\n useClass: BlockchainService,\n },\n MultiChainRewindService,\n SchedulerRegistry,\n ],\n controllers: [],\n})\nexport class ReindexFeatureModule {}\n\n@Module({\n imports: [\n DbModule.forRoot(),\n ConfigureModule.register(),\n ReindexFeatureModule,\n EventEmitterModule.forRoot(),\n ],\n controllers: [],\n})\nexport class ReindexModule {}\n"]}
|
|
@@ -16,6 +16,7 @@ const node_core_1 = require("@subql/node-core");
|
|
|
16
16
|
const blockchain_service_1 = require("../blockchain.service");
|
|
17
17
|
const configure_module_1 = require("../configure/configure.module");
|
|
18
18
|
const indexer_manager_1 = require("../indexer/indexer.manager");
|
|
19
|
+
const unfinalizedBlocks_service_1 = require("../indexer/unfinalizedBlocks.service");
|
|
19
20
|
const solana_1 = require("../solana");
|
|
20
21
|
let TestingFeatureModule = class TestingFeatureModule {
|
|
21
22
|
};
|
|
@@ -40,7 +41,7 @@ exports.TestingFeatureModule = TestingFeatureModule = __decorate([
|
|
|
40
41
|
},
|
|
41
42
|
{
|
|
42
43
|
provide: 'IUnfinalizedBlocksService',
|
|
43
|
-
useClass:
|
|
44
|
+
useClass: unfinalizedBlocks_service_1.UnfinalizedBlocksService,
|
|
44
45
|
},
|
|
45
46
|
{
|
|
46
47
|
provide: 'IBlockchainService',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.module.js","sourceRoot":"","sources":["../../src/subcommands/testing.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAA0E;AAC1E,+CAAkD;AAClD,
|
|
1
|
+
{"version":3,"file":"testing.module.js","sourceRoot":"","sources":["../../src/subcommands/testing.module.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;AAEnC,2CAAwC;AACxC,yDAA0E;AAC1E,+CAAkD;AAClD,gDAS0B;AAC1B,8DAA0D;AAC1D,oEAAgE;AAChE,gEAA4D;AAC5D,oFAAgF;AAChF,sCAA6C;AAsCtC,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAAG,CAAA;AAAvB,oDAAoB;+BAApB,oBAAoB;IApChC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,6BAAiB,CAAC;QAC5B,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,0BAAc;aACzB;YACD;gBACE,OAAO,EAAE,YAAY;gBACrB,UAAU,EAAE,yBAAgB,CAAC,IAAI;gBACjC,MAAM,EAAE;oBACN,kBAAkB;oBAClB,iCAAqB;oBACrB,6BAAa;oBACb,sBAAU;iBACX;aACF;YACD;gBACE,OAAO,EAAE,2BAA2B;gBACpC,QAAQ,EAAE,oDAAwB;aACnC;YACD;gBACE,OAAO,EAAE,oBAAoB;gBAC7B,QAAQ,EAAE,sCAAiB;aAC5B;YACD,sBAAU;YACV;gBACE,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,gCAAc;aACzB;YACD,8BAAkB;YAClB,4BAAgB;SACjB;QACD,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,CAAC,sBAAU,CAAC;KACtB,CAAC;GACW,oBAAoB,CAAG;AAY7B,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IAVzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,oBAAQ,CAAC,OAAO,EAAE;YAClB,kCAAe,CAAC,QAAQ,EAAE;YAC1B,kCAAkB,CAAC,OAAO,EAAE;YAC5B,yBAAc,CAAC,OAAO,EAAE;YACxB,oBAAoB;SACrB;QACD,WAAW,EAAE,EAAE;KAChB,CAAC;GACW,aAAa,CAAG","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Module } from '@nestjs/common';\nimport { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';\nimport { ScheduleModule } from '@nestjs/schedule';\nimport {\n ConnectionPoolService,\n DbModule,\n DsProcessorService,\n DynamicDsService,\n NodeConfig,\n ProjectService,\n TestRunner,\n TestingCoreModule,\n} from '@subql/node-core';\nimport { BlockchainService } from '../blockchain.service';\nimport { ConfigureModule } from '../configure/configure.module';\nimport { IndexerManager } from '../indexer/indexer.manager';\nimport { UnfinalizedBlocksService } from '../indexer/unfinalizedBlocks.service';\nimport { SolanaApiService } from '../solana';\n\n@Module({\n imports: [TestingCoreModule],\n providers: [\n {\n provide: 'IProjectService',\n useClass: ProjectService,\n },\n {\n provide: 'APIService',\n useFactory: SolanaApiService.init,\n inject: [\n 'ISubqueryProject',\n ConnectionPoolService,\n EventEmitter2,\n NodeConfig,\n ],\n },\n {\n provide: 'IUnfinalizedBlocksService',\n useClass: UnfinalizedBlocksService,\n },\n {\n provide: 'IBlockchainService',\n useClass: BlockchainService,\n },\n TestRunner,\n {\n provide: 'IIndexerManager',\n useClass: IndexerManager,\n },\n DsProcessorService,\n DynamicDsService,\n ],\n controllers: [],\n exports: [TestRunner],\n})\nexport class TestingFeatureModule {}\n\n@Module({\n imports: [\n DbModule.forRoot(),\n ConfigureModule.register(),\n EventEmitterModule.forRoot(),\n ScheduleModule.forRoot(),\n TestingFeatureModule,\n ],\n controllers: [],\n})\nexport class TestingModule {}\n"]}
|