132 lines
3.9 KiB
TypeScript
132 lines
3.9 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import { transactionsApi } from './transactions'
|
|
|
|
describe('transactionsApi.listByBlockSafe', () => {
|
|
beforeEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('returns normalized transactions for a specific block', async () => {
|
|
const fetchMock = vi.fn().mockResolvedValue({
|
|
ok: true,
|
|
json: async () => ({
|
|
items: [
|
|
{
|
|
hash: '0xabc',
|
|
block_number: 123,
|
|
block_hash: '0xdef',
|
|
transaction_index: 0,
|
|
from: { hash: '0x0000000000000000000000000000000000000001' },
|
|
to: { hash: '0x0000000000000000000000000000000000000002' },
|
|
value: '0',
|
|
gas_price: '1',
|
|
gas: '21000',
|
|
gas_used: '21000',
|
|
status: 'ok',
|
|
timestamp: '2026-04-16T09:40:12.000000Z',
|
|
},
|
|
],
|
|
next_page_params: { page: 2, page_size: 10 },
|
|
}),
|
|
})
|
|
|
|
vi.stubGlobal('fetch', fetchMock)
|
|
|
|
const result = await transactionsApi.listByBlockSafe(138, 123, 1, 10)
|
|
|
|
expect(result.ok).toBe(true)
|
|
expect(result.data).toHaveLength(1)
|
|
expect(result.hasNextPage).toBe(true)
|
|
expect(result.data[0]?.hash).toBe('0xabc')
|
|
expect(fetchMock).toHaveBeenCalledTimes(1)
|
|
expect(fetchMock.mock.calls[0]?.[0]).toEqual(
|
|
expect.stringContaining('/api/v2/blocks/123/transactions?page=1&page_size=10'),
|
|
)
|
|
})
|
|
|
|
it('returns a non-throwing failure result when the block transaction request fails', async () => {
|
|
vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new Error('network down')))
|
|
|
|
const result = await transactionsApi.listByBlockSafe(138, 123, 1, 10)
|
|
|
|
expect(result).toEqual({
|
|
ok: false,
|
|
data: [],
|
|
hasNextPage: false,
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('transactionsApi.diagnoseMissing', () => {
|
|
beforeEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('distinguishes missing explorer and missing rpc results', async () => {
|
|
const fetchMock = vi.fn()
|
|
.mockResolvedValueOnce({
|
|
ok: false,
|
|
status: 404,
|
|
json: async () => ({ message: 'Not found' }),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ result: null }),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ result: null }),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ result: '0x39fb85' }),
|
|
})
|
|
|
|
vi.stubGlobal('fetch', fetchMock)
|
|
|
|
const diagnostic = await transactionsApi.diagnoseMissing(
|
|
138,
|
|
'0x14d7259e6e75bbcd8979dc9e19f3001b0f328bbcdb730937f8cc2e6a52f26da6'
|
|
)
|
|
|
|
expect(diagnostic.checked_hash).toBe('0x14d7259e6e75bbcd8979dc9e19f3001b0f328bbcdb730937f8cc2e6a52f26da6')
|
|
expect(diagnostic.chain_id).toBe(138)
|
|
expect(diagnostic.explorer_indexed).toBe(false)
|
|
expect(diagnostic.rpc_transaction_found).toBe(false)
|
|
expect(diagnostic.rpc_receipt_found).toBe(false)
|
|
expect(diagnostic.latest_block_number).toBeTypeOf('number')
|
|
expect(diagnostic.rpc_url).toBe('https://rpc-http-pub.d-bis.org')
|
|
})
|
|
|
|
it('reports when rpc can still see a transaction the explorer has not indexed', async () => {
|
|
const fetchMock = vi.fn()
|
|
.mockResolvedValueOnce({
|
|
ok: false,
|
|
status: 404,
|
|
json: async () => ({ message: 'Not found' }),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ result: { hash: '0xabc' } }),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ result: null }),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ result: '0x10' }),
|
|
})
|
|
|
|
vi.stubGlobal('fetch', fetchMock)
|
|
|
|
const diagnostic = await transactionsApi.diagnoseMissing(138, '0xabc')
|
|
|
|
expect(diagnostic.explorer_indexed).toBe(false)
|
|
expect(diagnostic.rpc_transaction_found).toBe(true)
|
|
expect(diagnostic.rpc_receipt_found).toBe(false)
|
|
expect(diagnostic.latest_block_number).toBe(16)
|
|
})
|
|
})
|