/** * Component: Transactions Overview * Author: Nearblocks Pte Ltd * License: Business Source License 1.1 * Description: Transactions Overview. * @interface Props * @param {boolean} [fetchStyles] - Use Nearblock styles. * @param {string} [network] - The network data to show, either mainnet or testnet */ /* INCLUDE COMPONENT: "includes/Common/Skelton.jsx" */ /** * @interface Props * @param {string} [className] - The CSS class name(s) for styling purposes. */ const Skelton = (props) => { return ( <div className={`bg-gray-200 h-5 rounded shadow-sm animate-pulse ${props.className}`} ></div> ); };/* END_INCLUDE COMPONENT: "includes/Common/Skelton.jsx" */ /* INCLUDE: "includes/formats.jsx" */ function currency(number) { let absNumber = Math.abs(number); const suffixes = ['', 'K', 'M', 'B', 'T', 'Q']; let suffixIndex = 0; while (absNumber >= 1000 && suffixIndex < suffixes.length - 1) { absNumber /= 1000; suffixIndex++; } let shortNumber = parseFloat(absNumber.toFixed(2)); return (number < 0 ? '-' : '') + shortNumber + ' ' + suffixes[suffixIndex]; } function formatDate(dateString) { const inputDate = new Date(dateString); const days = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', ]; const months = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', ]; const dayOfWeek = days[inputDate.getDay()]; const month = months[inputDate.getMonth()]; const day = inputDate.getDate(); const year = inputDate.getFullYear(); const formattedDate = dayOfWeek + ', ' + month + ' ' + day + ', ' + year; return formattedDate; } function formatCustomDate(inputDate) { var date = new Date(inputDate); // Array of month names var monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; // Get month and day var month = monthNames[date.getMonth()]; var day = date.getDate(); // Create formatted date string in "MMM DD" format var formattedDate = month + ' ' + (day < 10 ? '0' + day : day); return formattedDate; } function shortenHex(address) { return `${address && address.substr(0, 6)}...${address.substr(-4)}`; } function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function shortenToken(token) { return truncateString(token, 14, ''); } function shortenTokenSymbol(token) { return truncateString(token, 5, ''); } function gasPercentage(gasUsed, gasAttached) { if (!gasAttached) return 'N/A'; const formattedNumber = (Big(gasUsed).div(Big(gasAttached)) * 100).toFixed(); return `${formattedNumber}%`; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function dollarFormat(number) { const formattedNumber = Number(number).toLocaleString('en', { minimumFractionDigits: 2, maximumFractionDigits: 2, }); return formattedNumber; } function weight(number) { const suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; let suffixIndex = 0; while (number >= 1000 && suffixIndex < suffixes.length - 1) { number /= 1000; suffixIndex++; } return number.toFixed(2) + ' ' + suffixes[suffixIndex]; } function convertToUTC(timestamp, hour) { const date = new Date(timestamp); // Get UTC date components const utcYear = date.getUTCFullYear(); const utcMonth = ('0' + (date.getUTCMonth() + 1)).slice(-2); // Adding 1 because months are zero-based const utcDay = ('0' + date.getUTCDate()).slice(-2); const utcHours = ('0' + date.getUTCHours()).slice(-2); const utcMinutes = ('0' + date.getUTCMinutes()).slice(-2); const utcSeconds = ('0' + date.getUTCSeconds()).slice(-2); // Array of month abbreviations const monthAbbreviations = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; const monthIndex = Number(utcMonth) - 1; // Format the date as required (Jul-25-2022 16:25:37) let formattedDate = monthAbbreviations[monthIndex] + '-' + utcDay + '-' + utcYear + ' ' + utcHours + ':' + utcMinutes + ':' + utcSeconds; if (hour) { // Convert hours to 12-hour format let hour12 = parseInt(utcHours); const ampm = hour12 >= 12 ? 'PM' : 'AM'; hour12 = hour12 % 12 || 12; // Add AM/PM to the formatted date (Jul-25-2022 4:25:37 PM) formattedDate = monthAbbreviations[monthIndex] + '-' + utcDay + '-' + utcYear + ' ' + hour12 + ':' + utcMinutes + ':' + utcSeconds + ' ' + ampm; } return formattedDate; } function getTimeAgoString(timestamp) { const currentUTC = Date.now(); const date = new Date(timestamp); const seconds = Math.floor((currentUTC - date.getTime()) / 1000); const intervals = { year: seconds / (60 * 60 * 24 * 365), month: seconds / (60 * 60 * 24 * 30), week: seconds / (60 * 60 * 24 * 7), day: seconds / (60 * 60 * 24), hour: seconds / (60 * 60), minute: seconds / 60, }; if (intervals.year == 1) { return Math.ceil(intervals.year) + ' year ago'; } else if (intervals.year > 1) { return Math.ceil(intervals.year) + ' years ago'; } else if (intervals.month > 1) { return Math.ceil(intervals.month) + ' months ago'; } else if (intervals.week > 1) { return Math.ceil(intervals.week) + ' weeks ago'; } else if (intervals.day > 1) { return Math.ceil(intervals.day) + ' days ago'; } else if (intervals.hour > 1) { return Math.ceil(intervals.hour) + ' hours ago'; } else if (intervals.minute > 1) { return Math.ceil(intervals.minute) + ' minutes ago'; } else { return 'a few seconds ago'; } } function formatWithCommas(number) { return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); } function formatTimestampToString(timestamp) { const date = new Date(timestamp); // Format the date to 'YYYY-MM-DD HH:mm:ss' format const formattedDate = date.toISOString().replace('T', ' ').split('.')[0]; return formattedDate; } function convertToMetricPrefix(number) { const prefixes = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']; // Metric prefixes let count = 0; while (Math.abs(number) >= 1000 && count < prefixes.length - 1) { number /= 1000; count++; } return number.toFixed(2) + ' ' + prefixes[count]; } function gasFee(gas, price) { const near = yoctoToNear(Big(gas).mul(Big(price)).toString(), true); return `${near} Ⓝ`; } function currency(number) { let absNumber = Math.abs(number); const suffixes = ['', 'K', 'M', 'B', 'T', 'Q']; let suffixIndex = 0; while (absNumber >= 1000 && suffixIndex < suffixes.length - 1) { absNumber /= 1000; suffixIndex++; } let shortNumber = parseFloat(absNumber.toFixed(2)); return (number < 0 ? '-' : '') + shortNumber + ' ' + suffixes[suffixIndex]; } function formatDate(dateString) { const inputDate = new Date(dateString); const days = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', ]; const months = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', ]; const dayOfWeek = days[inputDate.getDay()]; const month = months[inputDate.getMonth()]; const day = inputDate.getDate(); const year = inputDate.getFullYear(); const formattedDate = dayOfWeek + ', ' + month + ' ' + day + ', ' + year; return formattedDate; } function formatCustomDate(inputDate) { var date = new Date(inputDate); // Array of month names var monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; // Get month and day var month = monthNames[date.getMonth()]; var day = date.getDate(); // Create formatted date string in "MMM DD" format var formattedDate = month + ' ' + (day < 10 ? '0' + day : day); return formattedDate; } function shortenHex(address) { return `${address && address.substr(0, 6)}...${address.substr(-4)}`; } function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function shortenToken(token) { return truncateString(token, 14, ''); } function shortenTokenSymbol(token) { return truncateString(token, 5, ''); } function gasPercentage(gasUsed, gasAttached) { if (!gasAttached) return 'N/A'; const formattedNumber = (Big(gasUsed).div(Big(gasAttached)) * 100).toFixed(); return `${formattedNumber}%`; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function formatCustomDate(inputDate) { var date = new Date(inputDate); // Array of month names var monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; // Get month and day var month = monthNames[date.getMonth()]; var day = date.getDate(); // Create formatted date string in "MMM DD" format var formattedDate = month + ' ' + (day < 10 ? '0' + day : day); return formattedDate; } function shortenHex(address) { return `${address && address.substr(0, 6)}...${address.substr(-4)}`; } function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function shortenToken(token) { return truncateString(token, 14, ''); } function shortenTokenSymbol(token) { return truncateString(token, 5, ''); } function gasPercentage(gasUsed, gasAttached) { if (!gasAttached) return 'N/A'; const formattedNumber = (Big(gasUsed).div(Big(gasAttached)) * 100).toFixed(); return `${formattedNumber}%`; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function localFormat(number) { const formattedNumber = Number(number).toLocaleString('en', { minimumFractionDigits: 0, maximumFractionDigits: 5, }); return formattedNumber; } function dollarFormat(number) { const formattedNumber = Number(number).toLocaleString('en', { minimumFractionDigits: 2, maximumFractionDigits: 2, }); return formattedNumber; } function weight(number) { const suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; let suffixIndex = 0; while (number >= 1000 && suffixIndex < suffixes.length - 1) { number /= 1000; suffixIndex++; } return number.toFixed(2) + ' ' + suffixes[suffixIndex]; } function convertToUTC(timestamp, hour) { const date = new Date(timestamp); // Get UTC date components const utcYear = date.getUTCFullYear(); const utcMonth = ('0' + (date.getUTCMonth() + 1)).slice(-2); // Adding 1 because months are zero-based const utcDay = ('0' + date.getUTCDate()).slice(-2); const utcHours = ('0' + date.getUTCHours()).slice(-2); const utcMinutes = ('0' + date.getUTCMinutes()).slice(-2); const utcSeconds = ('0' + date.getUTCSeconds()).slice(-2); // Array of month abbreviations const monthAbbreviations = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; const monthIndex = Number(utcMonth) - 1; // Format the date as required (Jul-25-2022 16:25:37) let formattedDate = monthAbbreviations[monthIndex] + '-' + utcDay + '-' + utcYear + ' ' + utcHours + ':' + utcMinutes + ':' + utcSeconds; if (hour) { // Convert hours to 12-hour format let hour12 = parseInt(utcHours); const ampm = hour12 >= 12 ? 'PM' : 'AM'; hour12 = hour12 % 12 || 12; // Add AM/PM to the formatted date (Jul-25-2022 4:25:37 PM) formattedDate = monthAbbreviations[monthIndex] + '-' + utcDay + '-' + utcYear + ' ' + hour12 + ':' + utcMinutes + ':' + utcSeconds + ' ' + ampm; } return formattedDate; } function getTimeAgoString(timestamp) { const currentUTC = Date.now(); const date = new Date(timestamp); const seconds = Math.floor((currentUTC - date.getTime()) / 1000); const intervals = { year: seconds / (60 * 60 * 24 * 365), month: seconds / (60 * 60 * 24 * 30), week: seconds / (60 * 60 * 24 * 7), day: seconds / (60 * 60 * 24), hour: seconds / (60 * 60), minute: seconds / 60, }; if (intervals.year == 1) { return Math.ceil(intervals.year) + ' year ago'; } else if (intervals.year > 1) { return Math.ceil(intervals.year) + ' years ago'; } else if (intervals.month > 1) { return Math.ceil(intervals.month) + ' months ago'; } else if (intervals.week > 1) { return Math.ceil(intervals.week) + ' weeks ago'; } else if (intervals.day > 1) { return Math.ceil(intervals.day) + ' days ago'; } else if (intervals.hour > 1) { return Math.ceil(intervals.hour) + ' hours ago'; } else if (intervals.minute > 1) { return Math.ceil(intervals.minute) + ' minutes ago'; } else { return 'a few seconds ago'; } } function formatWithCommas(number) { return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); } function formatTimestampToString(timestamp) { const date = new Date(timestamp); // Format the date to 'YYYY-MM-DD HH:mm:ss' format const formattedDate = date.toISOString().replace('T', ' ').split('.')[0]; return formattedDate; } function convertToMetricPrefix(number) { const prefixes = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']; // Metric prefixes let count = 0; while (Math.abs(number) >= 1000 && count < prefixes.length - 1) { number /= 1000; count++; } return number.toFixed(2) + ' ' + prefixes[count]; } function gasFee(gas, price) { const near = yoctoToNear(Big(gas).mul(Big(price)).toString(), true); return `${near} Ⓝ`; } function currency(number) { let absNumber = Math.abs(number); const suffixes = ['', 'K', 'M', 'B', 'T', 'Q']; let suffixIndex = 0; while (absNumber >= 1000 && suffixIndex < suffixes.length - 1) { absNumber /= 1000; suffixIndex++; } let shortNumber = parseFloat(absNumber.toFixed(2)); return (number < 0 ? '-' : '') + shortNumber + ' ' + suffixes[suffixIndex]; } function formatDate(dateString) { const inputDate = new Date(dateString); const days = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', ]; const months = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', ]; const dayOfWeek = days[inputDate.getDay()]; const month = months[inputDate.getMonth()]; const day = inputDate.getDate(); const year = inputDate.getFullYear(); const formattedDate = dayOfWeek + ', ' + month + ' ' + day + ', ' + year; return formattedDate; } function formatCustomDate(inputDate) { var date = new Date(inputDate); // Array of month names var monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; // Get month and day var month = monthNames[date.getMonth()]; var day = date.getDate(); // Create formatted date string in "MMM DD" format var formattedDate = month + ' ' + (day < 10 ? '0' + day : day); return formattedDate; } function shortenHex(address) { return `${address && address.substr(0, 6)}...${address.substr(-4)}`; } function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function shortenToken(token) { return truncateString(token, 14, ''); } function shortenTokenSymbol(token) { return truncateString(token, 5, ''); } function gasPercentage(gasUsed, gasAttached) { if (!gasAttached) return 'N/A'; const formattedNumber = (Big(gasUsed).div(Big(gasAttached)) * 100).toFixed(); return `${formattedNumber}%`; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function truncateString(str, maxLength, suffix) { if (str.length <= maxLength) { return str; } return str.substring(0, maxLength - suffix.length) + suffix; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } /* END_INCLUDE: "includes/formats.jsx" */ /* INCLUDE: "includes/libs.jsx" */ function getConfig(network) { switch (network) { case 'mainnet': return { ownerId: 'nearblocks.near', nodeUrl: 'https://rpc.mainnet.near.org', backendUrl: 'https://api-beta.nearblocks.io/v1/', rpcUrl: 'https://archival-rpc.testnet.near.org', appUrl: 'https://nearblocks.io/', }; case 'testnet': return { ownerId: 'nearblocks.testnet', nodeUrl: 'https://rpc.testnet.near.org', backendUrl: 'https://api-testnet-beta.nearblocks.io/v1/', rpcUrl: 'https://archival-rpc.testnet.near.org', appUrl: 'https://testnet.nearblocks.io/', }; default: return {}; } } function debounce( delay, func, ) { let timer; let active = true; console.log('hgjhgh'); const debounced = (arg) => { if (active) { clearTimeout(timer); timer = setTimeout(() => { active && func(arg); timer = undefined; }, delay); } else { func(arg); } }; debounced.isPending = () => { return timer !== undefined; }; debounced.cancel = () => { active = false; }; debounced.flush = (arg) => func(arg); return debounced; } /* END_INCLUDE: "includes/libs.jsx" */ /* INCLUDE: "includes/near.jsx" */ function gasPrice(yacto) { const near = Big(yoctoToNear(yacto, false)).mul(Big(10).pow(12)).toString(); return `${localFormat(near)} Ⓝ / Tgas`; } function tokenAmount(amount, decimal, format) { if (amount === undefined || amount === null) return 'N/A'; const near = Big(amount).div(Big(10).pow(+decimal)); return format ? near.toString().toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 8, }) : near; } function yoctoToNear(yocto, format) { const YOCTO_PER_NEAR = Big(10).pow(24).toString(); const near = Big(yocto).div(YOCTO_PER_NEAR).toString(); return format ? localFormat(near) : near; } function localFormat(number) { const formattedNumber = Number(number).toLocaleString('en', { minimumFractionDigits: 0, maximumFractionDigits: 5, }); return formattedNumber; } /* END_INCLUDE: "includes/near.jsx" */ function MainComponent(props) { const [isLoading, setIsLoading] = useState(false); const [css, setCss] = useState({}); const [stats, setStats] = useState({} ); const [charts, setCharts] = useState([]); const [chartConfig, setChartConfig] = useState( {} , ); const config = getConfig(props.network); /** * Fetches styles asynchronously from a nearblocks gateway. */ function fetchStyles() { asyncFetch('https://beta.nearblocks.io/common.css').then( (res) => { if (res?.body) { setCss(res.body); } }, ); } const Theme = styled.div` ${css} `; useEffect(() => { let delay = 15000; let retries = 0; function fetchStats() { setIsLoading(true); asyncFetch(`${config?.backendUrl}stats`) .then((data) => { const resp = data?.body?.stats?.[0]; setStats({ avg_block_time: resp.avg_block_time, block: resp.block, change_24: resp.change_24, gas_price: resp.gas_price, high_24h: resp.high_24h, high_all: resp.high_all, low_24h: resp.low_24h, low_all: resp.low_all, market_cap: resp.market_cap, near_btc_price: resp.near_btc_price, near_price: resp.near_price, nodes: resp.nodes, nodes_online: resp.nodes_online, total_supply: resp.total_supply, total_txns: resp.total_txns, volume: resp.volume, }); }) .catch((error) => { if (error.response && error.response.status === 429) { delay = Math.min(2 ** retries * 15000, 60000); retries++; } }); setIsLoading(false); } fetchStats(); const interval = setInterval(fetchStats, delay); return () => clearInterval(interval); }, [config?.backendUrl]); useEffect(() => { if (props?.fetchStyles) { fetchStyles(); } function fetchChartData() { asyncFetch(`${config.backendUrl}charts/latest`) .then( (data ) => { const resp = data?.body?.charts; setCharts(resp); }, ) .catch(() => {}); } fetchChartData(); }, [props?.fetchStyles, config.backendUrl]); const chartData = useMemo(() => { try { const series = charts?.map((stat) => ({ y: Number(stat.txns), date: stat.date, price: stat.near_price, })); series.sort( (a, b) => new Date(a.date).getTime() - new Date(b.date).getTime(), ); const categories = series.map((stat) => formatCustomDate(stat.date)); return { series, categories, }; } catch (error) { return { series: [], categories: [], }; } }, [charts]); useEffect(() => { // Factory function to create the tooltip formatter function fetchData() { const fetchedData = { chart: { height: 110, spacingTop: 10, spacingBottom: 0, spacingLeft: 0, spacingRight: 10, }, title: { text: null, }, xAxis: { type: 'datetime', lineWidth: 0, tickLength: 0, labels: { step: 7, }, categories: chartData.categories, }, yAxis: { gridLineWidth: 0, title: { text: null, }, }, legend: { enabled: false, }, plotOptions: { spline: { lineWidth: 1, states: { hover: { lineWidth: 1, }, }, marker: { radius: 0, }, }, }, series: [ { type: 'spline', data: chartData.series, color: '#80D1BF', }, ] , exporting: { enabled: false, }, credits: { enabled: false, }, }; setChartConfig(fetchedData); } fetchData(); }, [chartData]); const iframeSrc = ` <html> <head> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.4"></script> <script src="https://cdn.jsdelivr.net/npm/numeral@2.0.6/numeral.min.js"></script> </head> <body> <div id="chart-container" style="width: 100%; height: 100%;"></div> <script type="text/javascript"> const chartConfig = ${JSON.stringify(chartConfig)}; chartConfig.tooltip = { formatter: function () { const item= this.point function dollarFormat(value) { return numeral(value).format('0,0.00'); } return \`<span style="font-size:10px">\${dayjs(this.point.date).format( 'dddd, MMMM DD, YYYY' )}</span><br/>Transactions: <strong>\${dollarFormat( this.point.y )}</strong><br/>Price: $\${dollarFormat(this.point.price)} \`; } }; Highcharts.chart('chart-container', chartConfig); </script> </body> </html> `; return ( <Theme> <div className="relative -mt-14"> <div className="container mx-auto px-3"> <div className="bg-white soft-shadow rounded-lg overflow-hidden px-5 md:py lg:px-0"> <div className={`grid grid-flow-col grid-cols-1 ${ props.network === 'mainnet' ? 'grid-rows-3 lg:grid-cols-3' : 'grid-rows-2 lg:grid-cols-2' } lg:grid-rows-1 divide-y lg:divide-y-0 lg:divide-x lg:py-3`} > {props.network === 'mainnet' && ( <> <div className="flex flex-col lg:flex-col lg:items-stretch divide-y lg:divide-y lg:divide-x-0 md:pt-0 md:pb-0 md:px-5"> <div className="flex flex-row py-5 lg:pb-5 lg:px-0"> <div className="items-center flex justify-left mr-3 "> <img src={`${config.appUrl}images/near price.svg`} alt={'nearPrice'} className="h-9 w-9" width="24" height="24" /> </div> <div className="ml-2"> <p className="uppercase font-semibold text-gray-600 text-sm "> NEAR PRICE </p> {isLoading ? ( <Skelton /> ) : ( <a href="/charts/near-price"> <a className="leading-6 text-gray-500"> ${dollarFormat(stats?.near_price ?? 0)}{' '} <span className="text-gray-400"> @{localFormat(stats?.near_btc_price ?? 0)} BTC </span>{' '} {stats?.change_24 > 0 ? ( <span className="text-neargreen text-sm"> ({dollarFormat(stats?.change_24)}%) </span> ) : ( <span className="text-red-500 text-sm"> ({dollarFormat(stats?.change_24)}%) </span> )} </a> </a> )} </div> </div> <div className="flex flex-row py-5 lg:pt-5 lg:px-0"> <div className="items-center flex justify-left mr-3 "> <img src={`${config.appUrl}images/market.svg`} alt={'marketCap'} className="h-9 w-9" width="24" height="24" /> </div> <div className="ml-2"> <p className="uppercase font-semibold text-gray-500 text-sm"> MARKET CAP </p> {isLoading ? ( <Skelton /> ) : ( <a href="/charts/market-cap"> <a className="leading-6 text-gray-400"> ${dollarFormat(stats?.market_cap ?? 0)} </a> </a> )} </div> </div> </div> </> )} <div className="flex flex-col lg:flex-col lg:items-stretch divide-y lg:divide-y lg:divide-x-0 md:pt-0 md:pb-0 md:px-5"> <div className="flex flex-row justify-between py-5 lg:pb-5 lg:px-0"> <div className="flex flex-row "> <div className="items-center flex justify-left mr-3 "> <img src={`${config.appUrl}images/transactions.svg`} alt={'transactions'} className="h-9 w-9" width="24" height="24" /> </div> <div className="ml-2"> <p className="uppercase font-semibold text-gray-500 text-sm"> TRANSACTIONS </p> {isLoading ? ( <Skelton /> ) : ( <p className="leading-6 text-gray-400"> {currency(Number(stats?.total_txns ?? 0))} </p> )} </div> </div> <div className="flex flex-col text-right"> <p className="uppercase font-semibold text-gray-500 text-sm"> {' '} GAS PRICE </p> {isLoading ? ( <Skelton /> ) : ( <p className="leading-6 text-gray-400"> {gasPrice(Number(stats?.gas_price ?? 0))} </p> )} </div> </div> <div className="flex flex-row justify-between align-center py-5 lg:pt-5 lg:px-0"> <div className="flex flex-row "> <div className="items-center flex justify-left mr-3 "> <img src={`${config.appUrl}images/pickaxe.svg`} alt={'activeValidator'} className="h-9 w-9" width="24" height="24" /> </div> <div className="ml-2"> <p className="uppercase font-semibold text-gray-500 text-sm"> ACTIVE VALIDATORS </p> {isLoading ? ( <Skelton /> ) : ( <a href="/charts/blocks"> <a className="leading-6 text-gray-400"> {localFormat(stats?.nodes_online ?? 0)} </a> </a> )} </div> </div> <div className="flex flex-col text-right"> <p className="uppercase font-semibold text-gray-500 text-sm"> AVG. BLOCK TIME </p> {isLoading ? ( <Skelton /> ) : ( <a className="leading-6 text-gray-400"> {stats?.avg_block_time ?? 0} s </a> )} </div> </div> </div> <div className="md:col-span-2 lg:col-span-1 flex flex-col lg:flex-col lg:items-stretch divide-y lg:divide-y lg:divide-x-0 md:pt-0 md:px-5"> <div className="flex-1 lg:px-0"> <p className="uppercase font-semibold text-gray-500 text-sm"> {' '} NEAR TRANSACTION HISTORY IN 14 DAYS </p> <div className="pl-2 pr-4 h-full"> {chartData ? ( <iframe srcDoc={iframeSrc} style={{ width: '100%', height: '100%', border: 'none', }} /> ) : ( <Skelton className="h-full w-full" /> )} </div> </div> </div> </div> </div> </div> <div className="py-8 relative"></div> </div> </Theme> ); } return MainComponent(props, context);