Fix explorer routing, links, and frontend API loading
This commit is contained in:
109
frontend/src/services/api/blockscout.ts
Normal file
109
frontend/src/services/api/blockscout.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import type { Block } from './blocks'
|
||||
import type { Transaction } from './transactions'
|
||||
import type { TransactionSummary } from './addresses'
|
||||
|
||||
export function getExplorerApiBase() {
|
||||
return (process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080').replace(/\/$/, '')
|
||||
}
|
||||
|
||||
export async function fetchBlockscoutJson<T>(path: string): Promise<T> {
|
||||
const response = await fetch(`${getExplorerApiBase()}${path}`)
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}`)
|
||||
}
|
||||
return response.json() as Promise<T>
|
||||
}
|
||||
|
||||
type HashLike = string | { hash?: string | null } | null | undefined
|
||||
|
||||
export function extractHash(value: HashLike): string {
|
||||
if (!value) return ''
|
||||
return typeof value === 'string' ? value : value.hash || ''
|
||||
}
|
||||
|
||||
function toNumber(value: unknown): number {
|
||||
if (typeof value === 'number') return value
|
||||
if (typeof value === 'string' && value.trim() !== '') return Number(value)
|
||||
return 0
|
||||
}
|
||||
|
||||
interface BlockscoutBlock {
|
||||
hash: string
|
||||
height: number | string
|
||||
timestamp: string
|
||||
miner: HashLike
|
||||
transaction_count: number | string
|
||||
gas_used: number | string
|
||||
gas_limit: number | string
|
||||
}
|
||||
|
||||
interface BlockscoutTransaction {
|
||||
hash: string
|
||||
block_number: number | string
|
||||
from: HashLike
|
||||
to: HashLike
|
||||
value: string
|
||||
status?: string | null
|
||||
result?: string | null
|
||||
gas_price?: number | string | null
|
||||
gas_limit: number | string
|
||||
gas_used?: number | string | null
|
||||
max_fee_per_gas?: number | string | null
|
||||
max_priority_fee_per_gas?: number | string | null
|
||||
raw_input?: string | null
|
||||
timestamp: string
|
||||
created_contract?: HashLike
|
||||
}
|
||||
|
||||
function normalizeStatus(raw: BlockscoutTransaction): number {
|
||||
const value = (raw.status || raw.result || '').toString().toLowerCase()
|
||||
if (value === 'success' || value === 'ok' || value === '1') return 1
|
||||
if (value === 'error' || value === 'failed' || value === '0') return 0
|
||||
return 0
|
||||
}
|
||||
|
||||
export function normalizeBlock(raw: BlockscoutBlock, chainId: number): Block {
|
||||
return {
|
||||
chain_id: chainId,
|
||||
number: toNumber(raw.height),
|
||||
hash: raw.hash,
|
||||
timestamp: raw.timestamp,
|
||||
miner: extractHash(raw.miner),
|
||||
transaction_count: toNumber(raw.transaction_count),
|
||||
gas_used: toNumber(raw.gas_used),
|
||||
gas_limit: toNumber(raw.gas_limit),
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeTransaction(raw: BlockscoutTransaction, chainId: number): Transaction {
|
||||
return {
|
||||
chain_id: chainId,
|
||||
hash: raw.hash,
|
||||
block_number: toNumber(raw.block_number),
|
||||
block_hash: '',
|
||||
transaction_index: 0,
|
||||
from_address: extractHash(raw.from),
|
||||
to_address: extractHash(raw.to) || undefined,
|
||||
value: raw.value || '0',
|
||||
gas_price: raw.gas_price != null ? toNumber(raw.gas_price) : undefined,
|
||||
max_fee_per_gas: raw.max_fee_per_gas != null ? toNumber(raw.max_fee_per_gas) : undefined,
|
||||
max_priority_fee_per_gas: raw.max_priority_fee_per_gas != null ? toNumber(raw.max_priority_fee_per_gas) : undefined,
|
||||
gas_limit: toNumber(raw.gas_limit),
|
||||
gas_used: raw.gas_used != null ? toNumber(raw.gas_used) : undefined,
|
||||
status: normalizeStatus(raw),
|
||||
input_data: raw.raw_input || undefined,
|
||||
contract_address: extractHash(raw.created_contract) || undefined,
|
||||
created_at: raw.timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeTransactionSummary(raw: BlockscoutTransaction): TransactionSummary {
|
||||
return {
|
||||
hash: raw.hash,
|
||||
block_number: toNumber(raw.block_number),
|
||||
from_address: extractHash(raw.from),
|
||||
to_address: extractHash(raw.to) || undefined,
|
||||
value: raw.value || '0',
|
||||
status: normalizeStatus(raw),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user