explorer-mock.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /**
  2. * Phase 2 mock explorer data.
  3. * Swap for Doltgres/SSE later without changing list/detail page shapes.
  4. */
  5. import type { MockBlock, MockTransaction } from "@/lib/explorer-types";
  6. export const MOCK_TRANSACTIONS: MockTransaction[] = [
  7. {
  8. hash: "0x7a3f9c2e1b8d4f6a0e5c9b7d3a1f8e2c6b4d0a9e5f3c7b1d8a6e4c2f0b9d7a5",
  9. status: "anchored",
  10. privateBlock: 1284901,
  11. from: "0x1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d",
  12. to: "0x9f8e7d6c5b4a39281706f5e4d3c2b1a09f8e7d6c",
  13. value: "12.40 KRYP",
  14. age: "32s ago",
  15. submittedAt: "2026-07-29T10:14:02.000Z",
  16. confirmedAt: "2026-07-29T10:14:03.200Z",
  17. publicAnchorTx:
  18. "0xbb11cc22dd33ee44ff556677889900aabbccddeeff00112233445566778899aa",
  19. publicChain: "Ethereum Sepolia (mock)",
  20. anchoredAt: "2026-07-29T10:14:28.000Z",
  21. method: "transfer",
  22. },
  23. {
  24. hash: "0x2b8e1f0a9c7d5e3f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8",
  25. status: "anchored",
  26. privateBlock: 1284900,
  27. from: "0x55aa66bb77cc88dd99ee00ff1122334455667788",
  28. to: "0xccdd11223344556677889900aabbccddeeff0011",
  29. value: "0.85 KRYP",
  30. age: "1m ago",
  31. submittedAt: "2026-07-29T10:13:10.000Z",
  32. confirmedAt: "2026-07-29T10:13:11.100Z",
  33. publicAnchorTx:
  34. "0xbb11cc22dd33ee44ff556677889900aabbccddeeff00112233445566778899aa",
  35. publicChain: "Ethereum Sepolia (mock)",
  36. anchoredAt: "2026-07-29T10:14:28.000Z",
  37. method: "transfer",
  38. },
  39. {
  40. hash: "0x9d0c1b2a3f4e5d6c7b8a9012e3f4a5b6c7d8e9f0a1b2c3d4e5f60718293a4b5",
  41. status: "confirmed",
  42. privateBlock: 1284902,
  43. from: "0xabcdef0123456789abcdef0123456789abcdef01",
  44. to: "0x0123456789abcdef0123456789abcdef01234567",
  45. value: "4.00 KRYP",
  46. age: "8s ago",
  47. submittedAt: "2026-07-29T10:14:26.000Z",
  48. confirmedAt: "2026-07-29T10:14:27.400Z",
  49. publicAnchorTx: null,
  50. publicChain: null,
  51. anchoredAt: null,
  52. method: "transfer",
  53. },
  54. {
  55. hash: "0x4e5f6a7b8c9d0e1f2a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f80",
  56. status: "pending",
  57. privateBlock: null,
  58. from: "0x777788889999aaaabbbbccccddddeeeeffff0000",
  59. to: "0x111122223333444455556666777788889999aaaa",
  60. value: "0.10 KRYP",
  61. age: "3s ago",
  62. submittedAt: "2026-07-29T10:14:31.000Z",
  63. confirmedAt: null,
  64. publicAnchorTx: null,
  65. publicChain: null,
  66. anchoredAt: null,
  67. method: "transfer",
  68. },
  69. {
  70. hash: "0x0a1b2c3d4e5f60718293a4b5c6d7e8f901a2b3c4d5e6f708192a3b4c5d6e7f",
  71. status: "anchored",
  72. privateBlock: 1284898,
  73. from: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
  74. to: "0xcafebabecafebabecafebabecafebabecafebabe",
  75. value: "100.00 KRYP",
  76. age: "4m ago",
  77. submittedAt: "2026-07-29T10:10:02.000Z",
  78. confirmedAt: "2026-07-29T10:10:03.000Z",
  79. publicAnchorTx:
  80. "0xaa00bb11cc22dd33ee44ff556677889900aabbccddeeff001122334455667788",
  81. publicChain: "Ethereum Sepolia (mock)",
  82. anchoredAt: "2026-07-29T10:11:40.000Z",
  83. method: "batchSettle",
  84. },
  85. {
  86. hash: "0xfedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
  87. status: "confirmed",
  88. privateBlock: 1284902,
  89. from: "0x3333444455556666777788889999aaaabbbbcccc",
  90. to: "0xeeeef0f1f2f3f4f5f6f7f8f9fafbfcfdfeff0001",
  91. value: "1.25 KRYP",
  92. age: "9s ago",
  93. submittedAt: "2026-07-29T10:14:25.000Z",
  94. confirmedAt: "2026-07-29T10:14:26.800Z",
  95. publicAnchorTx: null,
  96. publicChain: null,
  97. anchoredAt: null,
  98. method: "transfer",
  99. },
  100. {
  101. hash: "0x11223344556677889900aabbccddeeff00112233445566778899aabbccddeeff",
  102. status: "anchored",
  103. privateBlock: 1284895,
  104. from: "0xabcabcabcabcabcabcabcabcabcabcabcabcabca",
  105. to: "0x1231231231231231231231231231231231231231",
  106. value: "0.02 KRYP",
  107. age: "12m ago",
  108. submittedAt: "2026-07-29T10:02:11.000Z",
  109. confirmedAt: "2026-07-29T10:02:12.500Z",
  110. publicAnchorTx:
  111. "0x99aa88bb77cc66dd55ee44ff33aa221100ffeeddccbbaa998877665544332211",
  112. publicChain: "Ethereum Sepolia (mock)",
  113. anchoredAt: "2026-07-29T10:04:00.000Z",
  114. method: "approve",
  115. },
  116. {
  117. hash: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
  118. status: "pending",
  119. privateBlock: null,
  120. from: "0x88889999aaaabbbbccccddddeeeeffff00001111",
  121. to: "0x22223333444455556666777788889999aaaabbbb",
  122. value: "2.50 KRYP",
  123. age: "1s ago",
  124. submittedAt: "2026-07-29T10:14:33.000Z",
  125. confirmedAt: null,
  126. publicAnchorTx: null,
  127. publicChain: null,
  128. anchoredAt: null,
  129. method: "transfer",
  130. },
  131. ];
  132. export const MOCK_BLOCKS: MockBlock[] = [
  133. {
  134. height: 1284902,
  135. hash: "0xblk902aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  136. txCount: 2,
  137. proposer: "validator-3",
  138. age: "9s ago",
  139. timestamp: "2026-07-29T10:14:25.000Z",
  140. parentHash:
  141. "0xblk901aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  142. publicAnchorTx: null,
  143. transactions: [
  144. "0x9d0c1b2a3f4e5d6c7b8a9012e3f4a5b6c7d8e9f0a1b2c3d4e5f60718293a4b5",
  145. "0xfedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
  146. ],
  147. },
  148. {
  149. height: 1284901,
  150. hash: "0xblk901aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  151. txCount: 1,
  152. proposer: "validator-1",
  153. age: "32s ago",
  154. timestamp: "2026-07-29T10:14:02.000Z",
  155. parentHash:
  156. "0xblk900aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  157. publicAnchorTx:
  158. "0xbb11cc22dd33ee44ff556677889900aabbccddeeff00112233445566778899aa",
  159. transactions: [
  160. "0x7a3f9c2e1b8d4f6a0e5c9b7d3a1f8e2c6b4d0a9e5f3c7b1d8a6e4c2f0b9d7a5",
  161. ],
  162. },
  163. {
  164. height: 1284900,
  165. hash: "0xblk900aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  166. txCount: 1,
  167. proposer: "validator-2",
  168. age: "1m ago",
  169. timestamp: "2026-07-29T10:13:10.000Z",
  170. parentHash:
  171. "0xblk899aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  172. publicAnchorTx:
  173. "0xbb11cc22dd33ee44ff556677889900aabbccddeeff00112233445566778899aa",
  174. transactions: [
  175. "0x2b8e1f0a9c7d5e3f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8",
  176. ],
  177. },
  178. {
  179. height: 1284898,
  180. hash: "0xblk898aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  181. txCount: 1,
  182. proposer: "validator-1",
  183. age: "4m ago",
  184. timestamp: "2026-07-29T10:10:02.000Z",
  185. parentHash:
  186. "0xblk897aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  187. publicAnchorTx:
  188. "0xaa00bb11cc22dd33ee44ff556677889900aabbccddeeff001122334455667788",
  189. transactions: [
  190. "0x0a1b2c3d4e5f60718293a4b5c6d7e8f901a2b3c4d5e6f708192a3b4c5d6e7f",
  191. ],
  192. },
  193. {
  194. height: 1284895,
  195. hash: "0xblk895aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  196. txCount: 1,
  197. proposer: "validator-3",
  198. age: "12m ago",
  199. timestamp: "2026-07-29T10:02:11.000Z",
  200. parentHash:
  201. "0xblk894aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  202. publicAnchorTx:
  203. "0x99aa88bb77cc66dd55ee44ff33aa221100ffeeddccbbaa998877665544332211",
  204. transactions: [
  205. "0x11223344556677889900aabbccddeeff00112233445566778899aabbccddeeff",
  206. ],
  207. },
  208. {
  209. height: 1284890,
  210. hash: "0xblk890aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  211. txCount: 0,
  212. proposer: "validator-2",
  213. age: "18m ago",
  214. timestamp: "2026-07-29T09:56:00.000Z",
  215. parentHash:
  216. "0xblk889aa11bb22cc33dd44ee55ff66778899aabbccddeeff00112233445566",
  217. publicAnchorTx: null,
  218. transactions: [],
  219. },
  220. ];
  221. export function getTransaction(hash: string): MockTransaction | undefined {
  222. const q = hash.toLowerCase().replace(/^0x/, "");
  223. return MOCK_TRANSACTIONS.find((tx) => {
  224. const h = tx.hash.toLowerCase().replace(/^0x/, "");
  225. return h === q || h.startsWith(q) || tx.hash.toLowerCase() === hash.toLowerCase();
  226. });
  227. }
  228. export function getBlock(heightOrHash: string): MockBlock | undefined {
  229. const asNum = Number(heightOrHash);
  230. if (!Number.isNaN(asNum) && heightOrHash.trim() !== "") {
  231. return MOCK_BLOCKS.find((b) => b.height === asNum);
  232. }
  233. const q = heightOrHash.toLowerCase().replace(/^0x/, "");
  234. return MOCK_BLOCKS.find((b) => {
  235. const h = b.hash.toLowerCase().replace(/^0x/, "");
  236. return h === q || h.startsWith(q) || b.hash.toLowerCase() === heightOrHash.toLowerCase();
  237. });
  238. }
  239. export type SearchHit =
  240. | { kind: "tx"; id: string }
  241. | { kind: "block"; id: string }
  242. | { kind: "none" };
  243. /** Resolve a search query against mock txs/blocks. */
  244. export function searchExplorer(query: string): SearchHit {
  245. const raw = query.trim();
  246. if (!raw) return { kind: "none" };
  247. // Block height
  248. if (/^\d+$/.test(raw)) {
  249. const block = getBlock(raw);
  250. if (block) return { kind: "block", id: String(block.height) };
  251. }
  252. // Tx hash (full or prefix ≥6 hex chars)
  253. const tx = getTransaction(raw);
  254. if (tx) return { kind: "tx", id: tx.hash };
  255. // Block hash
  256. const block = getBlock(raw);
  257. if (block) return { kind: "block", id: String(block.height) };
  258. // Address: first matching from/to
  259. const addr = raw.toLowerCase();
  260. if (addr.startsWith("0x") && addr.length >= 10) {
  261. const byAddr = MOCK_TRANSACTIONS.find(
  262. (t) =>
  263. t.from.toLowerCase().includes(addr) ||
  264. t.to.toLowerCase().includes(addr),
  265. );
  266. if (byAddr) return { kind: "tx", id: byAddr.hash };
  267. }
  268. return { kind: "none" };
  269. }
  270. export function shortHash(hash: string, size = 6): string {
  271. if (hash.length < size * 2 + 2) return hash;
  272. return `${hash.slice(0, 2 + size)}…${hash.slice(-size)}`;
  273. }
  274. export function formatTime(iso: string | null): string {
  275. if (!iso) return "—";
  276. try {
  277. return new Date(iso).toLocaleString(undefined, {
  278. dateStyle: "medium",
  279. timeStyle: "medium",
  280. });
  281. } catch {
  282. return iso;
  283. }
  284. }