UNPKG

@ledgerhq/coin-stellar

Version:
120 lines (100 loc) 3.72 kB
// SPDX-FileCopyrightText: © 2026 LEDGER SAS // SPDX-License-Identifier: Apache-2.0 import * as network from '../network' import { getBlockInfo } from './getBlockInfo' jest.mock('../network', () => ({ ...jest.requireActual<typeof import('../network')>('../network'), fetchLedgerRecord: jest.fn(), })) const fetchLedgerRecordMock = network.fetchLedgerRecord as jest.MockedFunction< typeof network.fetchLedgerRecord > describe('getBlockInfo', () => { beforeEach(() => { jest.clearAllMocks() }) it('returns block info with parent when height > 1 (uses ledger prev_hash)', async () => { fetchLedgerRecordMock.mockImplementation( async (seq: number) => ({ sequence: seq, hash: `hash-${seq}`, closed_at: `2020-01-0${seq}T00:00:00Z`, ...(seq > 1 && { prev_hash: `hash-${seq - 1}` }), }) as unknown as Awaited<ReturnType<typeof network.fetchLedgerRecord>> ) const result = await getBlockInfo(5) expect(fetchLedgerRecordMock).toHaveBeenCalledTimes(1) expect(fetchLedgerRecordMock).toHaveBeenCalledWith(5) expect(result).toEqual({ height: 5, hash: 'hash-5', time: new Date('2020-01-05T00:00:00Z'), parent: { height: 4, hash: 'hash-4' }, }) }) it('falls back to fetching parent ledger when prev_hash is missing', async () => { fetchLedgerRecordMock.mockImplementation( async (seq: number) => ({ sequence: seq, hash: `hash-${seq}`, closed_at: `2020-01-0${seq}T00:00:00Z`, }) as unknown as Awaited<ReturnType<typeof network.fetchLedgerRecord>> ) const result = await getBlockInfo(5) expect(fetchLedgerRecordMock).toHaveBeenCalledWith(5) expect(fetchLedgerRecordMock).toHaveBeenCalledWith(4) expect(fetchLedgerRecordMock).toHaveBeenCalledTimes(2) expect(result).toEqual({ height: 5, hash: 'hash-5', time: new Date('2020-01-05T00:00:00Z'), parent: { height: 4, hash: 'hash-4' }, }) }) it('omits parent for genesis ledger sequence 1', async () => { fetchLedgerRecordMock.mockResolvedValue({ sequence: 1, hash: 'genesis-hash', closed_at: '2015-09-30T00:00:00Z', } as unknown as Awaited<ReturnType<typeof network.fetchLedgerRecord>>) const result = await getBlockInfo(1) expect(fetchLedgerRecordMock).toHaveBeenCalledTimes(1) expect(fetchLedgerRecordMock).toHaveBeenCalledWith(1) expect(result.parent).toBeUndefined() expect(result.height).toBe(1) }) describe('height validation', () => { it('rejects height 0', async () => { await expect(getBlockInfo(0)).rejects.toThrow( 'getBlockInfo: height must be a positive integer, got 0' ) }) it('rejects negative height', async () => { await expect(getBlockInfo(-3)).rejects.toThrow( 'getBlockInfo: height must be a positive integer, got -3' ) }) it('rejects non-integer height', async () => { await expect(getBlockInfo(3.5)).rejects.toThrow( 'getBlockInfo: height must be a positive integer, got 3.5' ) }) it('rejects NaN', async () => { await expect(getBlockInfo(Number.NaN)).rejects.toThrow( 'getBlockInfo: height must be a positive integer, got NaN' ) }) it('rejects unsafe integer', async () => { await expect(getBlockInfo(Number.MAX_SAFE_INTEGER + 1)).rejects.toThrow( 'getBlockInfo: height must be a positive integer' ) }) it('rejects Infinity', async () => { await expect(getBlockInfo(Number.POSITIVE_INFINITY)).rejects.toThrow( 'getBlockInfo: height must be a positive integer, got Infinity' ) }) }) })