@subql/node-solana 6.0.0-2 → 6.0.1-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.
|
@@ -23,7 +23,7 @@ export declare class SolanaApi {
|
|
|
23
23
|
getRuntimeChain(): string;
|
|
24
24
|
getGenesisHash(): string;
|
|
25
25
|
getSpecName(): string;
|
|
26
|
-
getHeaderByHeightOrHash(heightOrHash: number | string): Promise<Header>;
|
|
26
|
+
getHeaderByHeightOrHash(heightOrHash: number | string | 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>;
|
|
@@ -59,21 +59,10 @@ class SolanaApi {
|
|
|
59
59
|
}
|
|
60
60
|
async getFinalizedBlockHeader() {
|
|
61
61
|
try {
|
|
62
|
-
const height = await this
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const block = await this.#client
|
|
67
|
-
.getBlock(height, {
|
|
68
|
-
encoding: 'json',
|
|
69
|
-
transactionDetails: 'none',
|
|
70
|
-
rewards: false,
|
|
71
|
-
})
|
|
72
|
-
.send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });
|
|
73
|
-
if (!block) {
|
|
74
|
-
throw new Error('Unable to get finalized block');
|
|
75
|
-
}
|
|
76
|
-
return (0, block_solana_1.solanaBlockToHeader)(block);
|
|
62
|
+
const height = await this.getFinalizedBlockHeight();
|
|
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.getHeaderByHeightOrHash(height));
|
|
65
|
+
return header;
|
|
77
66
|
}
|
|
78
67
|
catch (e) {
|
|
79
68
|
throw new Error('Failed to get finalized header', { cause: e });
|
|
@@ -126,9 +115,12 @@ class SolanaApi {
|
|
|
126
115
|
if (typeof heightOrHash === 'string') {
|
|
127
116
|
throw new Error('Hash not supported'); // TODO find a workaround
|
|
128
117
|
}
|
|
118
|
+
const slot = typeof heightOrHash === 'number' ? BigInt(heightOrHash) : heightOrHash;
|
|
129
119
|
const block = await this.#client
|
|
130
|
-
.getBlock(
|
|
120
|
+
.getBlock(slot, {
|
|
131
121
|
maxSupportedTransactionVersion: 0,
|
|
122
|
+
transactionDetails: 'none',
|
|
123
|
+
rewards: false,
|
|
132
124
|
})
|
|
133
125
|
.send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });
|
|
134
126
|
if (!block) {
|
|
@@ -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 BlockUnavailableError,\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.#client\n .getSlot({ commitment: 'finalized' })\n .send({ abortSignal: AbortSignal.timeout(this.#requestTimeout) });\n\n // Request the minimal amount of information here\n const block = await this.#client\n .getBlock(height, {\n encoding: 'json',\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 finalized block');\n }\n\n return solanaBlockToHeader(block);\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,\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 block = await this.#client\n .getBlock(BigInt(heightOrHash), {\n maxSupportedTransactionVersion: 0,\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":"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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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subql/node-solana",
|
|
3
|
-
"version": "6.0.0
|
|
3
|
+
"version": "6.0.1-0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Ian He",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
"@nestjs/schedule": "^5.0.1",
|
|
28
28
|
"@solana/kit": "^2.1.0",
|
|
29
29
|
"@subql/common": "5.4.1-1",
|
|
30
|
-
"@subql/common-solana": "
|
|
31
|
-
"@subql/node-core": "^18.0
|
|
30
|
+
"@subql/common-solana": "1.0.0",
|
|
31
|
+
"@subql/node-core": "^18.1.0",
|
|
32
32
|
"@subql/testing": "^2.2.1",
|
|
33
|
-
"@subql/types-solana": "
|
|
33
|
+
"@subql/types-solana": "1.0.0",
|
|
34
34
|
"bs58": "^6.0.0",
|
|
35
35
|
"cacheable-lookup": "6",
|
|
36
36
|
"codama": "^1.2.11",
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"/dist",
|
|
66
66
|
"/bin"
|
|
67
67
|
],
|
|
68
|
-
"stableVersion": "6.0.0
|
|
68
|
+
"stableVersion": "6.0.0"
|
|
69
69
|
}
|