Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
HPaulson committed Jul 12, 2024
1 parent 074def1 commit 1284c48
Show file tree
Hide file tree
Showing 11 changed files with 1,228 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
19 changes: 19 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
async redirects() {
return [
{
source: "/_error",
destination: "/map.html",
permanent: true,
},
{
source: "/_not-found",
destination: "/map.html",
permanent: true,
},
];
},
};

export default nextConfig;
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "deso-validator-map",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"react": "^18",
"react-dom": "^18",
"next": "14.2.5"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"postcss": "^8",
"tailwindcss": "^3.4.1"
}
}
8 changes: 8 additions & 0 deletions postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};

export default config;
76 changes: 76 additions & 0 deletions public/map.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.Default.css" />
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.markercluster/dist/leaflet.markercluster.js"></script>
<title>Deso Validator Map</title>

<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
}

#map {
height: 70vh;
}
</style>
</head>

<body>
<h2>Deso Validator Map</h2>
<div id="map"></div>
<h2 id="heading">Included Validators (Loading...)</h2>
<div id="results">
</div>


<script>
getGeolocation().then(() => {
document.getElementById('heading').innerHTML = `Included Validators (${document.getElementById('results').childElementCount})`;
}).catch((error) => {
document.getElementById('heading').innerHTML = 'Failed to load validators.';
});

async function getGeolocation() {
const map = L.map('map').setView([20, 0], 3);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {}).addTo(map);

const markers = L.markerClusterGroup();

markers.clearLayers();
document.getElementById('results').innerHTML = '';



const data = await getData()
data.forEach((validator) => {
console.log(validator);
const marker = L.marker([validator.location.lat, validator.location.lon]);
const el = `<strong>${validator.name}</strong>: ${validator.location.city}, ${validator.location.regionName}, ${validator.location.country} (${validator.location.isp})`
marker.bindPopup(el);
markers.addLayer(marker);
map.addLayer(markers);
const result = document.createElement('div');
result.innerHTML = el
document.getElementById('results').appendChild(result);

})


}

async function getData() {
const response = await fetch(`${window.location.origin}/api`);
return await response.json();
}
</script>
</body>

</html>
46 changes: 46 additions & 0 deletions src/app/api/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use server";

import { NextRequest } from "next/server";

async function GET(request: NextRequest): Promise<Response> {
try {
const graphQl = await fetch("https://graphql-prod.deso.com/graphql", {
credentials: "include",
headers: {
"content-type": "application/json",
},
body: '{"operationName":"GetValidators","variables":{"viewerPublicKey":"","first":100,"before":null,"after":null,"last":null},"query":"query GetValidators($viewerPublicKey: String!, $first: Int, $after: Cursor, $last: Int, $before: Cursor) {\\n validatorStats(\\n first: $first\\n after: $after\\n before: $before\\n last: $last\\n orderBy: VALIDATOR_RANK_ASC\\n ) {\\n totalCount\\n pageInfo {\\n hasNextPage\\n hasPreviousPage\\n endCursor\\n startCursor\\n __typename\\n }\\n nodes {\\n ...ValidatorsTableRow\\n __typename\\n }\\n __typename\\n }\\n}\\n\\nfragment Validator on ValidatorEntry {\\n validatorPkid\\n domains\\n jailedAtEpochNumber\\n lastActiveAtEpochNumber\\n totalStakeAmountNanos\\n delegatedStakeCommissionBasisPoints\\n disableDelegatedStake\\n votingPublicKey\\n votingAuthorization\\n validatorStats {\\n percentTotalStake\\n validatorRank\\n __typename\\n }\\n account {\\n username\\n publicKey\\n description\\n extraData\\n viewerStakeRewards: validatorStakeRewards(\\n filter: {staker: {publicKey: {equalTo: $viewerPublicKey}}}\\n ) {\\n totalCount\\n nodes {\\n stakerPkid\\n rewardNanos\\n rewardMethod\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n stakeEntries {\\n totalCount\\n __typename\\n }\\n viewerStake: stakeEntries(\\n filter: {staker: {publicKey: {equalTo: $viewerPublicKey}}}\\n ) {\\n nodes {\\n stakeAmountNanos\\n rewardMethod\\n staker {\\n publicKey\\n desoBalance {\\n publicKey\\n balanceNanos\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n __typename\\n}\\n\\nfragment ValidatorsTableRow on ValidatorStat {\\n validatorPkid\\n validatorRank\\n percentTotalStake\\n validatorEntry {\\n ...Validator\\n __typename\\n }\\n __typename\\n}"}',
method: "POST",
});

const data = await graphQl.json();
let validators: {
name: string;
domain: string;
location: any;
}[] = data.data.validatorStats.nodes.map((node: any) => {
return {
name: node.validatorEntry.account.username,
domain: node.validatorEntry.domains[0].split(":")[0],
};
});

for (let i = 0; i < validators.length; i++) {
const location = await getLocation(validators[i].domain);
validators[i].location = location ? location : "Unknown";
}

return new Response(JSON.stringify(validators), {
status: 200,
});
} catch (error) {
return new Response("Error: " + error);
}
}

async function getLocation(domain: string) {
const response = await fetch(`http://ip-api.com/json/${domain}`);
return await response.json();
}

export { GET };
16 changes: 16 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const metadata = {
title: 'Next.js',
description: 'Generated by Next.js',
}

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
11 changes: 11 additions & 0 deletions src/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";
import { useEffect } from "react";
import { redirect } from "next/navigation";

export default function Custom404() {
useEffect(() => {
redirect("/map.html");
});

return null;
}
20 changes: 20 additions & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Config } from "tailwindcss";

const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
"gradient-conic":
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
},
},
},
plugins: [],
};
export default config;
26 changes: 26 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
Loading

0 comments on commit 1284c48

Please sign in to comment.