diff --git a/.gitignore b/.gitignore index 5ef6a52..4736730 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,9 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# blockchain / hardhat +blockchain/node_modules +blockchain/artifacts +blockchain/cache +blockchain/typechain-types diff --git a/README.md b/README.md index e215bc4..23f4465 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,110 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# πŸ”— LexiChain: Professional BFSI Document Intelligence Platform -## Getting Started +> **Status**: Production-Ready PFE Project +> **Target Audience**: Banking, Financial Services, and Insurance (BFSI) Institutions +> **Key Innovation**: Hybrid integration of Generative AI (Gemini) and Ethereum Blockchain (DocumentRegistry) -First, run the development server: +--- -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` +## πŸ›οΈ 1. Project Vision & Mission -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +**LexiChain** is a next-generation platform designed to bridge the gap between complex legal documentation and user-centric transparency. In the traditional BFSI sector, contracts are often "black boxes"β€”static PDFs that are hard to understand and easy to misplace. -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +LexiChain transforms these static documents into **dynamic, searchable, and cryptographically secured assets**. Our mission is to automate document analysis while providing an immutable "Digital Notary" service that guarantees trust between financial institutions and their clients. -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +--- -## Learn More +## πŸ“‰ 2. Market Problem & Opportunity -To learn more about Next.js, take a look at the following resources: +The project addresses several critical "pain points" in the current financial landscape: -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +1. **The Transparency Gap**: Clients often sign contracts without understanding specific exclusion clauses or renewal dates. +2. **Operational Friction**: Insurance agents spend thousands of hours manually checking PDFs for compliance and signature presence. +3. **The Integrity Risk**: In legal disputes, proving that a specific version of a document was the one actually signed can be difficult and expensive. +4. **Information Overload**: Users are overwhelmed by the volume of fine print in modern banking. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +--- -## Deploy on Vercel +## πŸš€ 3. Core Feature Deep-Dive -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +### 🧠 A. The AI "Analyst" Module (Intelligence Layer) -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +LexiChain uses **Google Gemini 2.0 Flash** to act as a virtual legal analyst. + +- **Smart Ingestion**: Uses high-fidelity OCR to read digital PDFs and scanned images. +- **Automated Extraction**: Identifies 15+ key data points (Amount, Interest Rate, Parties, Expiration Dates, Clauses) instantly. +- **RAG (Retrieval-Augmented Generation)**: The most advanced part of the AI. It breaks the contract into "Semantic Chunks" and stores them in a vector index. This allows the user to **Chat with their Contract** in natural language. +- **Intelligent Validation**: The AI automatically flags missing signatures, inconsistent dates, or high-risk clauses before the document is finalized. + +### ⛓️ B. The Blockchain "Notary" Module (Security Layer) + +LexiChain uses a private/public hybrid blockchain strategy to ensure **Non-Repudiation**. + +- **Proof of Existence (PoE)**: We generate a SHA-256 hash (digital fingerprint) for every file. This hash is sent to a **Solidity Smart Contract** on the Ethereum network. +- **Immutable Timestamping**: The blockchain records exactly _when_ the document was uploaded. This cannot be changed by any administrator, providing a "Golden Record." +- **Metadata Leakage Prevention**: We only store the **Hash** on-chain. No personal data (names, amounts) ever touches the public blockchain, ensuring 100% GDPR compliance. +- **The Explorer**: A built-in "Verification Panel" that allows any auditor to verify a file's integrity by comparing its current hash with the on-chain record. + +--- + +## πŸ—οΈ 4. Technical Architecture + +### **Architecture Pattern: Feature-Sliced Design (FSD)** + +The project follows **FSD principles**, which is a modern architectural pattern for scaling large applications. + +- **Layers**: App, Pages, Features, Entities, Shared. +- **Benefits**: Decouples the Blockchain logic from the AI logic, making the system highly maintainable and ready for enterprise scaling. + +### **The Stack** + +| Layer | Technology | Rationale | +| :------------- | :----------------------- | :-------------------------------------------------------------------------------------------------- | +| **Frontend** | Next.js 15 (React) | High performance, SEO-friendly, and supports React Server Components. | +| **Backend** | Server Actions (Next.js) | Allows for secure, server-side blockchain signing and API communication without a separate backend. +| **LLM** | Gemini | Unbeatable speed and context window size for long legal documents. | +| **Blockchain** | Solidity / Hardhat | Ethereum-compatible smart contracts for industry-standard security. | +| **Database** | PostgreSQL + Prisma | Robust relational storage for user data and contract metadata. | +| **Identity** | Clerk | Enterprise-grade security for user authentication and session management. | + +--- + +## πŸ”’ 5. Security & Privacy Philosophy + +LexiChain is built with a **"Security by Design"** approach: + +- **Hashing vs. Storage**: We never store the actual document on the blockchain. The blockchain only holds the "Proof," while the "Content" remains in encrypted cloud storage. +- **Server-Side Signing**: Users don't need a crypto wallet (MetaMask). Our backend acts as a **Trusted Custodian**, signing transactions with a secure private key hidden in environment variables. +- **Authentication Hooks**: Access to contracts is strictly controlled via Clerk Auth, ensuring users only see their own data. + +--- + +## 🎨 6. UX/UI & Aesthetics + +The application features a **"Premium Glassmorphism"** design system. + +- **Why?**: In BFSI, the interface must convey **Trust, Modernity, and Clarity**. +- **Design Tokens**: We use vibrant gradients, subtle blurs, and micro-animations to make the complex task of contract management feel light and intuitive. +- **Theme Awareness**: The UI is optimized for both Light and Dark modes, adapting to the professional environment of the user. + +--- + +## 🌟 7. Why this is a 10/10 PFE Project + +LexiChain isn't just a simple web app; it is a **Multidisciplinary Innovation**: + +1. **AI Innovation**: Moving beyond simple text extraction to a conversational RAG system. +2. **Blockchain Innovation**: Implementing a production-ready Document Registry that solves real-world legal issues. +3. **Architectural Integrity**: Using FSD and Clean Code principles usually found in senior-level software engineering. +4. **Market Readiness**: The solution is directly applicable to banks and insurance companies looking to digitalize their workflow. + +--- + +## πŸ“š 8. Glossary for NotebookLM + +- **BFSI**: Banking, Financial Services, and Insurance. +- **RAG (Retrieval-Augmented Generation)**: A technique that allows AI to answer questions based _only_ on the provided documents, preventing "hallucinations." +- **Smart Contract**: A programmable contract that executes automatically when conditions are met. +- **SHA-256**: A one-way cryptographic function. If you change 1 bit of a file, the entire hash changes. +- **Hardhat**: A professional development environment for Ethereum software. +- **Sepolia**: The public test network used to simulate the real Ethereum blockchain. diff --git a/app/(dashboard)/blockchain/layout.tsx b/app/(dashboard)/blockchain/layout.tsx new file mode 100644 index 0000000..f34cac3 --- /dev/null +++ b/app/(dashboard)/blockchain/layout.tsx @@ -0,0 +1,14 @@ +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Blockchain Explorer | LexiChain", + description: "View on-chain proofs and verify document integrity", +}; + +export default function BlockchainLayout({ + children, +}: { + children: React.ReactNode; +}) { + return <>{children}; +} diff --git a/app/(dashboard)/blockchain/page.tsx b/app/(dashboard)/blockchain/page.tsx new file mode 100644 index 0000000..fe64db3 --- /dev/null +++ b/app/(dashboard)/blockchain/page.tsx @@ -0,0 +1,532 @@ +"use client"; + +import React, { useEffect, useState, useCallback } from "react"; +import { motion } from "motion/react"; +import { + Link2, + Shield, + Activity, + Hash, + Clock, + FileText, + CheckCircle2, + Search, + RefreshCw, + ExternalLink, + Blocks, + Copy, + Check, + AlertCircle, + Upload, +} from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + getBlockchainTransactions, + getBlockchainStats, + verifyDocumentHashOnBlockchain, + registerContractOnBlockchain, +} from "@/features/blockchain/api/blockchain.action"; +import { getContracts } from "@/features/contracts/api/contract.action"; +import type { + BlockchainTransactionView, + BlockchainStats, +} from "@/lib/services/blockchain.types"; +import { toast } from "sonner"; + +// ═══════════════════════════════════════════════════════════════ +// Blockchain Explorer Page +// ═══════════════════════════════════════════════════════════════ + +export default function BlockchainExplorerPage() { + const [transactions, setTransactions] = useState([]); + const [stats, setStats] = useState(null); + const [loading, setLoading] = useState(true); + const [verifyHash, setVerifyHash] = useState(""); + const [verifyResult, setVerifyResult] = useState<{ + exists: boolean; + timestamp: number; + depositor: string; + } | null>(null); + const [verifying, setVerifying] = useState(false); + const [copiedTx, setCopiedTx] = useState(null); + const [unregisteredContracts, setUnregisteredContracts] = useState< + Array<{ id: string; title: string | null; fileName: string }> + >([]); + const [registeringId, setRegisteringId] = useState(null); + + const loadData = useCallback(async () => { + setLoading(true); + try { + const [txResult, statsResult, contractsResult] = await Promise.all([ + getBlockchainTransactions(), + getBlockchainStats(), + getContracts({ status: "COMPLETED" }), + ]); + + if (txResult.success && txResult.transactions) { + setTransactions(txResult.transactions); + } + if (statsResult.success && statsResult.stats) { + setStats(statsResult.stats); + } + + // Find contracts not yet on blockchain + if (contractsResult.success && contractsResult.contracts) { + const registered = new Set( + txResult.transactions?.map((tx) => tx.contractId) ?? [] + ); + const unregistered = contractsResult.contracts + .filter( + (c: { id: string; txHash?: string | null; status: string }) => + !c.txHash && !registered.has(c.id) && c.status === "COMPLETED" + ) + .map((c: { id: string; title: string | null; fileName: string }) => ({ + id: c.id, + title: c.title, + fileName: c.fileName, + })); + setUnregisteredContracts(unregistered); + } + } catch (error) { + console.error("Failed to load blockchain data:", error); + } finally { + setLoading(false); + } + }, []); + + useEffect(() => { + loadData(); + }, [loadData]); + + const handleVerify = async () => { + if (!verifyHash.trim()) return; + setVerifying(true); + setVerifyResult(null); + try { + const result = await verifyDocumentHashOnBlockchain(verifyHash.trim()); + if (result.success && result.verification) { + setVerifyResult(result.verification); + } else { + toast.error(result.error || "Verification failed"); + } + } catch { + toast.error("Failed to verify hash"); + } finally { + setVerifying(false); + } + }; + + const handleRegister = async (contractId: string) => { + setRegisteringId(contractId); + try { + const result = await registerContractOnBlockchain(contractId); + if (result.success) { + toast.success("Contract registered on blockchain!"); + await loadData(); + } else { + toast.error(result.error || "Registration failed"); + } + } catch { + toast.error("Failed to register on blockchain"); + } finally { + setRegisteringId(null); + } + }; + + const copyToClipboard = (text: string) => { + navigator.clipboard.writeText(text); + setCopiedTx(text); + setTimeout(() => setCopiedTx(null), 2000); + }; + + const formatTimestamp = (iso: string) => { + return new Date(iso).toLocaleString(); + }; + + const truncateHash = (hash: string, chars = 8) => { + if (!hash || hash.length <= chars * 2 + 3) return hash; + return `${hash.slice(0, chars + 2)}...${hash.slice(-chars)}`; + }; + + return ( +
+ {/* Page Header */} + +
+

+
+ +
+ Blockchain Explorer +

+

+ View on-chain proofs and verify document integrity +

+
+ +
+ + {/* Stats Cards */} + + } + label="Verified Documents" + value={stats?.totalVerified?.toString() ?? "0"} + color="emerald" + /> + } + label="Latest Block" + value={stats?.latestBlockNumber ? `#${stats.latestBlockNumber.toLocaleString()}` : "β€”"} + color="blue" + /> + } + label="Network" + value={stats?.networkName ? `${stats.networkName} ${stats.chainId ? `(Chain ${stats.chainId})` : ""}` : "Not Configured"} + color={stats?.networkStatus === "connected" ? "emerald" : "red"} + badge={stats?.networkStatus === "connected" ? "● Live" : "● Offline"} + /> + } + label="Wallet" + value={stats?.walletAddress ? truncateHash(stats.walletAddress, 6) : "β€”"} + color="violet" + /> + + + {/* Unregistered contracts */} + {unregisteredContracts.length > 0 && ( + +
+ +

+ {unregisteredContracts.length} contract{unregisteredContracts.length > 1 ? "s" : ""} not yet on blockchain +

+
+
+ {unregisteredContracts.map((contract) => ( +
+
+ + + {contract.title || contract.fileName} + +
+ +
+ ))} +
+
+ )} + +
+ {/* Transactions List */} + +
+

+ + Transaction History +

+

+ All documents registered on the blockchain +

+
+ + {loading ? ( +
+ + Loading transactions... +
+ ) : transactions.length === 0 ? ( +
+ +

No transactions yet

+

+ Upload and analyze a contract to register it on-chain +

+
+ ) : ( +
+ {transactions.map((tx, idx) => ( + +
+
+
+ + + {tx.contractTitle || tx.contractFileName} + + + {tx.status} + +
+ +
+
+ + Fingerprint: {truncateHash(tx.documentHash, 12)} + +
+
+ + Tx: {truncateHash(tx.txHash, 12)} + +
+
+ + Block #{tx.blockNumber.toLocaleString()} +
+
+ + {formatTimestamp(tx.blockTimestamp)} +
+
+
+ +
+ + {tx.network === "sepolia" ? "Sepolia" : "Hardhat"} + + {tx.explorerUrl && ( + + Etherscan + + + )} +
+
+
+ ))} +
+ )} +
+ + {/* Verification Panel */} + +
+

+ + Verify Document +

+

+ Check if a document hash exists on-chain +

+
+ +
+
+ +