Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions components/ApiStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { useState } from 'react';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';

interface ApiStatusProps {
apiUrl: string;
status: 'normal' | 'degraded' | 'disruption';
}

const statusColors = {
normal: 'bg-green-500',
degraded: 'bg-yellow-500',
disruption: 'bg-red-500',
};

export const ApiStatus: React.FC<ApiStatusProps> = ({ apiUrl, status }) => {
const [copied, setCopied] = useState(false);

const copyToClipboard = () => {
navigator.clipboard.writeText(apiUrl).then(() => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});
};

return ( //flex j p-4 bg-gray-100 rounded-lg shadow-md
<Card
className="mb-8 ustify-center items-center gap-8 md:flex-row"
>
<CardHeader>
<CardTitle>API Status</CardTitle>
</CardHeader>
<CardContent>
<div className="flex w-full flex-col content-around ">
<div className="flex items-center justify-between space-x-4">
<div className="flex items-center flex-grow">
<span className="mr-2 ">Mainnet</span>
<input
type="text"
value={apiUrl}
readOnly
className="border p-2 rounded w-full"
/>
<button onClick={copyToClipboard} className="ml-2 p-2 bg-blue-500 text-white rounded">
{copied ? 'Copied!' : 'Copy'}
</button>
</div>
<div
className={`w-4 h-4 rounded-full ${statusColors[status]}`}
title={`Status: ${status}`}
/>
</div>
</div>
</CardContent>
</Card>
);
};
3 changes: 3 additions & 0 deletions components/Benchmarks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ const Benchmarks = React.forwardRef<
605.16ms
</div>
{/**
*
* TODO: We will add these in later
*
<div className="col-span-1 border-r border-neutral-200 py-2 pb-3 pl-4 dark:border-neutral-50/20 max-lg:border-b md:pl-8 lg:pb-6">
UltraSoundMoney
</div>
Expand Down
18 changes: 15 additions & 3 deletions components/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@ import { Benchmarks } from '@/components/Benchmarks';
import { buttonDefaults } from '@/components/ui/button';
import { Card, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { cn } from '@/lib/utils';

import { Globe } from './globe';
import { CommandLineIcon, CursorArrowRaysIcon, ServerStackIcon, ShieldCheckIcon } from './icons';
import { ApiStatus } from './ApiStatus';

const stats = [
{ id: 1, name: 'Transactions every 24 hours', value: '$44 million' },
{ id: 2, name: 'Validators Registered', value: '909,802' },
{ id: 3, name: 'Uptime', value: '99.9999%' },
]

export function Home() {
return (


<main className="relative w-full max-w-full">

<div className="mx-auto mt-4 max-w-[1180px] px-6 md:mt-16">
<div className="hero-texture mb-6 flex w-full flex-col justify-between gap-8 rounded-lg p-4 text-neutral-950 shadow-sm dark:text-neutral-50 md:flex-row md:p-8">
<div className="flex max-w-[540px] flex-col items-start space-y-1.5">
Expand Down Expand Up @@ -53,8 +63,8 @@ export function Home() {
'flex-grow border border-neutral-200/30 text-neutral-900 hover:bg-neutral-100/30 dark:text-neutral-50',
])}
>
<Link href="https://github.com/manifoldfinance" target="_blank">
View on GitHub
<Link href="https://forums.manifoldfinance.com" target="_blank">
🌐 Community Forums
</Link>
</Slot>
</div>
Expand Down Expand Up @@ -114,6 +124,8 @@ export function Home() {
</Card>
</div>

<ApiStatus apiUrl="https://api.securerpc.com/v1" status="normal" />

<Benchmarks />
</div>

Expand Down
161 changes: 161 additions & 0 deletions components/globe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
"use client";

import createGlobe from "cobe";
import { useEffect, useRef, useState } from "react";

import { useMediaQuery } from "@/lib/hooks/use-media-query";

const SIZE = 350;

// https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/By_example/Detect_WebGL
function isWebGLContext() {
const canvas = document.createElement("canvas");
const gl =
canvas.getContext("webgl") || canvas.getContext("experimental-webgl");

return gl instanceof WebGLRenderingContext;
}

export function Globe() {
const canvasRef = useRef<HTMLCanvasElement>(null);
const prefersReducedMotion = useMediaQuery(
"(prefers-reduced-motion: reduce)",
);
const [disabledWebGL, setDisabledWebGL] = useState(false);

useEffect(() => {
let phi = 0;
if (!canvasRef.current) return;
if (!document) return;
if (!isWebGLContext()) {
setDisabledWebGL(true);
return;
}

const globe = createGlobe(canvasRef.current, {
devicePixelRatio: 2,
width: SIZE * 2,
height: SIZE * 2,
phi: 0,
theta: 0,
dark: 1,
diffuse: 1.2,
mapSamples: 16000,
mapBrightness: 6,
baseColor: [0.3, 0.3, 0.3],
markerColor: [1, 1, 1],
glowColor: [1, 1, 1],
markers: [
// AMS
{ location: [52.3676, 4.9041], size: 0.05 },
// IAD
{ location: [39.0438, -77.4874], size: 0.05 },
// JNB
{ location: [-26.2041, 28.0473], size: 0.05 },
// HKG
{ location: [22.3193, 114.1694], size: 0.05 },
// SYD
{ location: [-33.8688, 151.2093], size: 0.05 },
// GRU
{ location: [-23.5558, -46.6396], size: 0.05 },
// ARN
{ location: [59.6519, 17.9186], size: 0.05 },
// ATL
{ location: [33.6407, -84.4277], size: 0.05 },
// BOG
{ location: [4.711, -74.0721], size: 0.05 },
// BOM
{ location: [19.0896, 72.8656], size: 0.05 },
// CDG
{ location: [49.0097, 2.5479], size: 0.05 },
// DEN
{ location: [39.8561, -104.6737], size: 0.05 },
// DFW
{ location: [32.8998, -97.0403], size: 0.05 },
// EWR
{ location: [40.6895, -74.1745], size: 0.05 },
// EZE
{ location: [-34.8226, -58.5336], size: 0.05 },
// FRA
{ location: [50.0349, 8.5622], size: 0.05 },
// GDI
{ location: [20.6752, -103.34], size: 0.05 },
// LAX
{ location: [33.9416, -118.4085], size: 0.05 },
// MAD
{ location: [40.4168, -3.7038], size: 0.05 },
// MIA
{ location: [25.7617, -80.1918], size: 0.05 },
// NRT
{ location: [35.6895, 139.6917], size: 0.05 },
// ORD
{ location: [41.9742, -87.9073], size: 0.05 },
// OTP
{ location: [44.4268, 26.1025], size: 0.05 },
// PHX
{ location: [33.4484, -112.074], size: 0.05 },
// QRO
{ location: [20.5881, -100.3899], size: 0.05 },
// SCL
{ location: [-33.4489, -70.6693], size: 0.05 },
// SEA
{ location: [47.6062, -122.3321], size: 0.05 },
// SIN
{ location: [1.3521, 103.8198], size: 0.05 },
// SJC
{ location: [37.3541, -121.9552], size: 0.05 },
// WAW
{ location: [52.2297, 21.0122], size: 0.05 },
// YUL
{ location: [45.5017, -73.5673], size: 0.05 },
// YYZ
{ location: [43.6511, -79.347], size: 0.05 },
],
onRender: (state) => {
// Called on every animation frame.
// `state` will be an empty object, return updated params.
if (!prefersReducedMotion) {
state.phi = phi;
phi += 0.003;
}
},
});

setTimeout(() => {
const canvas = canvasRef.current;
if (!canvas) return;
canvas.style.opacity = "1";
});

return () => {
globe.destroy();
};
}, [prefersReducedMotion]);

if (disabledWebGL) {
return (
<div className="flex items-center justify-center">
<p className="text-muted-foreground text-sm">
<span className="font-semibold">Hint</span>: enable{" "}
<span className="font-semibold">WebGL</span> to render the globe.
</p>
</div>
);
}

return (
<div className="flex justify-center">
<canvas
ref={canvasRef}
style={{
width: SIZE,
height: SIZE,
maxWidth: "100%",
aspectRatio: 1,
opacity: 0,
transition: "opacity 1s ease",
}}
/>
</div>
);
}
28 changes: 28 additions & 0 deletions lib/hooks/use-media-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useEffect, useState } from "react";

type MediaQuery = string | number;

export function useMediaQuery(query: MediaQuery): boolean {
const [matches, setMatches] = useState<boolean>(false);

useEffect(() => {
const mediaQueryList = window.matchMedia(String(query));

const handleChange = (event: MediaQueryListEvent) => {
setMatches(event.matches);
};

// Initial check
setMatches(mediaQueryList.matches);

// Add listener for changes
mediaQueryList.addEventListener("change", handleChange);

// Clean up listener on unmount
return () => {
mediaQueryList.removeEventListener("change", handleChange);
};
}, [query]);

return matches;
}
11 changes: 7 additions & 4 deletions mkBuildInfo.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
const path = require('path')
const fs = require('fs')
const fetch = require('node-fetch')
import path from 'path';
import fs from 'fs';
import fetch from 'node-fetch';

// @note this should be `NEXT_PUBLIC_COMMIT_SHA` for nextjs
const commit = process.env.COMMIT_SHA

const github_org = 'manifoldfinacne'
const github_repo = 'securerpc-frontend'

async function getCommit() {
if (!commit) return `No COMMIT_SHA environment variable set.`
try {
Expand All @@ -30,7 +33,7 @@ async function go() {
}

// @note this is different for nextjs, should be in dir: `.next/~`
fs.writeFileSync(path.join(__dirname, '../public/build/info.json'), JSON.stringify(buildInfo, null, 2))
fs.writeFileSync(path.join('.next/build-manifest.json'), JSON.stringify(buildInfo, null, 2))
console.log('build info generated', buildInfo)
}
go()
Loading
Loading