@subql/node-solana 6.1.1 → 6.1.2-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 +2 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/solana/api.solana.js +1 -1
- package/dist/solana/api.solana.js.map +1 -1
- package/dist/solana/api.solana.spec.js +12 -3
- package/dist/solana/api.solana.spec.js.map +1 -1
- package/dist/solana/block.solana.js +1 -1
- package/dist/solana/block.solana.js.map +1 -1
- package/package.json +3 -2
|
@@ -96,7 +96,7 @@ class SolanaApi {
|
|
|
96
96
|
return 'mainnet';
|
|
97
97
|
case 'EKLxEB4xoEDq9AAn5HhFiP5WqdhNVc4An2HvJyzHzx7u': // Not tested
|
|
98
98
|
return 'testnet;';
|
|
99
|
-
case '
|
|
99
|
+
case 'EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG':
|
|
100
100
|
return 'devnet';
|
|
101
101
|
default:
|
|
102
102
|
return 'unknown';
|
|
@@ -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/rpc';\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"]}
|
|
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/rpc';\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 'EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG':\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"]}
|
|
@@ -7,7 +7,9 @@ const api_solana_1 = require("./api.solana");
|
|
|
7
7
|
const decoder_1 = require("./decoder");
|
|
8
8
|
const utils_solana_1 = require("./utils.solana");
|
|
9
9
|
// Add api key to work
|
|
10
|
-
const HTTP_ENDPOINT = process.env.HTTP_ENDPOINT ??
|
|
10
|
+
const HTTP_ENDPOINT = process.env.HTTP_ENDPOINT ??
|
|
11
|
+
'https://api.mainnet-beta.solana.com' ??
|
|
12
|
+
'https://solana.api.onfinality.io/public';
|
|
11
13
|
const IDL_swap = require('../../test/swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.idl.json');
|
|
12
14
|
describe('Api.solana', () => {
|
|
13
15
|
let solanaApi;
|
|
@@ -19,8 +21,8 @@ describe('Api.solana', () => {
|
|
|
19
21
|
// https://solscan.io/block/325922873
|
|
20
22
|
block = await solanaApi.fetchBlock(325_922_873);
|
|
21
23
|
}, 20_000);
|
|
22
|
-
function getTxBySig(sig) {
|
|
23
|
-
const tx = block.block.transactions.find((tx) => tx.transaction.signatures.find((s) => s === sig));
|
|
24
|
+
function getTxBySig(sig, specificBlock) {
|
|
25
|
+
const tx = (specificBlock ?? block).block.transactions.find((tx) => tx.transaction.signatures.find((s) => s === sig));
|
|
24
26
|
if (!tx) {
|
|
25
27
|
throw new Error(`Unable to find tx with signature ${sig}`);
|
|
26
28
|
}
|
|
@@ -162,6 +164,13 @@ describe('Api.solana', () => {
|
|
|
162
164
|
expect(txWError.meta.logs).toBeDefined();
|
|
163
165
|
expect(txWError.meta.logs.length).toBeGreaterThan(0);
|
|
164
166
|
});
|
|
167
|
+
it('can parse a block with a transaction that has "null" innerTransactions', async () => {
|
|
168
|
+
// The problem transaction: https://solscan.io/tx/3mSAfK9hm4wgMw5kzKpVz73viBftapNLwECN9rmG5Q6qWPyARognZsyoosB4XjYf5nFRtcEmrKGVgLGLRN7tnmWN?cluster=devnet
|
|
169
|
+
const solanaApi = await api_solana_1.SolanaApi.create('https://api.devnet.solana.com', eventEmitter, decoder);
|
|
170
|
+
const block = await solanaApi.fetchBlock(405433240);
|
|
171
|
+
expect(block).toBeDefined();
|
|
172
|
+
expect(getTxBySig('3mSAfK9hm4wgMw5kzKpVz73viBftapNLwECN9rmG5Q6qWPyARognZsyoosB4XjYf5nFRtcEmrKGVgLGLRN7tnmWN', block)).toBeDefined();
|
|
173
|
+
});
|
|
165
174
|
});
|
|
166
175
|
// Tests that data types can be stringified, this is important to test because of circular references
|
|
167
176
|
describe('JSON serialization', () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.solana.spec.js","sourceRoot":"","sources":["../../src/solana/api.solana.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 { IdlV01 } from '@codama/nodes-from-anchor';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { TransactionFilter } from '@subql/common-solana';\nimport { IBlock } from '@subql/node-core';\nimport {\n SolanaBlock,\n SolanaBlockFilter,\n SolanaTransaction,\n} from '@subql/types-solana';\nimport { SolanaApi } from './api.solana';\nimport { SolanaDecoder } from './decoder';\nimport {\n filterBlocksProcessor,\n filterInstructionsProcessor,\n filterLogsProcessor,\n filterTransactionsProcessor,\n} from './utils.solana';\n\n// Add api key to work\nconst HTTP_ENDPOINT =\n process.env.HTTP_ENDPOINT ?? 'https://solana.api.onfinality.io/public';\n\nconst IDL_swap: IdlV01 = require('../../test/swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.idl.json');\n\ndescribe('Api.solana', () => {\n let solanaApi: SolanaApi;\n const eventEmitter = new EventEmitter2();\n let block: IBlock<SolanaBlock>;\n const decoder = new SolanaDecoder();\n\n beforeAll(async () => {\n solanaApi = await SolanaApi.create(HTTP_ENDPOINT, eventEmitter, decoder);\n // https://solscan.io/block/325922873\n block = await solanaApi.fetchBlock(325_922_873);\n }, 20_000);\n\n function getTxBySig(sig: string): SolanaTransaction {\n const tx = block.block.transactions.find((tx) =>\n tx.transaction.signatures.find((s) => s === sig),\n );\n if (!tx) {\n throw new Error(`Unable to find tx with signature ${sig}`);\n }\n return tx;\n }\n\n it('parses block timestamps correctly', () => {\n expect(block.getHeader().timestamp).toEqual(\n new Date('2025-03-10T22:40:28.000Z'),\n );\n });\n\n describe('Filters', () => {\n it('Should run block filters correctly', () => {\n const moduloBlockFilter: SolanaBlockFilter = {\n modulo: 1,\n };\n expect(\n filterBlocksProcessor(block.block, moduloBlockFilter),\n ).toBeTruthy();\n\n const moduloBlockFilter2: SolanaBlockFilter = {\n modulo: 325_922_870,\n };\n expect(\n filterBlocksProcessor(block.block, moduloBlockFilter2),\n ).toBeFalsy();\n\n // TODO timestamp block filter\n });\n\n it('Should run transaction filters correctly', () => {\n // https://solscan.io/tx/FQNxV3NQHf6JBzYkaaWaRVj3eAtdEVSsjdStXM9ciZmWfoeiABaG3dXqK612T3LMi3McP5hf967AgJByvRkkRJY\n const tx = getTxBySig(\n 'FQNxV3NQHf6JBzYkaaWaRVj3eAtdEVSsjdStXM9ciZmWfoeiABaG3dXqK612T3LMi3McP5hf967AgJByvRkkRJY',\n );\n\n const signerMatch: TransactionFilter = {\n signerAccountKey: '3j1iDNRseKJVEWAb62Xxn74mVjJ7sUTVJaaBNb3gKtUe',\n };\n expect(filterTransactionsProcessor(tx!, signerMatch)).toBeTruthy();\n\n const signerMismatch: TransactionFilter = {\n signerAccountKey: '7yYGUXSY9hSa3MqmU7t4acCMBzSQyjxZyoRC1bDKMKJh',\n };\n expect(filterTransactionsProcessor(tx!, signerMismatch)).toBeFalsy();\n });\n\n describe('instructions', () => {\n it('can filter failed instructions', () => {\n const failedTx = block.block.transactions.find((tx) => tx.meta?.err);\n const failedInst = failedTx!.transaction.message.instructions[0];\n expect(\n filterInstructionsProcessor(failedInst, solanaApi.decoder, {\n includeFailed: true,\n }),\n ).toBeTruthy();\n expect(\n filterInstructionsProcessor(failedInst, solanaApi.decoder, {\n includeFailed: false,\n }),\n ).toBeFalsy();\n });\n\n it('can filter programIds', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n const inst = tx?.transaction.message.instructions[4];\n\n expect(inst).toBeDefined();\n\n // A program called by this instruction\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n programId: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8',\n }),\n ).toBe(true);\n\n // A program not called by this instruction\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n }),\n ).toBe(false);\n });\n\n it.each([\n // ['human', 'swap', true], // TODO wrong IDL currently\n ['hex', '0x09', true],\n ['base58', 'A', true],\n ['human', 'shutdown', false],\n ['hex', '0x74ce1bbfa6130049', false],\n ['base58', 'kPf6M86k1NDLT', false],\n ])(\n 'should correctly match discrminators in %s format',\n (_, discriminator, result) => {\n // TODO wrong IDL currently\n solanaApi.decoder.idls[\n '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'\n ] = IDL_swap;\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n const inst = tx?.transaction.message.instructions[4];\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n programId: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8',\n discriminator,\n }),\n ).toBe(result);\n },\n );\n\n it('can filter accounts', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n const inst = tx?.transaction.message.instructions[4];\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n accounts: [null, ['6fuLRV8aLJF96MaNi44bLJUhaSJu1yzc588kHM4DfG2W']],\n }),\n ).toBe(true);\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n accounts: [\n null,\n null,\n ['6fuLRV8aLJF96MaNi44bLJUhaSJu1yzc588kHM4DfG2W'], // Out of position\n ],\n }),\n ).toBe(false);\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n accounts: [null, null, []],\n }),\n ).toBe(false);\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n accounts: [\n null,\n [\n '6fuLRV8aLJF96MaNi44bLJUhaSJu1yzc588kHM4DfG2W',\n '5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1',\n ], // Out of position\n ],\n }),\n ).toBe(true);\n });\n });\n\n describe('logs', () => {\n it('should filter logs by program Id', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n\n const log = tx!.meta!.logs![1];\n expect(log).toBeDefined();\n // Matching program id\n expect(\n filterLogsProcessor(log, {\n programId: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8',\n }),\n ).toBe(true);\n\n // non-matching programId\n expect(\n filterLogsProcessor(log, {\n programId: '5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1',\n }),\n ).toBe(false);\n });\n });\n });\n\n describe('Block parsing', () => {\n it('makes instructions that have a transaction property', () => {\n const tx = getTxBySig(\n 'FQNxV3NQHf6JBzYkaaWaRVj3eAtdEVSsjdStXM9ciZmWfoeiABaG3dXqK612T3LMi3McP5hf967AgJByvRkkRJY',\n );\n\n for (const instruction of tx!.transaction.message.instructions) {\n expect(instruction.transaction).toBeDefined();\n }\n\n for (const innerInstruction of tx!.meta!.innerInstructions) {\n for (const instruction of innerInstruction.instructions) {\n expect(instruction.transaction).toBeDefined();\n }\n }\n });\n\n it('corretly parses logs', () => {\n const tx = getTxBySig(\n '4vGc5nP4W7VZe7SmSb2GsJMG3KJijZJ4KGHUCQ14FmqfPsyDotn7kwR5nA13PpzjwT732ggiLuDGs5PDpjRCKsC6',\n );\n expect(tx!.meta!.logs).toBeDefined();\n expect(tx!.meta!.logs!.length).toBeGreaterThan(0);\n\n // Tx with data logs\n const txWData = getTxBySig(\n 'qtUujQqx16ChZRMG4TE9eNMp4th3GxLvuuCQBEXK4KYyjqfAAPbP6xejA2ZTUe7X1cZYiHCnJHpC5v6GRctYc8c',\n );\n expect(txWData!.meta!.logs).toBeDefined();\n expect(txWData!.meta!.logs!.length).toBeGreaterThan(0);\n\n // Tx with a failure\n const txWError = getTxBySig(\n '8q3z3WoYUcA8UQLYgdgriGCZrGJUAYoeUwTJaVuuq43AmKLQxKLAMxuEAWXMquozVXEX4eL91r3jxKFVifmeXrv',\n );\n expect(txWError!.meta!.logs).toBeDefined();\n expect(txWError!.meta!.logs!.length).toBeGreaterThan(0);\n });\n });\n\n // Tests that data types can be stringified, this is important to test because of circular references\n describe('JSON serialization', () => {\n it('can stringify a SolanaBlock', () => {\n expect(() => JSON.stringify(block)).not.toThrow();\n });\n\n it('can stringify a SolanaTransaction', () => {\n const tx = getTxBySig(\n '4vGc5nP4W7VZe7SmSb2GsJMG3KJijZJ4KGHUCQ14FmqfPsyDotn7kwR5nA13PpzjwT732ggiLuDGs5PDpjRCKsC6',\n );\n\n expect(tx).toBeDefined();\n expect(() => JSON.stringify(tx)).not.toThrow();\n });\n\n it('can stringify a SolanaInstruction', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n const inst = tx?.transaction.message.instructions[4];\n expect(inst).toBeDefined();\n\n const decodeInst = jest.spyOn(solanaApi.decoder, 'decodeInstruction');\n expect(() => JSON.stringify(inst)).not.toThrow();\n expect(decodeInst).not.toHaveBeenCalled();\n });\n\n it('can stringify a LogMessage', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n\n for (const log of tx!.meta!.logs!) {\n const decodeLog = jest.spyOn(solanaApi.decoder, 'decodeLog');\n expect(() => JSON.stringify(log)).not.toThrow();\n expect(decodeLog).not.toHaveBeenCalled();\n }\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"api.solana.spec.js","sourceRoot":"","sources":["../../src/solana/api.solana.spec.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;AAGnC,yDAAsD;AAQtD,6CAAyC;AACzC,uCAA0C;AAC1C,iDAKwB;AAExB,sBAAsB;AACtB,MAAM,aAAa,GACjB,OAAO,CAAC,GAAG,CAAC,aAAa;IACzB,qCAAqC;IACrC,yCAAyC,CAAC;AAE5C,MAAM,QAAQ,GAAW,OAAO,CAAC,iEAAiE,CAAC,CAAC;AAEpG,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,IAAI,SAAoB,CAAC;IACzB,MAAM,YAAY,GAAG,IAAI,6BAAa,EAAE,CAAC;IACzC,IAAI,KAA0B,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,uBAAa,EAAE,CAAC;IAEpC,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,SAAS,GAAG,MAAM,sBAAS,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QACzE,qCAAqC;QACrC,KAAK,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,SAAS,UAAU,CACjB,GAAW,EACX,aAAmC;QAEnC,MAAM,EAAE,GAAG,CAAC,aAAa,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CACjE,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CACjD,CAAC;QACF,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,CAAC,OAAO,CACzC,IAAI,IAAI,CAAC,0BAA0B,CAAC,CACrC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,iBAAiB,GAAsB;gBAC3C,MAAM,EAAE,CAAC;aACV,CAAC;YACF,MAAM,CACJ,IAAA,oCAAqB,EAAC,KAAK,CAAC,KAAK,EAAE,iBAAiB,CAAC,CACtD,CAAC,UAAU,EAAE,CAAC;YAEf,MAAM,kBAAkB,GAAsB;gBAC5C,MAAM,EAAE,WAAW;aACpB,CAAC;YACF,MAAM,CACJ,IAAA,oCAAqB,EAAC,KAAK,CAAC,KAAK,EAAE,kBAAkB,CAAC,CACvD,CAAC,SAAS,EAAE,CAAC;YAEd,8BAA8B;QAChC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,gHAAgH;YAChH,MAAM,EAAE,GAAG,UAAU,CACnB,yFAAyF,CAC1F,CAAC;YAEF,MAAM,WAAW,GAAsB;gBACrC,gBAAgB,EAAE,8CAA8C;aACjE,CAAC;YACF,MAAM,CAAC,IAAA,0CAA2B,EAAC,EAAG,EAAE,WAAW,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;YAEnE,MAAM,cAAc,GAAsB;gBACxC,gBAAgB,EAAE,8CAA8C;aACjE,CAAC;YACF,MAAM,CAAC,IAAA,0CAA2B,EAAC,EAAG,EAAE,cAAc,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;YAC5B,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;gBACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBACrE,MAAM,UAAU,GAAG,QAAS,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;gBACjE,MAAM,CACJ,IAAA,0CAA2B,EAAC,UAAU,EAAE,SAAS,CAAC,OAAO,EAAE;oBACzD,aAAa,EAAE,IAAI;iBACpB,CAAC,CACH,CAAC,UAAU,EAAE,CAAC;gBACf,MAAM,CACJ,IAAA,0CAA2B,EAAC,UAAU,EAAE,SAAS,CAAC,OAAO,EAAE;oBACzD,aAAa,EAAE,KAAK;iBACrB,CAAC,CACH,CAAC,SAAS,EAAE,CAAC;YAChB,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;gBAC/B,MAAM,EAAE,GAAG,UAAU,CACnB,0FAA0F,CAC3F,CAAC;gBACF,MAAM,IAAI,GAAG,EAAE,EAAE,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;gBAErD,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBAE3B,uCAAuC;gBACvC,MAAM,CACJ,IAAA,0CAA2B,EAAC,IAAK,EAAE,SAAS,CAAC,OAAO,EAAE;oBACpD,SAAS,EAAE,8CAA8C;iBAC1D,CAAC,CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEb,2CAA2C;gBAC3C,MAAM,CACJ,IAAA,0CAA2B,EAAC,IAAK,EAAE,SAAS,CAAC,OAAO,EAAE;oBACpD,SAAS,EAAE,6CAA6C;iBACzD,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,IAAI,CAAC;gBACN,uDAAuD;gBACvD,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC;gBACrB,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC;gBACrB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC;gBAC5B,CAAC,KAAK,EAAE,oBAAoB,EAAE,KAAK,CAAC;gBACpC,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC;aACnC,CAAC,CACA,mDAAmD,EACnD,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE;gBAC3B,2BAA2B;gBAC3B,SAAS,CAAC,OAAO,CAAC,IAAI,CACpB,8CAA8C,CAC/C,GAAG,QAAQ,CAAC;gBACb,MAAM,EAAE,GAAG,UAAU,CACnB,0FAA0F,CAC3F,CAAC;gBACF,MAAM,IAAI,GAAG,EAAE,EAAE,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;gBAErD,MAAM,CACJ,IAAA,0CAA2B,EAAC,IAAK,EAAE,SAAS,CAAC,OAAO,EAAE;oBACpD,SAAS,EAAE,8CAA8C;oBACzD,aAAa;iBACd,CAAC,CACH,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,CAAC,CACF,CAAC;YAEF,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;gBAC7B,MAAM,EAAE,GAAG,UAAU,CACnB,0FAA0F,CAC3F,CAAC;gBACF,MAAM,IAAI,GAAG,EAAE,EAAE,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;gBAErD,MAAM,CACJ,IAAA,0CAA2B,EAAC,IAAK,EAAE,SAAS,CAAC,OAAO,EAAE;oBACpD,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,8CAA8C,CAAC,CAAC;iBACnE,CAAC,CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEb,MAAM,CACJ,IAAA,0CAA2B,EAAC,IAAK,EAAE,SAAS,CAAC,OAAO,EAAE;oBACpD,QAAQ,EAAE;wBACR,IAAI;wBACJ,IAAI;wBACJ,CAAC,8CAA8C,CAAC,EAAE,kBAAkB;qBACrE;iBACF,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAEd,MAAM,CACJ,IAAA,0CAA2B,EAAC,IAAK,EAAE,SAAS,CAAC,OAAO,EAAE;oBACpD,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;iBAC3B,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAEd,MAAM,CACJ,IAAA,0CAA2B,EAAC,IAAK,EAAE,SAAS,CAAC,OAAO,EAAE;oBACpD,QAAQ,EAAE;wBACR,IAAI;wBACJ;4BACE,8CAA8C;4BAC9C,8CAA8C;yBAC/C,EAAE,kBAAkB;qBACtB;iBACF,CAAC,CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;YACpB,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;gBAC1C,MAAM,EAAE,GAAG,UAAU,CACnB,0FAA0F,CAC3F,CAAC;gBAEF,MAAM,GAAG,GAAG,EAAG,CAAC,IAAK,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC;gBAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;gBAC1B,sBAAsB;gBACtB,MAAM,CACJ,IAAA,kCAAmB,EAAC,GAAG,EAAE;oBACvB,SAAS,EAAE,8CAA8C;iBAC1D,CAAC,CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEb,yBAAyB;gBACzB,MAAM,CACJ,IAAA,kCAAmB,EAAC,GAAG,EAAE;oBACvB,SAAS,EAAE,8CAA8C;iBAC1D,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,EAAE,GAAG,UAAU,CACnB,yFAAyF,CAC1F,CAAC;YAEF,KAAK,MAAM,WAAW,IAAI,EAAG,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;gBAC/D,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;YAChD,CAAC;YAED,KAAK,MAAM,gBAAgB,IAAI,EAAG,CAAC,IAAK,CAAC,iBAAiB,EAAE,CAAC;gBAC3D,KAAK,MAAM,WAAW,IAAI,gBAAgB,CAAC,YAAY,EAAE,CAAC;oBACxD,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;YAC9B,MAAM,EAAE,GAAG,UAAU,CACnB,0FAA0F,CAC3F,CAAC;YACF,MAAM,CAAC,EAAG,CAAC,IAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,CAAC,EAAG,CAAC,IAAK,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAElD,oBAAoB;YACpB,MAAM,OAAO,GAAG,UAAU,CACxB,yFAAyF,CAC1F,CAAC;YACF,MAAM,CAAC,OAAQ,CAAC,IAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC1C,MAAM,CAAC,OAAQ,CAAC,IAAK,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAEvD,oBAAoB;YACpB,MAAM,QAAQ,GAAG,UAAU,CACzB,yFAAyF,CAC1F,CAAC;YACF,MAAM,CAAC,QAAS,CAAC,IAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,CAAC,QAAS,CAAC,IAAK,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;YACtF,yJAAyJ;YACzJ,MAAM,SAAS,GAAG,MAAM,sBAAS,CAAC,MAAM,CACtC,+BAA+B,EAC/B,YAAY,EACZ,OAAO,CACR,CAAC;YAEF,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAEpD,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YAE5B,MAAM,CACJ,UAAU,CACR,0FAA0F,EAC1F,KAAK,CACN,CACF,CAAC,WAAW,EAAE,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,qGAAqG;IACrG,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,EAAE,GAAG,UAAU,CACnB,0FAA0F,CAC3F,CAAC;YAEF,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,EAAE,GAAG,UAAU,CACnB,0FAA0F,CAC3F,CAAC;YACF,MAAM,IAAI,GAAG,EAAE,EAAE,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAE3B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;YACtE,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YACjD,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;YACpC,MAAM,EAAE,GAAG,UAAU,CACnB,0FAA0F,CAC3F,CAAC;YAEF,KAAK,MAAM,GAAG,IAAI,EAAG,CAAC,IAAK,CAAC,IAAK,EAAE,CAAC;gBAClC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;gBAC7D,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBAChD,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAC3C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,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 { IdlV01 } from '@codama/nodes-from-anchor';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { TransactionFilter } from '@subql/common-solana';\nimport { IBlock } from '@subql/node-core';\nimport {\n SolanaBlock,\n SolanaBlockFilter,\n SolanaTransaction,\n} from '@subql/types-solana';\nimport { SolanaApi } from './api.solana';\nimport { SolanaDecoder } from './decoder';\nimport {\n filterBlocksProcessor,\n filterInstructionsProcessor,\n filterLogsProcessor,\n filterTransactionsProcessor,\n} from './utils.solana';\n\n// Add api key to work\nconst HTTP_ENDPOINT =\n process.env.HTTP_ENDPOINT ??\n 'https://api.mainnet-beta.solana.com' ??\n 'https://solana.api.onfinality.io/public';\n\nconst IDL_swap: IdlV01 = require('../../test/swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.idl.json');\n\ndescribe('Api.solana', () => {\n let solanaApi: SolanaApi;\n const eventEmitter = new EventEmitter2();\n let block: IBlock<SolanaBlock>;\n const decoder = new SolanaDecoder();\n\n beforeAll(async () => {\n solanaApi = await SolanaApi.create(HTTP_ENDPOINT, eventEmitter, decoder);\n // https://solscan.io/block/325922873\n block = await solanaApi.fetchBlock(325_922_873);\n }, 20_000);\n\n function getTxBySig(\n sig: string,\n specificBlock?: IBlock<SolanaBlock>,\n ): SolanaTransaction {\n const tx = (specificBlock ?? block).block.transactions.find((tx) =>\n tx.transaction.signatures.find((s) => s === sig),\n );\n if (!tx) {\n throw new Error(`Unable to find tx with signature ${sig}`);\n }\n return tx;\n }\n\n it('parses block timestamps correctly', () => {\n expect(block.getHeader().timestamp).toEqual(\n new Date('2025-03-10T22:40:28.000Z'),\n );\n });\n\n describe('Filters', () => {\n it('Should run block filters correctly', () => {\n const moduloBlockFilter: SolanaBlockFilter = {\n modulo: 1,\n };\n expect(\n filterBlocksProcessor(block.block, moduloBlockFilter),\n ).toBeTruthy();\n\n const moduloBlockFilter2: SolanaBlockFilter = {\n modulo: 325_922_870,\n };\n expect(\n filterBlocksProcessor(block.block, moduloBlockFilter2),\n ).toBeFalsy();\n\n // TODO timestamp block filter\n });\n\n it('Should run transaction filters correctly', () => {\n // https://solscan.io/tx/FQNxV3NQHf6JBzYkaaWaRVj3eAtdEVSsjdStXM9ciZmWfoeiABaG3dXqK612T3LMi3McP5hf967AgJByvRkkRJY\n const tx = getTxBySig(\n 'FQNxV3NQHf6JBzYkaaWaRVj3eAtdEVSsjdStXM9ciZmWfoeiABaG3dXqK612T3LMi3McP5hf967AgJByvRkkRJY',\n );\n\n const signerMatch: TransactionFilter = {\n signerAccountKey: '3j1iDNRseKJVEWAb62Xxn74mVjJ7sUTVJaaBNb3gKtUe',\n };\n expect(filterTransactionsProcessor(tx!, signerMatch)).toBeTruthy();\n\n const signerMismatch: TransactionFilter = {\n signerAccountKey: '7yYGUXSY9hSa3MqmU7t4acCMBzSQyjxZyoRC1bDKMKJh',\n };\n expect(filterTransactionsProcessor(tx!, signerMismatch)).toBeFalsy();\n });\n\n describe('instructions', () => {\n it('can filter failed instructions', () => {\n const failedTx = block.block.transactions.find((tx) => tx.meta?.err);\n const failedInst = failedTx!.transaction.message.instructions[0];\n expect(\n filterInstructionsProcessor(failedInst, solanaApi.decoder, {\n includeFailed: true,\n }),\n ).toBeTruthy();\n expect(\n filterInstructionsProcessor(failedInst, solanaApi.decoder, {\n includeFailed: false,\n }),\n ).toBeFalsy();\n });\n\n it('can filter programIds', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n const inst = tx?.transaction.message.instructions[4];\n\n expect(inst).toBeDefined();\n\n // A program called by this instruction\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n programId: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8',\n }),\n ).toBe(true);\n\n // A program not called by this instruction\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n }),\n ).toBe(false);\n });\n\n it.each([\n // ['human', 'swap', true], // TODO wrong IDL currently\n ['hex', '0x09', true],\n ['base58', 'A', true],\n ['human', 'shutdown', false],\n ['hex', '0x74ce1bbfa6130049', false],\n ['base58', 'kPf6M86k1NDLT', false],\n ])(\n 'should correctly match discrminators in %s format',\n (_, discriminator, result) => {\n // TODO wrong IDL currently\n solanaApi.decoder.idls[\n '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'\n ] = IDL_swap;\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n const inst = tx?.transaction.message.instructions[4];\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n programId: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8',\n discriminator,\n }),\n ).toBe(result);\n },\n );\n\n it('can filter accounts', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n const inst = tx?.transaction.message.instructions[4];\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n accounts: [null, ['6fuLRV8aLJF96MaNi44bLJUhaSJu1yzc588kHM4DfG2W']],\n }),\n ).toBe(true);\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n accounts: [\n null,\n null,\n ['6fuLRV8aLJF96MaNi44bLJUhaSJu1yzc588kHM4DfG2W'], // Out of position\n ],\n }),\n ).toBe(false);\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n accounts: [null, null, []],\n }),\n ).toBe(false);\n\n expect(\n filterInstructionsProcessor(inst!, solanaApi.decoder, {\n accounts: [\n null,\n [\n '6fuLRV8aLJF96MaNi44bLJUhaSJu1yzc588kHM4DfG2W',\n '5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1',\n ], // Out of position\n ],\n }),\n ).toBe(true);\n });\n });\n\n describe('logs', () => {\n it('should filter logs by program Id', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n\n const log = tx!.meta!.logs![1];\n expect(log).toBeDefined();\n // Matching program id\n expect(\n filterLogsProcessor(log, {\n programId: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8',\n }),\n ).toBe(true);\n\n // non-matching programId\n expect(\n filterLogsProcessor(log, {\n programId: '5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1',\n }),\n ).toBe(false);\n });\n });\n });\n\n describe('Block parsing', () => {\n it('makes instructions that have a transaction property', () => {\n const tx = getTxBySig(\n 'FQNxV3NQHf6JBzYkaaWaRVj3eAtdEVSsjdStXM9ciZmWfoeiABaG3dXqK612T3LMi3McP5hf967AgJByvRkkRJY',\n );\n\n for (const instruction of tx!.transaction.message.instructions) {\n expect(instruction.transaction).toBeDefined();\n }\n\n for (const innerInstruction of tx!.meta!.innerInstructions) {\n for (const instruction of innerInstruction.instructions) {\n expect(instruction.transaction).toBeDefined();\n }\n }\n });\n\n it('corretly parses logs', () => {\n const tx = getTxBySig(\n '4vGc5nP4W7VZe7SmSb2GsJMG3KJijZJ4KGHUCQ14FmqfPsyDotn7kwR5nA13PpzjwT732ggiLuDGs5PDpjRCKsC6',\n );\n expect(tx!.meta!.logs).toBeDefined();\n expect(tx!.meta!.logs!.length).toBeGreaterThan(0);\n\n // Tx with data logs\n const txWData = getTxBySig(\n 'qtUujQqx16ChZRMG4TE9eNMp4th3GxLvuuCQBEXK4KYyjqfAAPbP6xejA2ZTUe7X1cZYiHCnJHpC5v6GRctYc8c',\n );\n expect(txWData!.meta!.logs).toBeDefined();\n expect(txWData!.meta!.logs!.length).toBeGreaterThan(0);\n\n // Tx with a failure\n const txWError = getTxBySig(\n '8q3z3WoYUcA8UQLYgdgriGCZrGJUAYoeUwTJaVuuq43AmKLQxKLAMxuEAWXMquozVXEX4eL91r3jxKFVifmeXrv',\n );\n expect(txWError!.meta!.logs).toBeDefined();\n expect(txWError!.meta!.logs!.length).toBeGreaterThan(0);\n });\n\n it('can parse a block with a transaction that has \"null\" innerTransactions', async () => {\n // The problem transaction: https://solscan.io/tx/3mSAfK9hm4wgMw5kzKpVz73viBftapNLwECN9rmG5Q6qWPyARognZsyoosB4XjYf5nFRtcEmrKGVgLGLRN7tnmWN?cluster=devnet\n const solanaApi = await SolanaApi.create(\n 'https://api.devnet.solana.com',\n eventEmitter,\n decoder,\n );\n\n const block = await solanaApi.fetchBlock(405433240);\n\n expect(block).toBeDefined();\n\n expect(\n getTxBySig(\n '3mSAfK9hm4wgMw5kzKpVz73viBftapNLwECN9rmG5Q6qWPyARognZsyoosB4XjYf5nFRtcEmrKGVgLGLRN7tnmWN',\n block,\n ),\n ).toBeDefined();\n });\n });\n\n // Tests that data types can be stringified, this is important to test because of circular references\n describe('JSON serialization', () => {\n it('can stringify a SolanaBlock', () => {\n expect(() => JSON.stringify(block)).not.toThrow();\n });\n\n it('can stringify a SolanaTransaction', () => {\n const tx = getTxBySig(\n '4vGc5nP4W7VZe7SmSb2GsJMG3KJijZJ4KGHUCQ14FmqfPsyDotn7kwR5nA13PpzjwT732ggiLuDGs5PDpjRCKsC6',\n );\n\n expect(tx).toBeDefined();\n expect(() => JSON.stringify(tx)).not.toThrow();\n });\n\n it('can stringify a SolanaInstruction', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n const inst = tx?.transaction.message.instructions[4];\n expect(inst).toBeDefined();\n\n const decodeInst = jest.spyOn(solanaApi.decoder, 'decodeInstruction');\n expect(() => JSON.stringify(inst)).not.toThrow();\n expect(decodeInst).not.toHaveBeenCalled();\n });\n\n it('can stringify a LogMessage', () => {\n const tx = getTxBySig(\n '4V5S9ymSheic34SsHN9AHA86b41qXfA9JwdEra1UUgoNdvWFTMA5ueSCHn6nRTBDphMQFUFLPgU4N2QsG8En3J1d',\n );\n\n for (const log of tx!.meta!.logs!) {\n const decodeLog = jest.spyOn(solanaApi.decoder, 'decodeLog');\n expect(() => JSON.stringify(log)).not.toThrow();\n expect(decodeLog).not.toHaveBeenCalled();\n }\n });\n });\n});\n"]}
|
|
@@ -166,7 +166,7 @@ function transformBlock(block, decoder) {
|
|
|
166
166
|
meta: tx.meta
|
|
167
167
|
? {
|
|
168
168
|
...tx.meta,
|
|
169
|
-
innerInstructions: tx.meta.innerInstructions.map((innerInstruction) => ({
|
|
169
|
+
innerInstructions: (tx.meta.innerInstructions ?? []).map((innerInstruction) => ({
|
|
170
170
|
...innerInstruction,
|
|
171
171
|
instructions: innerInstruction.instructions.map((instruction, innerIndex) => wrapInstruction([innerInstruction.index, innerIndex], instruction, tx, baseBlock, decoder)),
|
|
172
172
|
})),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block.solana.js","sourceRoot":"","sources":["../../src/solana/block.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 type {\n UnixTimestamp,\n Blockhash,\n Slot,\n TransactionForFullJson,\n} from '@solana/rpc-types';\nimport { getLogger, type Header, type IBlock } from '@subql/node-core';\nimport type {\n SolanaBlock,\n BaseSolanaBlock,\n SolanaInstruction,\n DecodedData,\n SolanaLogMessage,\n} from '@subql/types-solana';\nimport { SolanaDecoder } from './decoder';\n\nconst logger = getLogger('SolanaBlock');\n\ntype RawSolanaBlock = Readonly<{\n /** The number of blocks beneath this block */\n blockHeight: bigint;\n /** Estimated production time, as Unix timestamp */\n blockTime: UnixTimestamp;\n /** the blockhash of this block */\n blockhash: Blockhash;\n /** The slot index of this block's parent */\n parentSlot: Slot;\n /** The blockhash of this block's parent */\n previousBlockhash: Blockhash;\n\n transactions: readonly TransactionForFullJson<0>[];\n}>;\n\n// We use this function to omit properties without accessing getters\nfunction omit<T>(input: T, omit: (keyof T)[]) {\n const json: Record<string, any> = {};\n\n for (const key of Object.getOwnPropertyNames(input)) {\n if (!omit.includes(key as keyof T)) {\n json[key] = (input as any)[key];\n }\n }\n\n return json;\n}\n\nfunction wrapInstruction(\n index: number[],\n instruction: Omit<\n SolanaInstruction,\n 'index' | 'block' | 'transaction' | 'decodedData'\n >,\n transaction: TransactionForFullJson<0>,\n block: BaseSolanaBlock,\n decoder: SolanaDecoder,\n): SolanaInstruction {\n let pendingDecode: Promise<DecodedData | null>;\n // XXX if we make this fully circular toJSON will need to be added to omit the transaction on the instruction\n const res = {\n ...instruction,\n index,\n transaction,\n block,\n get decodedData(): Promise<DecodedData | null> {\n pendingDecode ??= decoder.decodeInstruction(this);\n return pendingDecode;\n },\n };\n\n // Implement this in order to calculate block size\n (res as any).toJSON = () => {\n return omit(res, ['block', 'decodedData', 'transaction']);\n };\n\n return res;\n}\n\nexport function wrapLogs(\n logs: readonly string[] | null,\n decoder: SolanaDecoder,\n): SolanaLogMessage[] | null {\n if (logs === null) {\n return null;\n }\n const res: SolanaLogMessage[] = [];\n\n // Keep a stack of the instruction programs\n const instructionPath: string[] = [];\n\n for (const [idx, log] of Object.entries(logs)) {\n let pendingDecode: Promise<DecodedData | null>;\n if (log.startsWith('Program log:')) {\n res.push({\n message: log,\n programId: instructionPath[instructionPath.length - 1],\n logIndex: parseInt(idx, 10),\n type: 'log',\n decodedMessage: Promise.resolve(null),\n });\n } else if (log.startsWith('Program data:')) {\n res.push({\n message: log,\n programId: instructionPath[instructionPath.length - 1],\n logIndex: parseInt(idx, 10),\n type: 'data',\n get decodedMessage(): Promise<DecodedData | null> {\n pendingDecode ??= decoder.decodeLog(this);\n return pendingDecode;\n }, // TODO getter function to parse\n });\n } else if (log.startsWith('Program return:')) {\n res.push({\n message: log,\n programId: instructionPath[instructionPath.length - 1],\n logIndex: parseInt(idx, 10),\n type: 'other',\n get decodedMessage(): Promise<DecodedData | null> {\n pendingDecode ??= decoder.decodeLog(this);\n return pendingDecode;\n }, // TODO getter function to parse, can return data be dcoded?\n });\n } else if (log.startsWith('Program consumption:')) {\n // DO nothing\n } else if (log.startsWith('Program')) {\n const [, /* \"Program\"*/ programAddress, mode, ...rest] = log.split(' '); // TODO doesn't work with compute units\n switch (mode) {\n case 'invoke':\n instructionPath.push(programAddress);\n break;\n case 'success':\n // TODO need to check this is always the last item\n instructionPath.pop();\n break;\n case 'consumed':\n // Do nothing\n break;\n case 'failed:':\n // TODO\n instructionPath.pop();\n break;\n default:\n throw new Error(`Unknown log mode: ${mode}, log: ${log}`);\n }\n } else {\n /**\n * Known examples (prefixes):\n * * Transfer\n * * Create Account\n * * Allocate\n * * Instruction references an unknown account\n * */\n\n logger.warn(`Unable to parse log message: ${log}`);\n }\n }\n\n // Implement this in order to calculate block size\n res.forEach((r) => {\n (r as any).toJSON = () => {\n return omit(r, ['decodedMessage']);\n };\n });\n\n return res;\n}\n\ntype DictionaryLog = {\n message: string;\n logIndex: number;\n programId: string;\n kind: 'data' | 'log' | 'other';\n};\n\nfunction wrapDictionaryLogs(\n logs: DictionaryLog[],\n decoder: SolanaDecoder,\n): SolanaLogMessage[] {\n return logs.map((l) => {\n let pendingDecode: Promise<DecodedData | null>;\n const res = {\n message: l.message,\n programId: l.programId,\n logIndex: l.logIndex,\n type: l.kind,\n get decodedMessage() {\n if (!['other', 'data'].includes(l.kind)) {\n return Promise.resolve(null);\n }\n\n pendingDecode ??= decoder.decodeLog(this);\n return pendingDecode;\n },\n };\n\n // Implement this in order to calculate block size\n (res as any).toJSON = () => {\n return omit(res, ['decodedMessage']);\n };\n\n return res;\n });\n}\n\n/**\n * Transforms a block from a raw response to the types injected into handlers*/\nexport function transformBlock(\n block: RawSolanaBlock,\n decoder: SolanaDecoder,\n): SolanaBlock {\n const { transactions, ...baseBlock } = block;\n return {\n ...baseBlock,\n transactions: transactions.map((tx) => {\n try {\n return {\n ...tx,\n block: baseBlock,\n transaction: {\n ...tx.transaction,\n message: {\n ...tx.transaction.message,\n instructions: tx.transaction.message.instructions.map(\n (instruction, index) =>\n wrapInstruction([index], instruction, tx, baseBlock, decoder),\n ),\n },\n },\n meta: tx.meta\n ? {\n ...tx.meta,\n innerInstructions: tx.meta.innerInstructions.map(\n (innerInstruction) => ({\n ...innerInstruction,\n instructions: innerInstruction.instructions.map(\n (instruction, innerIndex) =>\n wrapInstruction(\n [innerInstruction.index, innerIndex],\n instruction,\n tx,\n baseBlock,\n decoder,\n ),\n ),\n }),\n ),\n // Dictionary blocks have logs instead of logMessages that are already somewhat wrapped\n logs: (tx.meta as any).logs\n ? wrapDictionaryLogs((tx.meta as any).logs, decoder)\n : wrapLogs(tx.meta.logMessages, decoder),\n }\n : null,\n };\n } catch (e) {\n throw new Error(\n `Failed to transform transaction: ${tx.transaction.signatures[0]}`,\n { cause: e },\n );\n }\n }),\n };\n}\n\nexport function formatBlockUtil<B extends SolanaBlock = SolanaBlock>(\n block: B,\n): IBlock<B> {\n return {\n block,\n getHeader: () => solanaBlockToHeader(block),\n };\n}\n\nexport function solanaBlockToHeader(block: BaseSolanaBlock): Header {\n return {\n blockHeight: Number(block.parentSlot) + 1, // The blocks don't include the slot because they assume you know that when making the request\n blockHash: block.blockhash,\n parentHash: block.previousBlockhash,\n timestamp: new Date(Number(block.blockTime) * 1000),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"block.solana.js","sourceRoot":"","sources":["../../src/solana/block.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 type {\n UnixTimestamp,\n Blockhash,\n Slot,\n TransactionForFullJson,\n} from '@solana/rpc-types';\nimport { getLogger, type Header, type IBlock } from '@subql/node-core';\nimport type {\n SolanaBlock,\n BaseSolanaBlock,\n SolanaInstruction,\n DecodedData,\n SolanaLogMessage,\n} from '@subql/types-solana';\nimport { SolanaDecoder } from './decoder';\n\nconst logger = getLogger('SolanaBlock');\n\ntype RawSolanaBlock = Readonly<{\n /** The number of blocks beneath this block */\n blockHeight: bigint;\n /** Estimated production time, as Unix timestamp */\n blockTime: UnixTimestamp;\n /** the blockhash of this block */\n blockhash: Blockhash;\n /** The slot index of this block's parent */\n parentSlot: Slot;\n /** The blockhash of this block's parent */\n previousBlockhash: Blockhash;\n\n transactions: readonly TransactionForFullJson<0>[];\n}>;\n\n// We use this function to omit properties without accessing getters\nfunction omit<T>(input: T, omit: (keyof T)[]) {\n const json: Record<string, any> = {};\n\n for (const key of Object.getOwnPropertyNames(input)) {\n if (!omit.includes(key as keyof T)) {\n json[key] = (input as any)[key];\n }\n }\n\n return json;\n}\n\nfunction wrapInstruction(\n index: number[],\n instruction: Omit<\n SolanaInstruction,\n 'index' | 'block' | 'transaction' | 'decodedData'\n >,\n transaction: TransactionForFullJson<0>,\n block: BaseSolanaBlock,\n decoder: SolanaDecoder,\n): SolanaInstruction {\n let pendingDecode: Promise<DecodedData | null>;\n // XXX if we make this fully circular toJSON will need to be added to omit the transaction on the instruction\n const res = {\n ...instruction,\n index,\n transaction,\n block,\n get decodedData(): Promise<DecodedData | null> {\n pendingDecode ??= decoder.decodeInstruction(this);\n return pendingDecode;\n },\n };\n\n // Implement this in order to calculate block size\n (res as any).toJSON = () => {\n return omit(res, ['block', 'decodedData', 'transaction']);\n };\n\n return res;\n}\n\nexport function wrapLogs(\n logs: readonly string[] | null,\n decoder: SolanaDecoder,\n): SolanaLogMessage[] | null {\n if (logs === null) {\n return null;\n }\n const res: SolanaLogMessage[] = [];\n\n // Keep a stack of the instruction programs\n const instructionPath: string[] = [];\n\n for (const [idx, log] of Object.entries(logs)) {\n let pendingDecode: Promise<DecodedData | null>;\n if (log.startsWith('Program log:')) {\n res.push({\n message: log,\n programId: instructionPath[instructionPath.length - 1],\n logIndex: parseInt(idx, 10),\n type: 'log',\n decodedMessage: Promise.resolve(null),\n });\n } else if (log.startsWith('Program data:')) {\n res.push({\n message: log,\n programId: instructionPath[instructionPath.length - 1],\n logIndex: parseInt(idx, 10),\n type: 'data',\n get decodedMessage(): Promise<DecodedData | null> {\n pendingDecode ??= decoder.decodeLog(this);\n return pendingDecode;\n }, // TODO getter function to parse\n });\n } else if (log.startsWith('Program return:')) {\n res.push({\n message: log,\n programId: instructionPath[instructionPath.length - 1],\n logIndex: parseInt(idx, 10),\n type: 'other',\n get decodedMessage(): Promise<DecodedData | null> {\n pendingDecode ??= decoder.decodeLog(this);\n return pendingDecode;\n }, // TODO getter function to parse, can return data be dcoded?\n });\n } else if (log.startsWith('Program consumption:')) {\n // DO nothing\n } else if (log.startsWith('Program')) {\n const [, /* \"Program\"*/ programAddress, mode, ...rest] = log.split(' '); // TODO doesn't work with compute units\n switch (mode) {\n case 'invoke':\n instructionPath.push(programAddress);\n break;\n case 'success':\n // TODO need to check this is always the last item\n instructionPath.pop();\n break;\n case 'consumed':\n // Do nothing\n break;\n case 'failed:':\n // TODO\n instructionPath.pop();\n break;\n default:\n throw new Error(`Unknown log mode: ${mode}, log: ${log}`);\n }\n } else {\n /**\n * Known examples (prefixes):\n * * Transfer\n * * Create Account\n * * Allocate\n * * Instruction references an unknown account\n * */\n\n logger.warn(`Unable to parse log message: ${log}`);\n }\n }\n\n // Implement this in order to calculate block size\n res.forEach((r) => {\n (r as any).toJSON = () => {\n return omit(r, ['decodedMessage']);\n };\n });\n\n return res;\n}\n\ntype DictionaryLog = {\n message: string;\n logIndex: number;\n programId: string;\n kind: 'data' | 'log' | 'other';\n};\n\nfunction wrapDictionaryLogs(\n logs: DictionaryLog[],\n decoder: SolanaDecoder,\n): SolanaLogMessage[] {\n return logs.map((l) => {\n let pendingDecode: Promise<DecodedData | null>;\n const res = {\n message: l.message,\n programId: l.programId,\n logIndex: l.logIndex,\n type: l.kind,\n get decodedMessage() {\n if (!['other', 'data'].includes(l.kind)) {\n return Promise.resolve(null);\n }\n\n pendingDecode ??= decoder.decodeLog(this);\n return pendingDecode;\n },\n };\n\n // Implement this in order to calculate block size\n (res as any).toJSON = () => {\n return omit(res, ['decodedMessage']);\n };\n\n return res;\n });\n}\n\n/**\n * Transforms a block from a raw response to the types injected into handlers*/\nexport function transformBlock(\n block: RawSolanaBlock,\n decoder: SolanaDecoder,\n): SolanaBlock {\n const { transactions, ...baseBlock } = block;\n return {\n ...baseBlock,\n transactions: transactions.map((tx) => {\n try {\n return {\n ...tx,\n block: baseBlock,\n transaction: {\n ...tx.transaction,\n message: {\n ...tx.transaction.message,\n instructions: tx.transaction.message.instructions.map(\n (instruction, index) =>\n wrapInstruction([index], instruction, tx, baseBlock, decoder),\n ),\n },\n },\n meta: tx.meta\n ? {\n ...tx.meta,\n innerInstructions: (tx.meta.innerInstructions ?? []).map(\n (innerInstruction) => ({\n ...innerInstruction,\n instructions: innerInstruction.instructions.map(\n (instruction, innerIndex) =>\n wrapInstruction(\n [innerInstruction.index, innerIndex],\n instruction,\n tx,\n baseBlock,\n decoder,\n ),\n ),\n }),\n ),\n // Dictionary blocks have logs instead of logMessages that are already somewhat wrapped\n logs: (tx.meta as any).logs\n ? wrapDictionaryLogs((tx.meta as any).logs, decoder)\n : wrapLogs(tx.meta.logMessages, decoder),\n }\n : null,\n };\n } catch (e) {\n throw new Error(\n `Failed to transform transaction: ${tx.transaction.signatures[0]}`,\n { cause: e },\n );\n }\n }),\n };\n}\n\nexport function formatBlockUtil<B extends SolanaBlock = SolanaBlock>(\n block: B,\n): IBlock<B> {\n return {\n block,\n getHeader: () => solanaBlockToHeader(block),\n };\n}\n\nexport function solanaBlockToHeader(block: BaseSolanaBlock): Header {\n return {\n blockHeight: Number(block.parentSlot) + 1, // The blocks don't include the slot because they assume you know that when making the request\n blockHash: block.blockhash,\n parentHash: block.previousBlockhash,\n timestamp: new Date(Number(block.blockTime) * 1000),\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subql/node-solana",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.2-0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Ian He",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -72,5 +72,6 @@
|
|
|
72
72
|
"README.md",
|
|
73
73
|
"CHANGELOG.md",
|
|
74
74
|
"LICENSE"
|
|
75
|
-
]
|
|
75
|
+
],
|
|
76
|
+
"stableVersion": "6.1.1"
|
|
76
77
|
}
|