UNPKG

@ledgerhq/coin-filecoin

Version:
219 lines (179 loc) 6.48 kB
import { getEnv } from "@ledgerhq/live-env"; import network from "@ledgerhq/live-network"; import { createMockBalanceResponse, createMockEstimatedFeesResponse, createMockTransactionResponse, createMockERC20Transfer, TEST_ADDRESSES, TEST_TRANSACTION_HASHES, TEST_BLOCK_HEIGHTS, } from "../test/fixtures"; import { fetchBalances, fetchEstimatedFees, fetchBlockHeight, fetchTxs, fetchTxsWithPages, broadcastTx, fetchERC20TokenBalance, fetchERC20TransactionsWithPages, } from "../network/api"; // Mock dependencies jest.mock("@ledgerhq/logs"); jest.mock("@ledgerhq/live-network/network"); jest.mock("@ledgerhq/live-env"); const MOCK_API_URL = "https://mock.filecoin.api"; const mockedNetwork = network as jest.MockedFunction<typeof network>; const mockedGetEnv = getEnv as jest.MockedFunction<typeof getEnv>; describe("Filecoin API", () => { beforeEach(() => { jest.clearAllMocks(); jest.resetAllMocks(); mockedGetEnv.mockReturnValue(MOCK_API_URL); }); describe("fetchBalances", () => { it("should fetch balance for a given address", async () => { const mockBalance = createMockBalanceResponse({ total_balance: "1000000000000000000", spendable_balance: "900000000000000000", locked_balance: "100000000000000000", }); mockedNetwork.mockResolvedValueOnce({ data: mockBalance, status: 200 }); const result = await fetchBalances(TEST_ADDRESSES.F1_ADDRESS); expect(result).toEqual(mockBalance); }); }); describe("fetchEstimatedFees", () => { it("should fetch estimated fees for a transaction", async () => { const mockFees = createMockEstimatedFeesResponse({ gas_limit: 1500000, gas_fee_cap: "150000", gas_premium: "125000", nonce: 5, }); const request = { from: TEST_ADDRESSES.F1_ADDRESS, to: TEST_ADDRESSES.RECIPIENT_F1, }; mockedNetwork.mockResolvedValueOnce({ data: mockFees, status: 200 }); const result = await fetchEstimatedFees(request); expect(result).toEqual(mockFees); }); }); describe("fetchBlockHeight", () => { it("should fetch current block height", async () => { const mockNetworkStatus = { current_block_identifier: { index: TEST_BLOCK_HEIGHTS.CURRENT, hash: "blockhash123", }, genesis_block_identifier: { index: 0, hash: "genesis", }, current_block_timestamp: Date.now(), }; mockedNetwork.mockResolvedValueOnce({ data: mockNetworkStatus, status: 200 }); const result = await fetchBlockHeight(); expect(result.current_block_identifier.index).toBe(TEST_BLOCK_HEIGHTS.CURRENT); }); }); describe("fetchTxs", () => { it("should fetch transactions from specific height", async () => { const mockResponse = { txs: [createMockTransactionResponse()], metadata: { limit: 50, offset: 10 }, }; mockedNetwork.mockResolvedValueOnce({ data: mockResponse, status: 200 }); await fetchTxs(TEST_ADDRESSES.F1_ADDRESS, 2500000, 10, 50); expect(mockedNetwork).toHaveBeenCalledWith({ method: "GET", url: expect.stringContaining("from_height=2500000&offset=10&limit=50"), }); }); }); describe("fetchTxsWithPages", () => { it("should fetch all transactions with multi-page pagination", async () => { const firstPageTxs = Array.from({ length: 1000 }, (_, i) => createMockTransactionResponse({ hash: `hash_${i}` }), ); const secondPageTxs = Array.from({ length: 500 }, (_, i) => createMockTransactionResponse({ hash: `hash_${1000 + i}` }), ); mockedNetwork .mockResolvedValueOnce({ data: { txs: firstPageTxs, metadata: {} }, status: 200 }) .mockResolvedValueOnce({ data: { txs: secondPageTxs, metadata: {} }, status: 200 }); const result = await fetchTxsWithPages(TEST_ADDRESSES.F1_ADDRESS, 0); expect(result).toHaveLength(1500); expect(mockedNetwork).toHaveBeenCalledTimes(2); }); }); describe("broadcastTx", () => { it("should broadcast a signed transaction", async () => { const mockRequest = { message: { version: 0, to: TEST_ADDRESSES.RECIPIENT_F1, from: TEST_ADDRESSES.F1_ADDRESS, nonce: 5, value: "100000000000000000", gaslimit: 1000000, gasfeecap: "100000", gaspremium: "100000", method: 0, params: "", }, signature: { type: 1, data: "signature_data_here", }, }; const mockResponse = { hash: TEST_TRANSACTION_HASHES.VALID, }; mockedNetwork.mockResolvedValueOnce({ data: mockResponse, status: 200 }); const result = await broadcastTx(mockRequest); expect(result).toEqual({ hash: "bafy2bzacedpqzd6qm2r7nvxj5oetpqvhujwwmvkhz4u3xnfzdvwzxpjzuqhpa", }); }); }); describe("fetchERC20TokenBalance", () => { it("should return 0 when no balance data is available", async () => { const mockResponse = { data: [], }; mockedNetwork.mockResolvedValueOnce({ data: mockResponse, status: 200 }); const result = await fetchERC20TokenBalance( TEST_ADDRESSES.F4_ADDRESS, TEST_ADDRESSES.ERC20_CONTRACT, ); expect(result).toBe("0"); }); }); describe("fetchERC20TransactionsWithPages", () => { it("should fetch all ERC20 transactions with pagination and sort by timestamp", async () => { const now = Math.floor(Date.now() / 1000); const firstPageTxs = Array.from({ length: 1000 }, (_, i) => createMockERC20Transfer({ id: `${i}`, timestamp: now - i, }), ); const secondPageTxs = Array.from({ length: 300 }, (_, i) => createMockERC20Transfer({ id: `${1000 + i}`, timestamp: now - 1000 - i, }), ); mockedNetwork .mockResolvedValueOnce({ data: { txs: firstPageTxs }, status: 200 }) .mockResolvedValueOnce({ data: { txs: secondPageTxs }, status: 200 }); const result = await fetchERC20TransactionsWithPages(TEST_ADDRESSES.F4_ADDRESS, 100); expect(result).toHaveLength(1300); expect(mockedNetwork).toHaveBeenCalledTimes(2); expect(result[0].timestamp).toBeGreaterThanOrEqual(result[1].timestamp); }); }); });