/** * Phase 2 mock explorer data. * Swap for Doltgres/SSE later without changing list/detail page shapes. */ import type { MockBlock, MockTransaction } from "@/lib/explorer-types"; export const MOCK_TRANSACTIONS: MockTransaction[] = [ { hash: "0x7a3f9c2e1b8d4f6a0e5c9b7d3a1f8e2c6b4d0a9e5f3c7b1d8a6e4c2f0b9d7a5", status: "anchored", privateBlock: 1284901, from: "0x1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d", to: "0x9f8e7d6c5b4a39281706f5e4d3c2b1a09f8e7d6c", value: "12.40 KRYP", age: "32s ago", submittedAt: "2026-07-29T10:14:02.000Z", confirmedAt: "2026-07-29T10:14:03.200Z", publicAnchorTx: "0xbb11cc22dd33ee44ff556677889900aabbccddeeff00112233445566778899aa", publicChain: "Ethereum Sepolia (mock)", anchoredAt: "2026-07-29T10:14:28.000Z", method: "transfer", }, { hash: "0x2b8e1f0a9c7d5e3f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8", status: "anchored", privateBlock: 1284900, from: "0x55aa66bb77cc88dd99ee00ff1122334455667788", to: "0xccdd11223344556677889900aabbccddeeff0011", value: "0.85 KRYP", age: "1m ago", submittedAt: "2026-07-29T10:13:10.000Z", confirmedAt: "2026-07-29T10:13:11.100Z", publicAnchorTx: "0xbb11cc22dd33ee44ff556677889900aabbccddeeff00112233445566778899aa", publicChain: "Ethereum Sepolia (mock)", anchoredAt: "2026-07-29T10:14:28.000Z", method: "transfer", }, { hash: "0x9d0c1b2a3f4e5d6c7b8a9012e3f4a5b6c7d8e9f0a1b2c3d4e5f60718293a4b5", status: "confirmed", privateBlock: 1284902, from: "0xabcdef0123456789abcdef0123456789abcdef01", to: "0x0123456789abcdef0123456789abcdef01234567", value: "4.00 KRYP", age: "8s ago", submittedAt: "2026-07-29T10:14:26.000Z", confirmedAt: "2026-07-29T10:14:27.400Z", publicAnchorTx: null, publicChain: null, anchoredAt: null, method: "transfer", }, { hash: "0x4e5f6a7b8c9d0e1f2a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f80", status: "pending", privateBlock: null, from: "0x777788889999aaaabbbbccccddddeeeeffff0000", to: "0x111122223333444455556666777788889999aaaa", value: "0.10 KRYP", age: "3s ago", submittedAt: "2026-07-29T10:14:31.000Z", confirmedAt: null, publicAnchorTx: null, publicChain: null, anchoredAt: null, method: "transfer", }, { hash: "0x0a1b2c3d4e5f60718293a4b5c6d7e8f901a2b3c4d5e6f708192a3b4c5d6e7f", status: "anchored", privateBlock: 1284898, from: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", to: "0xcafebabecafebabecafebabecafebabecafebabe", value: "100.00 KRYP", age: "4m ago", submittedAt: "2026-07-29T10:10:02.000Z", confirmedAt: "2026-07-29T10:10:03.000Z", publicAnchorTx: "0xaa00bb11cc22dd33ee44ff556677889900aabbccddeeff001122334455667788", publicChain: "Ethereum Sepolia (mock)", anchoredAt: "2026-07-29T10:11:40.000Z", method: "batchSettle", }, { hash: "0xfedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210", status: "confirmed", privateBlock: 1284902, from: "0x3333444455556666777788889999aaaabbbbcccc", to: "0xeeeef0f1f2f3f4f5f6f7f8f9fafbfcfdfeff0001", value: "1.25 KRYP", age: "9s ago", submittedAt: "2026-07-29T10:14:25.000Z", confirmedAt: "2026-07-29T10:14:26.800Z", publicAnchorTx: null, publicChain: null, anchoredAt: null, method: "transfer", }, { hash: "0x11223344556677889900aabbccddeeff00112233445566778899aabbccddeeff", status: "anchored", privateBlock: 1284895, from: "0xabcabcabcabcabcabcabcabcabcabcabcabcabca", to: "0x1231231231231231231231231231231231231231", value: "0.02 KRYP", age: "12m ago", submittedAt: "2026-07-29T10:02:11.000Z", confirmedAt: "2026-07-29T10:02:12.500Z", publicAnchorTx: "0x99aa88bb77cc66dd55ee44ff33aa221100ffeeddccbbaa998877665544332211", publicChain: "Ethereum Sepolia (mock)", anchoredAt: "2026-07-29T10:04:00.000Z", method: "approve", }, { hash: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd", status: "pending", privateBlock: null, from: "0x88889999aaaabbbbccccddddeeeeffff00001111", to: "0x22223333444455556666777788889999aaaabbbb", value: "2.50 KRYP", age: "1s ago", submittedAt: "2026-07-29T10:14:33.000Z", confirmedAt: null, publicAnchorTx: null, publicChain: null, anchoredAt: null, method: "transfer", }, ]; export const MOCK_BLOCKS: MockBlock[] = [ { height: 1284902, hash: "0xblk902aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", txCount: 2, proposer: "validator-3", age: "9s ago", timestamp: "2026-07-29T10:14:25.000Z", parentHash: "0xblk901aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", publicAnchorTx: null, transactions: [ "0x9d0c1b2a3f4e5d6c7b8a9012e3f4a5b6c7d8e9f0a1b2c3d4e5f60718293a4b5", "0xfedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210", ], }, { height: 1284901, hash: "0xblk901aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", txCount: 1, proposer: "validator-1", age: "32s ago", timestamp: "2026-07-29T10:14:02.000Z", parentHash: "0xblk900aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", publicAnchorTx: "0xbb11cc22dd33ee44ff556677889900aabbccddeeff00112233445566778899aa", transactions: [ "0x7a3f9c2e1b8d4f6a0e5c9b7d3a1f8e2c6b4d0a9e5f3c7b1d8a6e4c2f0b9d7a5", ], }, { height: 1284900, hash: "0xblk900aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", txCount: 1, proposer: "validator-2", age: "1m ago", timestamp: "2026-07-29T10:13:10.000Z", parentHash: "0xblk899aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", publicAnchorTx: "0xbb11cc22dd33ee44ff556677889900aabbccddeeff00112233445566778899aa", transactions: [ "0x2b8e1f0a9c7d5e3f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8", ], }, { height: 1284898, hash: "0xblk898aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", txCount: 1, proposer: "validator-1", age: "4m ago", timestamp: "2026-07-29T10:10:02.000Z", parentHash: "0xblk897aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", publicAnchorTx: "0xaa00bb11cc22dd33ee44ff556677889900aabbccddeeff001122334455667788", transactions: [ "0x0a1b2c3d4e5f60718293a4b5c6d7e8f901a2b3c4d5e6f708192a3b4c5d6e7f", ], }, { height: 1284895, hash: "0xblk895aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", txCount: 1, proposer: "validator-3", age: "12m ago", timestamp: "2026-07-29T10:02:11.000Z", parentHash: "0xblk894aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", publicAnchorTx: "0x99aa88bb77cc66dd55ee44ff33aa221100ffeeddccbbaa998877665544332211", transactions: [ "0x11223344556677889900aabbccddeeff00112233445566778899aabbccddeeff", ], }, { height: 1284890, hash: "0xblk890aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", txCount: 0, proposer: "validator-2", age: "18m ago", timestamp: "2026-07-29T09:56:00.000Z", parentHash: "0xblk889aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566", publicAnchorTx: null, transactions: [], }, ]; export function getTransaction(hash: string): MockTransaction | undefined { const q = hash.toLowerCase().replace(/^0x/, ""); return MOCK_TRANSACTIONS.find((tx) => { const h = tx.hash.toLowerCase().replace(/^0x/, ""); return h === q || h.startsWith(q) || tx.hash.toLowerCase() === hash.toLowerCase(); }); } export function getBlock(heightOrHash: string): MockBlock | undefined { const asNum = Number(heightOrHash); if (!Number.isNaN(asNum) && heightOrHash.trim() !== "") { return MOCK_BLOCKS.find((b) => b.height === asNum); } const q = heightOrHash.toLowerCase().replace(/^0x/, ""); return MOCK_BLOCKS.find((b) => { const h = b.hash.toLowerCase().replace(/^0x/, ""); return h === q || h.startsWith(q) || b.hash.toLowerCase() === heightOrHash.toLowerCase(); }); } export type SearchHit = | { kind: "tx"; id: string } | { kind: "block"; id: string } | { kind: "none" }; /** Resolve a search query against mock txs/blocks. */ export function searchExplorer(query: string): SearchHit { const raw = query.trim(); if (!raw) return { kind: "none" }; // Block height if (/^\d+$/.test(raw)) { const block = getBlock(raw); if (block) return { kind: "block", id: String(block.height) }; } // Tx hash (full or prefix ≥6 hex chars) const tx = getTransaction(raw); if (tx) return { kind: "tx", id: tx.hash }; // Block hash const block = getBlock(raw); if (block) return { kind: "block", id: String(block.height) }; // Address: first matching from/to const addr = raw.toLowerCase(); if (addr.startsWith("0x") && addr.length >= 10) { const byAddr = MOCK_TRANSACTIONS.find( (t) => t.from.toLowerCase().includes(addr) || t.to.toLowerCase().includes(addr), ); if (byAddr) return { kind: "tx", id: byAddr.hash }; } return { kind: "none" }; } export function shortHash(hash: string, size = 6): string { if (hash.length < size * 2 + 2) return hash; return `${hash.slice(0, 2 + size)}…${hash.slice(-size)}`; } export function formatTime(iso: string | null): string { if (!iso) return "—"; try { return new Date(iso).toLocaleString(undefined, { dateStyle: "medium", timeStyle: "medium", }); } catch { return iso; } }