Skip to content

Commit

Permalink
Add user's session ID and new Slither command
Browse files Browse the repository at this point in the history
  • Loading branch information
Levironexe committed Oct 31, 2024
1 parent 360f08b commit 54b607c
Show file tree
Hide file tree
Showing 16 changed files with 3,800 additions and 202 deletions.
2,052 changes: 2,052 additions & 0 deletions Sample.sol

Large diffs are not rendered by default.

78 changes: 55 additions & 23 deletions app/api/backend.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,19 @@ function initializeSupabase() {
throw new Error('Missing Supabase credentials');
}

return createClient(supabaseUrl, supabaseKey);
return createClient(supabaseUrl, supabaseKey, {
auth: {
persistSession: false,
},
global: {
headers: {
'apikey': supabaseKey, // Add this
'Authorization': `Bearer ${supabaseKey}`, // And this
'Content-Type': 'application/json',
'Accept': '*/*'
}
}
});
}

// Initialize Express and middleware
Expand All @@ -55,7 +67,6 @@ function initializeExpress() {
const corsOptions = {
origin: ['http://localhost:3000', 'http://localhost:3001', 'https://blockscan-swin.vercel.app'],
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
};
app.use(cors(corsOptions));
Expand Down Expand Up @@ -344,7 +355,24 @@ function parseSlitherVulns(slitherVulns) {
return vulnsArray;
}


async function getMarkdownContent(filePath) {
try {
// Generate the markdown file
const resultPath = path.join(process.cwd(), 'app', 'api', 'result.md');

try {
const { stdout, stderr } = await execAsync(`slither "${filePath}" --checklist`);
// Return the output directly instead of writing to file
return stdout || '';
} catch (execError) {
// Even if there's an error, we might have useful output
return execError.stdout || execError.stderr || '';
}
} catch (error) {
console.error('Error generating markdown content:', error);
throw error;
}
}
// Main application setup
async function setupApplication() {
try {
Expand Down Expand Up @@ -386,7 +414,8 @@ async function setupApplication() {

// Contract analysis endpoint
app.post('/contract-analyze', async (req, res) => {
const timer = new Timer();
const sessionId = req.headers['x-session-id']; // Get from request header
const timer = new Timer();
timer.start();
let filePath;

Expand Down Expand Up @@ -419,27 +448,29 @@ async function setupApplication() {
const scanDuration = timer.stop();
const metrics = parseSlitherOutput(analysisResult.overview, scanDuration);
const vulnerabilities = parseSlitherVulns(analysisResult.vulns);

const markdownContent = await getMarkdownContent(filePath);
// Convert all numeric values explicitly for database
const dbMetrics = {
project_name: projectName,
total_contracts: parseInt(metrics.total_contracts) || 0,
source_lines: parseInt(metrics.source_lines) || 0,
assembly_lines: parseInt(metrics.assembly_lines) || 0,
scan_duration: scanDuration,
optimization_issues: parseInt(metrics.optimization_issues) || 0,
informational_issues: parseInt(metrics.informational_issues) || 0,
low_issues: parseInt(metrics.low_issues) || 0,
medium_issues: parseInt(metrics.medium_issues) || 0,
high_issues: parseInt(metrics.high_issues) || 0,
ercs: metrics.ercs || 'None'
};


// Save to database
const { data: metricsData, error: metricsError } = await supabase
.from('slither_metrics')
.insert([dbMetrics])
.select();
const { data: metricsData, error: metricsError } = await supabase
.from('slither_metrics')
.insert([{
project_name: projectName,
session_id: sessionId,
total_contracts: Number(metrics.total_contracts) || 0,
source_lines: Number(metrics.source_lines) || 0,
assembly_lines: Number(metrics.assembly_lines) || 0,
scan_duration: Number(scanDuration) || 0,
optimization_issues: Number(metrics.optimization_issues) || 0,
informational_issues: Number(metrics.informational_issues) || 0,
low_issues: Number(metrics.low_issues) || 0,
medium_issues: Number(metrics.medium_issues) || 0,
high_issues: Number(metrics.high_issues) || 0,
ercs: String(metrics.ercs || 'None'),
markdown_content: markdownContent || 'None',
}])
.select();

if (metricsError) throw metricsError;

Expand Down Expand Up @@ -487,7 +518,8 @@ async function setupApplication() {
},
vulnerabilities: vulnerabilities, //here I return the array of Vulnerabilities including names and severity
timestamp: new Date().toISOString(),
id: metricsData[0].id
id: metricsData[0].id,
markdown_content: markdownContent,
}
});

Expand Down
Binary file added app/api/result.md
Binary file not shown.
16 changes: 16 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -312,4 +312,20 @@ background: linear-gradient(45deg,#9333ea, #e70606);
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
.markdown-content {
padding: 1em;
font-family: Arial, sans-serif;
line-height: 1.6;
}

.markdown-content h2, .markdown-content h3, .markdown-content li, .markdown-content p {
color: #000000;
}

.markdown-content a {
color: rgb(231, 54, 6);
text-decoration: underline;
pointer-events: none;
}

/* END: search manufacturer styles */
19 changes: 10 additions & 9 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
import {CustomCursor, Footer, Navbar} from '@/components/index';

import { Footer, Navbar} from '@/components/index';
import { SessionProvider } from "./session_provider";

const geistSans = localFont({
src: "./fonts/GeistVF.woff",
variable: "--font-geist-sans",
weight: "100 900",
});

const geistMono = localFont({
src: "./fonts/GeistMonoVF.woff",
variable: "--font-geist-mono",
Expand All @@ -18,7 +19,6 @@ const geistMono = localFont({
export const metadata: Metadata = {
title: "BlockScan",
description: "An effective scanner for you.",

};

export default function RootLayout({
Expand All @@ -30,12 +30,13 @@ export default function RootLayout({
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-black`}
>
<CustomCursor/>
<Navbar/>
{children}
<Footer/>
>
<SessionProvider>
<Navbar/>
{children}
<Footer/>
</SessionProvider>
</body>
</html>
);
}
}
20 changes: 20 additions & 0 deletions app/session_provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// app/session-provider.tsx
'use client';

import { useEffect } from 'react';
import { v4 as uuidv4 } from 'uuid';

export function SessionProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
// Add console.log to debug
console.log('Current sessionId:', localStorage.getItem('sessionId'));

if (typeof window !== 'undefined' && !localStorage.getItem('sessionId')) {
const newSessionId = uuidv4();
localStorage.setItem('sessionId', newSessionId);
console.log('Created new sessionId:', newSessionId);
}
}, []);

return <>{children}</>;
}
6 changes: 4 additions & 2 deletions components/button/upload-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const UploadForm = ({style, title}: UploadFormProps) => {
const [messageName, setMessageName] = useState<string>('');
const {isScanning, startScanning, setIsScanning} = useScanning(); // Destructuring scanning state and key press handler from custom hook
const [openUpload, setOpenUpload] = useState(false);
const API_URL = process.env.NEXT_PUBLIC_API_URL;
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000' || 'http://localhost:5001';
const handleProjectNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setProjectName(event.target.value); // Update project name
};
Expand Down Expand Up @@ -70,7 +70,7 @@ const UploadForm = ({style, title}: UploadFormProps) => {

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();

const sessionId = localStorage.getItem('sessionId');
if (!projectName.trim()) {
setMessageName('Please enter a project name before uploading.');
return;
Expand All @@ -91,6 +91,7 @@ const UploadForm = ({style, title}: UploadFormProps) => {
const uploadResponse = await axios.post(`${API_URL}/contract-upload`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
'X-Session-Id': sessionId || '',
},
});

Expand All @@ -105,6 +106,7 @@ const UploadForm = ({style, title}: UploadFormProps) => {
}, {
headers: {
'Content-Type': 'application/json',
'X-Session-Id': sessionId || ''
},
});

Expand Down
10 changes: 4 additions & 6 deletions components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import Hero from './section/hero-section';
import Navbar from './section/navbar-section';
import Footer from './section/footer-section';
import CustomCursor from './utils/CustomCursor';
import CustomButton from './utils/CustomButton';
import RiliabilitySection from './section/reliability-section';
import YTRefSection from './section/youtube-reference-section';
Expand All @@ -17,17 +16,15 @@ import RadarChart from './chart/RadarChart';
import FAQ from './section/frequently-asked-question-section';
import {useScanning} from './utils/useScanning';
import CopyButton from './button/copy-button';
import Vulnerability from './section/vulnerability';
import ContractList from './section/contract-list-section';
import ScanningNotification from './section/scanning-notification';
import splitString from './utils/split-string'
import TokenBasicInfo from './section/token-basic-info';
import UploadForm from './button/upload-form';
import { Overview } from './section/overview';

import VulnerabilityList from './section/vulnerability-list'
export {
Hero,
CustomCursor,
Navbar,
Footer,
CustomButton,
Expand All @@ -42,11 +39,12 @@ export {
FAQ,
useScanning,
CopyButton,
Vulnerability,
ContractList,
ScanningNotification,
splitString,
TokenBasicInfo,
UploadForm,
Overview
VulnerabilityList,
Overview,

}
38 changes: 29 additions & 9 deletions components/section/contract-scan-result-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ interface AnalysisMetrics {
medium_issues: number;
high_issues: number;
ercs: string;
markdown_content: string;
}


interface AnalysisVulns {
vulnerability: string;
severity: string;
Expand Down Expand Up @@ -98,32 +100,50 @@ const calculateSafetyScore = (metrics: AnalysisMetrics): number => {

return Math.max(0, Math.min(100, baseScore - totalDeduction - (100*2.5*totalIssues/metrics.source_lines)));
};
// At the top of your file, create a Supabase client with proper config
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
auth: {
persistSession: false,
autoRefreshToken: false,
detectSessionInUrl: false
},
global: {
headers: {
'apikey': process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!}`,
'Content-Type': 'application/json',
'Accept': '*/*'
}
}
}
);

// Main Component
const ContractScanResult: React.FC = () => {
const [metrics, setMetrics] = useState<AnalysisMetrics | null>(null);
const [vulns, setVulns] = useState<AnalysisVulns[] | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

const [rawMarkdownContent, setRawMarkdownContent] = useState('');
useEffect(() => {
let isMounted = true;

const fetchResults = async () => {
const sessionId = localStorage.getItem('sessionId');

try {
setLoading(true);
setError(null);

const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

// Fetch metrics
const { data: metricsData, error: metricsError } = await supabase
.from('slither_metrics')
.select('*')
.select('*, markdown_content')
.order('created_at', { ascending: false })
.eq('session_id', sessionId)
.limit(1)
.single();

Expand All @@ -132,7 +152,7 @@ const ContractScanResult: React.FC = () => {

if (isMounted) {
setMetrics(metricsData);

setRawMarkdownContent(metricsData.markdown_content || '');
// Fetch vulnerabilities
const { data: vulnsData, error: vulnsError } = await supabase
.from('vulnerabilities')
Expand Down Expand Up @@ -288,7 +308,7 @@ const ContractScanResult: React.FC = () => {
{/* Main content area */}
<div className="flex flex-col lg:flex-row gap-8">
<div className="flex-[5] lg:w-1/3">
<ResultBody metrics={metrics} vulns={vulns} score={safetyScore}/>
<ResultBody metrics={metrics} vulns={vulns} score={safetyScore} raw_markdown_content={rawMarkdownContent}/>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 54b607c

Please sign in to comment.