import type { NextPage } from 'next' import { DashboardNavbar } from '.' import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' import { useState, useMemo, useEffect } from 'react' import { LinkButton } from '@components/shared/Button' import Image from 'next/image' import Loading from '@components/shared/Loading' import useBanks from 'hooks/useBanks' interface Token { symbol: string // Every token will definitely have a symbol. [key: string]: string // Other properties are unknown and can vary. } const fetchTokens = async ( offset = 0, existingTokens: Token[] = [], ): Promise => { const res = await fetch(`/api/tokens?offset=${offset * 50}&limit=50`) const data = await res.json() return [...existingTokens, ...data] // Ensure the returned data conforms to Token[] } const Prospective: NextPage = () => { const banks = useBanks()['banks'] const bankNames = banks.map((bank) => bank.name.toUpperCase()) // Generate headers from the first token entry if available const [tokensList, setTokensList] = useState([]) const [offset, setOffset] = useState(0) const [loading, setLoading] = useState(false) useEffect(() => { const initialFetch = async () => { setLoading(true) try { const initialTokens: Token[] = await fetchTokens(0) setTokensList(initialTokens) } catch (error) { console.error('Failed to fetch tokens:', error) } finally { setLoading(false) } } initialFetch() }, []) const handleShowMore = async () => { setLoading(true) try { const newTokens = await fetchTokens(offset + 1, tokensList) setTokensList(newTokens) setOffset((prevOffset) => prevOffset + 1) } catch (error) { console.error('Failed to fetch more tokens:', error) } setLoading(false) } const heads = useMemo(() => { if (tokensList.length > 0) { const allKeys = Object.keys(tokensList[0]) const filteredKeys = allKeys.filter( (key) => ![ 'symbol', 'extensions', 'lastTradeUnixTime', 'uniqueWallet30m', ].includes(key), ) return ['symbol', ...filteredKeys] } return [] }, [tokensList]) const downloadTokens = () => { let csvContent = 'data:text/csv;charset=utf-8,' const filteredTokens = tokensList.filter( (token) => !bankNames.includes(token.symbol.toUpperCase()), ) if (filteredTokens.length > 0) { const headers = Object.keys(filteredTokens[0]).join(',') const rows = filteredTokens.map((token) => Object.values(token) .map( (value) => `"${value?.toString().replace(/"/g, '""')}"`, // Handle quotes in data ) .join(','), ) csvContent += headers + '\n' + rows.join('\n') } const encodedUri = encodeURI(csvContent) const link = document.createElement('a') link.setAttribute('href', encodedUri) link.setAttribute('download', 'non_bank_tokens.csv') document.body.appendChild(link) // Required for FF link.click() document.body.removeChild(link) } return (

Hidden Gems to Prospect On

{heads.map((head, index) => ( ))} {tokensList.map((token: Token, idx) => ( window.open( `https://birdeye.so/token/${token['address']}?chain=solana&tab=recentTrades`, '_blank', ) } > {heads.map((head, valIdx) => { if (head == 'symbol') { token[head] = token[head]?.toUpperCase().toString() } return ( ) })} ))}
{head}
{head == 'logoURI' ? ( <> Token Logo{' '} ) : ( <> {token[head] ? token[head]?.toString() : 'N/A'} )}
{loading && (
)}
Show More
) } export default Prospective