UNPKG

@magiceden/magiceden-sdk

Version:

A TypeScript SDK for interacting with Magic Eden's API across multiple chains.

339 lines (338 loc) 16.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const solana_1 = require("../../../services/nft/solana"); const solana_2 = require("../../../mappers/nft/solana"); const solana_3 = require("../../../adapters/transactions/solana"); const v2_1 = require("../../../api/clients/v2"); const types_1 = require("../../../types"); // Mock dependencies jest.mock('../../../mappers/nft/solana'); jest.mock('../../../adapters/transactions/solana'); jest.mock('../../../api/clients/v2'); describe('SolanaNftService V2', () => { let service; let mockWallet; let mockV2ApiClient; let mockTransaction; let mockApiResponse; beforeEach(() => { // Reset mocks jest.clearAllMocks(); // Create mock transaction mockTransaction = { /* mock transaction object */ serialize: jest.fn().mockReturnValue(new Uint8Array([1, 2, 3])), }; // Create mock API response mockApiResponse = { v0: { txSigned: { type: 'Buffer', data: [1, 2, 3], }, }, }; // Create mock wallet mockWallet = { getAddress: jest.fn().mockReturnValue('mock-address'), signAndSendTransaction: jest.fn().mockResolvedValue('mock-signature'), waitForTransactionConfirmation: jest.fn().mockResolvedValue({ txId: 'mock-signature', status: 'confirmed', }), }; // Create service instance service = new solana_1.SolanaNftService({ chain: types_1.ChainType.SOLANA, apiKey: 'test-api-key', wallet: mockWallet, }); // Get mock API client instance mockV2ApiClient = v2_1.V2ApiClient.mock .instances[0]; // Setup default mock implementations solana_3.SolanaTransactionAdapters.fromInstructionsResponse.mockReturnValue([ mockTransaction, ]); }); describe('list', () => { it('should map parameters, call API, and sign transaction', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenAccount: 'mockTokenAccount', expiry: 1234567890, }; const mockApiRequest = { tokenMint: 'mockTokenMint' /* other fields */ }; // Setup mock implementations solana_2.SolanaApiMappers.v2.listRequest.mockReturnValue(mockApiRequest); mockV2ApiClient.list.mockResolvedValue(mockApiResponse); // Call the method const result = await service.list(mockParams); // Verify the flow expect(solana_2.SolanaApiMappers.v2.listRequest).toHaveBeenCalledWith(mockParams); expect(mockV2ApiClient.list).toHaveBeenCalledWith(mockApiRequest); expect(solana_3.SolanaTransactionAdapters.fromInstructionsResponse).toHaveBeenCalledWith(mockApiResponse); expect(mockWallet.signAndSendTransaction).toHaveBeenCalledWith(mockTransaction); expect(result).toEqual([{ txId: 'mock-signature', status: 'confirmed' }]); }); it('should handle API errors', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenAccount: 'mockTokenAccount', expiry: 1234567890, }; // Setup mock to throw error mockV2ApiClient.list.mockRejectedValue(new Error('API error')); // Call the method and expect it to throw await expect(service.list(mockParams)).rejects.toThrow('API error'); }); it('should handle wallet errors', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenAccount: 'mockTokenAccount', expiry: 1234567890, }; // Setup wallet to throw error mockWallet.signAndSendTransaction.mockRejectedValue(new Error('Wallet error')); // Call the method and expect it to throw await expect(service.list(mockParams)).rejects.toThrow('Wallet error'); }); }); describe('cancelListing', () => { it('should map parameters, call API, and sign transaction', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenAccount: 'mockTokenAccount', expiry: 1234567890, }; const mockApiRequest = { tokenMint: 'mockTokenMint' /* other fields */ }; // Setup mock implementations solana_2.SolanaApiMappers.v2.cancelListingRequest.mockReturnValue(mockApiRequest); mockV2ApiClient.cancelListing.mockResolvedValue(mockApiResponse); // Call the method const result = await service.cancelListing(mockParams); // Verify the flow expect(solana_2.SolanaApiMappers.v2.cancelListingRequest).toHaveBeenCalledWith(mockParams); expect(mockV2ApiClient.cancelListing).toHaveBeenCalledWith(mockApiRequest); expect(solana_3.SolanaTransactionAdapters.fromInstructionsResponse).toHaveBeenCalledWith(mockApiResponse); expect(mockWallet.signAndSendTransaction).toHaveBeenCalledWith(mockTransaction); expect(result).toEqual([{ txId: 'mock-signature', status: 'confirmed' }]); }); }); describe('makeItemOffer', () => { it('should map parameters, call API, and sign transaction', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', buyer: 'mockBuyer', auctionHouseAddress: 'mockAuctionHouse', expiry: 1234567890, }; const mockApiRequest = { tokenMint: 'mockTokenMint' /* other fields */ }; // Setup mock implementations solana_2.SolanaApiMappers.v2.makeItemOfferRequest.mockReturnValue(mockApiRequest); mockV2ApiClient.makeItemOffer.mockResolvedValue(mockApiResponse); // Call the method const result = await service.makeItemOffer(mockParams); // Verify the flow expect(solana_2.SolanaApiMappers.v2.makeItemOfferRequest).toHaveBeenCalledWith(mockParams); expect(mockV2ApiClient.makeItemOffer).toHaveBeenCalledWith(mockApiRequest); expect(solana_3.SolanaTransactionAdapters.fromInstructionsResponse).toHaveBeenCalledWith(mockApiResponse); expect(mockWallet.signAndSendTransaction).toHaveBeenCalledWith(mockTransaction); expect(result).toEqual([{ txId: 'mock-signature', status: 'confirmed' }]); }); }); describe('cancelItemOffer', () => { it('should map parameters, call API, and sign transaction', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', buyer: 'mockBuyer', auctionHouseAddress: 'mockAuctionHouse', expiry: 1234567890, }; const mockApiRequest = { tokenMint: 'mockTokenMint' /* other fields */ }; // Setup mock implementations solana_2.SolanaApiMappers.v2.cancelItemOfferRequest.mockReturnValue(mockApiRequest); mockV2ApiClient.cancelItemOffer.mockResolvedValue(mockApiResponse); // Call the method const result = await service.cancelItemOffer(mockParams); // Verify the flow expect(solana_2.SolanaApiMappers.v2.cancelItemOfferRequest).toHaveBeenCalledWith(mockParams); expect(mockV2ApiClient.cancelItemOffer).toHaveBeenCalledWith(mockApiRequest); expect(solana_3.SolanaTransactionAdapters.fromInstructionsResponse).toHaveBeenCalledWith(mockApiResponse); expect(mockWallet.signAndSendTransaction).toHaveBeenCalledWith(mockTransaction); expect(result).toEqual([{ txId: 'mock-signature', status: 'confirmed' }]); }); }); describe('takeItemOffer', () => { it('should map parameters, call API, and sign transaction', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', buyer: 'mockBuyer', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenATA: 'mockTokenATA', price: '1000000000', newPrice: '1100000000', buyerExpiry: 1234567890, sellerExpiry: 1234567891, }; const mockApiRequest = { tokenMint: 'mockTokenMint' /* other fields */ }; // Setup mock implementations solana_2.SolanaApiMappers.v2.takeItemOfferRequest.mockReturnValue(mockApiRequest); mockV2ApiClient.takeItemOffer.mockResolvedValue(mockApiResponse); // Call the method const result = await service.takeItemOffer(mockParams); // Verify the flow expect(solana_2.SolanaApiMappers.v2.takeItemOfferRequest).toHaveBeenCalledWith(mockParams); expect(mockV2ApiClient.takeItemOffer).toHaveBeenCalledWith(mockApiRequest); expect(solana_3.SolanaTransactionAdapters.fromInstructionsResponse).toHaveBeenCalledWith(mockApiResponse); expect(mockWallet.signAndSendTransaction).toHaveBeenCalledWith(mockTransaction); expect(result).toEqual([{ txId: 'mock-signature', status: 'confirmed' }]); }); }); describe('buy', () => { it('should map parameters, call API, and sign transaction', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', buyer: 'mockBuyer', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenATA: 'mockTokenATA', price: '1000000000', sellerExpiry: 1234567891, }; const mockApiRequest = { tokenMint: 'mockTokenMint' /* other fields */ }; // Setup mock implementations solana_2.SolanaApiMappers.v2.buyRequest.mockReturnValue(mockApiRequest); mockV2ApiClient.buy.mockResolvedValue(mockApiResponse); // Call the method const result = await service.buy(mockParams); // Verify the flow expect(solana_2.SolanaApiMappers.v2.buyRequest).toHaveBeenCalledWith(mockParams); expect(mockV2ApiClient.buy).toHaveBeenCalledWith(mockApiRequest); expect(solana_3.SolanaTransactionAdapters.fromInstructionsResponse).toHaveBeenCalledWith(mockApiResponse); expect(mockWallet.signAndSendTransaction).toHaveBeenCalledWith(mockTransaction); expect(result).toEqual([{ txId: 'mock-signature', status: 'confirmed' }]); }); }); describe('transfer', () => { it('should map parameters, call API, and sign transaction', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', from: 'mockFrom', to: 'mockTo', }; const mockApiRequest = { mint: 'mockTokenMint' /* other fields */ }; // Setup mock implementations solana_2.SolanaApiMappers.v2.transferRequest.mockReturnValue(mockApiRequest); mockV2ApiClient.transfer.mockResolvedValue(mockApiResponse); // Call the method const result = await service.transfer(mockParams); // Verify the flow expect(solana_2.SolanaApiMappers.v2.transferRequest).toHaveBeenCalledWith(mockParams); expect(mockV2ApiClient.transfer).toHaveBeenCalledWith(mockApiRequest); expect(solana_3.SolanaTransactionAdapters.fromInstructionsResponse).toHaveBeenCalledWith(mockApiResponse); expect(mockWallet.signAndSendTransaction).toHaveBeenCalledWith(mockTransaction); expect(result).toEqual([{ txId: 'mock-signature', status: 'confirmed' }]); }); }); describe('error handling', () => { it('should handle adapter errors', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenAccount: 'mockTokenAccount', expiry: 1234567890, }; // Setup adapter to throw error solana_3.SolanaTransactionAdapters.fromInstructionsResponse.mockImplementation(() => { throw new Error('Adapter error'); }); // Call the method and expect it to throw await expect(service.list(mockParams)).rejects.toThrow('Adapter error'); }); it('should handle mapper errors', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenAccount: 'mockTokenAccount', expiry: 1234567890, }; // Setup mapper to throw error solana_2.SolanaApiMappers.v2.listRequest.mockImplementation(() => { throw new Error('Invalid transaction response format'); }); // Call the method and expect it to throw await expect(service.list(mockParams)).rejects.toThrow('Invalid transaction response format'); }); }); describe('edge cases', () => { it('should handle empty transaction response', async () => { // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenAccount: 'mockTokenAccount', expiry: 1234567890, }; // Setup API to return empty response mockV2ApiClient.list.mockResolvedValue({}); // Setup adapter to throw for empty response solana_3.SolanaTransactionAdapters.fromInstructionsResponse.mockImplementation(() => { throw new Error('Invalid transaction response format'); }); // Call the method and expect it to throw await expect(service.list(mockParams)).rejects.toThrow('Invalid transaction response format'); }); it('should handle null wallet', async () => { // Create service with null wallet service = new solana_1.SolanaNftService({ chain: types_1.ChainType.SOLANA, apiKey: 'test-api-key', wallet: null, }); // Setup mocks const mockParams = { token: 'mockTokenMint', price: '1000000000', seller: 'mockSeller', auctionHouseAddress: 'mockAuctionHouse', tokenAccount: 'mockTokenAccount', expiry: 1234567890, }; // Call the method and expect it to throw await expect(service.list(mockParams)).rejects.toThrow(); }); }); });