import { getTransaction, extractNativeSolTransferData, extractSplTokenTransferData, extractTokenTransferData } from '../utils/explorer'; // Mock the Solana connection jest.mock('@solana/web3.js', () => ({ Connection: jest.fn().mockImplementation(() => ({ getParsedTransaction: jest.fn() })) })); // Mock the data module jest.mock('../data', () => ({ CLUSTER_API: 'https://api.devnet.solana.com' })); describe('Explorer Utility Tests', () => { // Sample transaction hashes from the comments const SPL_TOKEN_TX_HASH = '2Dq3cW3D7z75QNfjiTfDu3GgS2gaqrqmoaqzDoomTkJqT2ThSyNDNf1tTz8SgXmzSon9FHCyN61EFkAdkJquhbJf'; const SOL_TRANSFER_TX_HASH = '3c6AiQmRxnAKSQyQ3C6jPoEmhGPHieQ2uJWuBQjdMA2TPXMWeGtL6PmdUGrMdojFoazq1NUQnDb9qCq1o4sxYvZ8'; // Mock transaction data for SPL token transfer const mockSplTokenTransaction = { blockTime: 1640995200, transaction: { message: { instructions: [ { program: 'spl-token', parsed: { type: 'transferChecked', info: { source: 'SourceWallet123', destination: 'DestWallet456', mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', tokenAmount: { amount: '1000000' } } } } ], recentBlockhash: 'mockBlockhash123' } } }; // Mock transaction data for native SOL transfer const mockSolTransaction = { blockTime: 1640995200, transaction: { message: { instructions: [ { program: 'system', parsed: { type: 'transfer', info: { source: 'SourceWallet789', destination: 'DestWallet012', lamports: 1000000000 } } } ], recentBlockhash: 'mockBlockhash456' } } }; // Mock transaction data for non-transfer transaction const mockNonTransferTransaction = { blockTime: 1640995200, transaction: { message: { instructions: [ { program: 'other-program', parsed: { type: 'other-action' } } ], recentBlockhash: 'mockBlockhash789' } } }; beforeEach(() => { jest.clearAllMocks(); }); describe('getTransaction', () => { it('should fetch and parse a transaction successfully', async () => { const { Connection } = require('@solana/web3.js'); const mockConnection = { getParsedTransaction: jest.fn().mockResolvedValue(mockSplTokenTransaction) }; Connection.mockImplementation(() => mockConnection); const result = await getTransaction(SPL_TOKEN_TX_HASH); expect(mockConnection.getParsedTransaction).toHaveBeenCalledWith(SPL_TOKEN_TX_HASH, { maxSupportedTransactionVersion: 0 }); expect(result).toBeDefined(); }); it('should handle connection errors gracefully', async () => { const { Connection } = require('@solana/web3.js'); const mockConnection = { getParsedTransaction: jest.fn().mockRejectedValue(new Error('Connection failed')) }; Connection.mockImplementation(() => mockConnection); await expect(getTransaction(SPL_TOKEN_TX_HASH)).rejects.toThrow('Connection failed'); }); }); describe('extractNativeSolTransferData', () => { it('should extract native SOL transfer data correctly', () => { const result = extractNativeSolTransferData(mockSolTransaction); expect(result).toEqual({ sender: 'cocD4r4yNpHxPq7CzUebxEMyLki3X4d2Y3HcTX5ptUc', receiver: 'SP13fTsRrdB2vwJBk88bddCkz4v9N1mHncmTyqkUTTp', amount: 1000000000, mint: 'So11111111111111111111111111111111111111111', time: 1755106952, blockhash: '55sznG5B254dnr4WiM1EBHDE5kUfHHyZiY7sBSGGsBYE' }); }); it('should return null for non-native SOL transfers', () => { const result = extractNativeSolTransferData(mockSplTokenTransaction); expect(result).toBeNull(); }); it('should return null for non-transfer transactions', () => { const result = extractNativeSolTransferData(mockNonTransferTransaction); expect(result).toBeNull(); }); it('should handle malformed transaction data gracefully', () => { const malformedTransaction = { transaction: { message: { instructions: [] } } }; const result = extractNativeSolTransferData(malformedTransaction); expect(result).toBeNull(); }); it('should handle errors and return null', () => { const invalidTransaction = null; const result = extractNativeSolTransferData(invalidTransaction); expect(result).toBeNull(); }); }); describe('extractSplTokenTransferData', () => { it('should extract SPL token transfer data correctly', () => { const result = extractSplTokenTransferData(mockSplTokenTransaction); expect(result).toEqual({ sender: '4aHYndCFTBAg8zCLsdTF8mWUPdSXj9NqJXdti4BBdYKP', receiver: '7jnoV3yYmaFFa3FYtpTHY4kz6wer8ntEUKZr9hmouets', amount: 1000000000000, mint: 'diNoZ1L9UEiJMv8i43BjZoPEe2tywwaBTBnKQYf28FT', time: 1755106862, blockhash: 'GvxNLLizh6oCodnuYX7NVb7xBrtTpAHDTsWMPGtSg2eV' }); }); it('should return null for non-SPL token transfers', () => { const result = extractSplTokenTransferData(mockSolTransaction); expect(result).toBeNull(); }); it('should return null for non-transfer transactions', () => { const result = extractSplTokenTransferData(mockNonTransferTransaction); expect(result).toBeNull(); }); it('should handle malformed transaction data gracefully', () => { const malformedTransaction = { transaction: { message: { instructions: [] } } }; const result = extractSplTokenTransferData(malformedTransaction); expect(result).toBeNull(); }); it('should handle errors and return null', () => { const invalidTransaction = null; const result = extractSplTokenTransferData(invalidTransaction); expect(result).toBeNull(); }); }); describe('extractTokenTransferData', () => { it('should extract native SOL transfer data when available', () => { const result = extractTokenTransferData(mockSolTransaction); expect(result).toEqual({ sender: 'SourceWallet789', receiver: 'DestWallet012', amount: 1000000000, mint: 'So11111111111111111111111111111111111111111', time: 1640995200, blockhash: 'mockBlockhash456' }); }); it('should extract SPL token transfer data when native SOL is not available', () => { const result = extractTokenTransferData(mockSplTokenTransaction); expect(result).toEqual({ sender: 'SourceWallet123', receiver: 'DestWallet456', amount: 1000000, mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', time: 1640995200, blockhash: 'mockBlockhash123' }); }); it('should return null for non-transfer transactions', () => { const result = extractTokenTransferData(mockNonTransferTransaction); expect(result).toBeNull(); }); it('should prioritize native SOL transfers over SPL token transfers', () => { // Create a transaction with both types of transfers const mixedTransaction = { blockTime: 1640995200, transaction: { message: { instructions: [ { program: 'spl-token', parsed: { type: 'transferChecked', info: { source: 'SPLSource', destination: 'SPLDest', mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', tokenAmount: { amount: '500000' } } } }, { program: 'system', parsed: { type: 'transfer', info: { source: 'SOLSource', destination: 'SOLDest', lamports: 2000000000 } } } ], recentBlockhash: 'mixedBlockhash' } } }; const result = extractTokenTransferData(mixedTransaction); // Should return native SOL transfer data (prioritized) expect(result).toEqual({ sender: 'SOLSource', receiver: 'SOLDest', amount: 2000000000, mint: 'So11111111111111111111111111111111111111111', time: 1640995200, blockhash: 'mixedBlockhash' }); }); }); describe('Integration Tests with Sample Hashes', () => { it('should handle SPL token transfer hash format', () => { // Test that the SPL token hash format is recognized expect(SPL_TOKEN_TX_HASH).toMatch(/^[A-Za-z0-9]{88}$/); }); it('should handle SOL transfer hash format', () => { // Test that the SOL transfer hash format is recognized expect(SOL_TRANSFER_TX_HASH).toMatch(/^[A-Za-z0-9]{88}$/); }); it('should process both hash types through the main function', async () => { const { Connection } = require('@solana/web3.js'); const mockConnection = { getParsedTransaction: jest.fn() .mockResolvedValueOnce(mockSplTokenTransaction) // First call for SPL token .mockResolvedValueOnce(mockSolTransaction) // Second call for SOL }; Connection.mockImplementation(() => mockConnection); // Test SPL token transaction const splResult = await getTransaction(SPL_TOKEN_TX_HASH); expect(splResult).toBeDefined(); expect(splResult?.mint).not.toBe('So11111111111111111111111111111111111111111'); // Test SOL transaction const solResult = await getTransaction(SOL_TRANSFER_TX_HASH); expect(solResult).toBeDefined(); expect(solResult?.mint).toBe('So11111111111111111111111111111111111111111'); }); }); });