From 26f99f3fa914a9c858b81d2ebc7271d2e73ef48a Mon Sep 17 00:00:00 2001 From: NeonTechnoX <89855167+NeonTechno@users.noreply.github.com> Date: Sun, 11 Oct 2026 15:12:33 +0000 Subject: [PATCH 1/3] feat: add dedicated DRP network explorer app --- explorer/app/globals.css | 35 ++++++++++ explorer/app/layout.tsx | 15 +++++ explorer/app/page.tsx | 95 +++++++++++++++++++++++++++ explorer/next-env.d.ts | 5 ++ explorer/package.json | 21 ++++++ explorer/tsconfig.json | 35 ++++++++++ src/app/api/explorer/summary/route.ts | 2 +- 7 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 explorer/app/globals.css create mode 100644 explorer/app/layout.tsx create mode 100644 explorer/app/page.tsx create mode 100644 explorer/next-env.d.ts create mode 100644 explorer/package.json create mode 100644 explorer/tsconfig.json diff --git a/explorer/app/globals.css b/explorer/app/globals.css new file mode 100644 index 0000000..abdc2ca --- /dev/null +++ b/explorer/app/globals.css @@ -0,0 +1,35 @@ +:root { + color-scheme: dark; + --bg: #070a12; + --panel: #101724; + --border: rgba(174, 199, 220, .15); + --text: #edf7fb; + --muted: #94a7b7; + --teal: #00e5cc; + --blue: #6aa9ff; +} +* { box-sizing: border-box; } +body { margin: 0; background: radial-gradient(ellipse at 15% 0%, rgba(0,229,204,.11), transparent 38%), radial-gradient(ellipse at 90% 10%, rgba(106,169,255,.12), transparent 34%), var(--bg); color: var(--text); font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; } +a { color: var(--teal); text-decoration: none; } +a:hover { text-decoration: underline; } +main { width: min(1180px, calc(100% - 32px)); margin: 0 auto; padding: 36px 0 64px; } +.eyebrow { color: var(--teal); text-transform: uppercase; letter-spacing: .2em; font-size: .72rem; font-weight: 800; } +h1 { margin: 12px 0; font-size: clamp(2.3rem, 6vw, 4.5rem); letter-spacing: -.055em; line-height: 1.03; } +.lede { color: var(--muted); max-width: 760px; line-height: 1.7; } +.topline { display:flex; justify-content:space-between; align-items:center; gap:18px; flex-wrap:wrap; margin-bottom:28px; } +.status { border:1px solid var(--border); border-radius:999px; padding:9px 13px; font-size:.8rem; color:var(--muted); } +.grid { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:12px; margin:28px 0; } +.panel { border:1px solid var(--border); border-radius:18px; background:linear-gradient(140deg,rgba(255,255,255,.045),rgba(255,255,255,.018)); padding:18px; min-width:0; } +.panel h2 { font-size:1rem; margin:0 0 14px; } +.metric-label { color:var(--muted); font-size:.76rem; text-transform:uppercase; letter-spacing:.08em; } +.metric-value { font-size:1.25rem; font-weight:800; margin-top:8px; overflow-wrap:anywhere; } +.section-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; } +.list { display:grid; gap:10px; } +.item { padding:12px 0; border-top:1px solid var(--border); min-width:0; } +.item:first-child { border-top:0; padding-top:0; } +.item-title { font-weight:700; overflow-wrap:anywhere; } +.item-meta { margin-top:5px; color:var(--muted); font-size:.78rem; line-height:1.55; overflow-wrap:anywhere; } +.empty { color:var(--muted); font-size:.88rem; line-height:1.6; } +.error { color:#ffc3c3; } +footer { margin-top:26px; padding-top:20px; border-top:1px solid var(--border); color:var(--muted); font-size:.78rem; line-height:1.6; } +@media (max-width: 760px) { .grid { grid-template-columns:repeat(2,minmax(0,1fr)); } .section-grid { grid-template-columns:1fr; } main { width:min(100% - 24px,1180px); padding-top:24px; } .panel { padding:15px; } } diff --git a/explorer/app/layout.tsx b/explorer/app/layout.tsx new file mode 100644 index 0000000..a30939b --- /dev/null +++ b/explorer/app/layout.tsx @@ -0,0 +1,15 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "DRP Explorer | Decentralized Rights Protocol", + description: "Explore DRP network activity, blocks, transactions, and verification infrastructure using live API data.", +}; + +export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { + return ( + + {children} + + ); +} diff --git a/explorer/app/page.tsx b/explorer/app/page.tsx new file mode 100644 index 0000000..2c6820b --- /dev/null +++ b/explorer/app/page.tsx @@ -0,0 +1,95 @@ +export const dynamic = "force-dynamic"; + +type ApiRecord = Record; +type ApiResult = { data: T | null; error: string | null }; + +const API_BASE = (process.env.DRP_EXPLORER_API_URL || "https://api.decentralizedrights.com/api/v1/explorer").replace(/\/$/, ""); + +async function load(path: string): Promise> { + try { + const response = await fetch(`${API_BASE}${path}`, { + cache: "no-store", + signal: AbortSignal.timeout(5000), + headers: { accept: "application/json" }, + }); + if (!response.ok) return { data: null, error: `API returned HTTP ${response.status}` }; + return { data: await response.json() as T, error: null }; + } catch { + return { data: null, error: "The DRP API is currently unreachable. No live values are being substituted." }; + } +} + +function isRecord(value: unknown): value is ApiRecord { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function valueText(value: unknown): string { + if (value === null || value === undefined || value === "") return "—"; + if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return String(value); + try { return JSON.stringify(value) ?? String(value); } catch { return String(value); } +} + +function first(item: ApiRecord, keys: string[]): unknown { + for (const key of keys) if (item[key] !== undefined && item[key] !== null) return item[key]; + return undefined; +} + +function ListSection({ title, items, error, kind }: { title: string; items: ApiRecord[] | null; error: string | null; kind: "block" | "transaction" | "activity" }) { + return ( +
+

{title}

+ {error &&

{error}

} + {!error && (!items || items.length === 0) &&

No records were returned by the API.

} + {items && items.length > 0 &&
{items.slice(0, 8).map((item, index) => { + const titleValue = kind === "block" + ? first(item, ["block_number", "number", "height"]) + : kind === "transaction" + ? first(item, ["tx_hash", "hash", "id"]) + : first(item, ["title", "type", "id"]); + const meta = kind === "block" + ? [first(item, ["block_hash", "hash"]), first(item, ["transaction_count", "transactions"]), first(item, ["timestamp"])].filter(v => v !== undefined).map(valueText).join(" · ") + : kind === "transaction" + ? [first(item, ["status"]), first(item, ["type", "token_type"]), first(item, ["timestamp"])].filter(v => v !== undefined).map(valueText).join(" · ") + : [first(item, ["description"]), first(item, ["actor"]), first(item, ["timestamp"])].filter(v => v !== undefined).map(valueText).join(" · "); + return
{valueText(titleValue)}
{meta || "Record returned; additional fields may be available in the API response."}
; + })}
} +
+ ); +} + +export default async function ExplorerPage() { + const [statsResult, blocksResult, transactionsResult, activityResult] = await Promise.all([ + load("/stats"), + load("/blocks?limit=8"), + load("/transactions?limit=8"), + load("/activity?limit=8"), + ]); + const stats = isRecord(statsResult.data) ? statsResult.data : null; + const metrics = stats ? Object.entries(stats).filter(([, value]) => ["string", "number", "boolean"].includes(typeof value)).slice(0, 4) : []; + const blocks = Array.isArray(blocksResult.data) ? blocksResult.data : null; + const transactions = Array.isArray(transactionsResult.data) ? transactionsResult.data : null; + const activity = Array.isArray(activityResult.data) ? activityResult.data : null; + const errors = [statsResult.error, blocksResult.error, transactionsResult.error, activityResult.error].filter(Boolean); + return ( +
+
+ Decentralized Rights Protocol + {errors.length === 0 ? "API responding" : "Live data connection needs attention"} +
+
+

DRP Network Explorer

+

A transparent view of network activity and verification infrastructure. This explorer displays records returned by the configured DRP API; it does not invent missing blocks, transactions, or proof counts.

+
+
+ {metrics.length ? metrics.map(([key, value]) =>
{key.replace(/[_-]/g, " ")}
{valueText(value)}
) :
Network summary
Waiting for live API data

{statsResult.error || "The API did not return summary metrics."}

} +
+
+ + + +

Verification principles

Proof of Activity (PoAT)
Evidence and source provenance matter; a submitted claim is not automatically verified.
Proof of Status (PoST)
Status claims should identify their issuer, scope, validity period, and revocation state.
Accountable verification
A cryptographic signature confirms who signed a payload, not that the real-world claim is true.
+
+
API base: {API_BASE}. Configure DRP_EXPLORER_API_URL in Vercel to use a different API origin. Raw evidence and private personal data should not be published to a public ledger.
+
+ ); +} diff --git a/explorer/next-env.d.ts b/explorer/next-env.d.ts new file mode 100644 index 0000000..1b3be08 --- /dev/null +++ b/explorer/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/explorer/package.json b/explorer/package.json new file mode 100644 index 0000000..636ba00 --- /dev/null +++ b/explorer/package.json @@ -0,0 +1,21 @@ +{ + "name": "drp-blockchain-explorer", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "next": "15.5.24", + "react": "18.3.1", + "react-dom": "18.3.1" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "typescript": "^5" + } +} diff --git a/explorer/tsconfig.json b/explorer/tsconfig.json new file mode 100644 index 0000000..6dde179 --- /dev/null +++ b/explorer/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "target": "ES2017", + "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" + } + ] + }, + "include": [ + "next-env.d.ts", + ".next/types/**/*.ts", + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/src/app/api/explorer/summary/route.ts b/src/app/api/explorer/summary/route.ts index cfaf142..6f6e74d 100644 --- a/src/app/api/explorer/summary/route.ts +++ b/src/app/api/explorer/summary/route.ts @@ -3,5 +3,5 @@ import { createProxyRoute } from "@/lib/api/proxy"; export const dynamic = "force-dynamic"; export const GET = createProxyRoute({ - pathPrefix: "/api/ai/summary", + pathPrefix: "/api/v1/explorer/stats", }); From f08ded1ab51556c66f3b9bd3e88e57c0070da4bb Mon Sep 17 00:00:00 2001 From: NeonTechno Date: Mon, 12 Oct 2026 22:03:28 +0000 Subject: [PATCH 2/3] fix: resolve CI dependency conflict and explorer configuration Co-authored-by: Codesmith --- explorer/app/page.tsx | 3 +- explorer/package.json | 3 ++ package-lock.json | 89 +++++++++++++++++++++---------------------- package.json | 2 +- 4 files changed, 50 insertions(+), 47 deletions(-) diff --git a/explorer/app/page.tsx b/explorer/app/page.tsx index 2c6820b..cf7f72e 100644 --- a/explorer/app/page.tsx +++ b/explorer/app/page.tsx @@ -3,7 +3,8 @@ export const dynamic = "force-dynamic"; type ApiRecord = Record; type ApiResult = { data: T | null; error: string | null }; -const API_BASE = (process.env.DRP_EXPLORER_API_URL || "https://api.decentralizedrights.com/api/v1/explorer").replace(/\/$/, ""); +const API_URL = (process.env.DRP_EXPLORER_API_URL || process.env.NEXT_PUBLIC_API_URL || "https://api.decentralizedrights.com").replace(/\/+$/, ""); +const API_BASE = API_URL.endsWith("/api/v1/explorer") ? API_URL : `${API_URL}/api/v1/explorer`; async function load(path: string): Promise> { try { diff --git a/explorer/package.json b/explorer/package.json index 636ba00..15e3af9 100644 --- a/explorer/package.json +++ b/explorer/package.json @@ -17,5 +17,8 @@ "@types/react": "^18", "@types/react-dom": "^18", "typescript": "^5" + }, + "postcss": { + "plugins": {} } } diff --git a/package-lock.json b/package-lock.json index 3053083..83ad546 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,7 @@ "media-chrome": "^4.18.3", "motion": "^12.38.0", "nanoid": "^5.1.7", - "next": "14.2.3", + "next": "14.2.35", "next-i18next": "^15.2.0", "next-themes": "^0.2.1", "npm-run-all2": "^8.0.4", @@ -1959,9 +1959,9 @@ } }, "node_modules/@next/env": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz", - "integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==", + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -1996,9 +1996,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz", - "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", + "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", "cpu": [ "arm64" ], @@ -2012,9 +2012,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz", - "integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", + "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", "cpu": [ "x64" ], @@ -2028,9 +2028,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz", - "integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", + "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", "cpu": [ "arm64" ], @@ -2044,9 +2044,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz", - "integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", + "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", "cpu": [ "arm64" ], @@ -2060,9 +2060,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz", - "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", + "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", "cpu": [ "x64" ], @@ -2076,9 +2076,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", - "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", + "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", "cpu": [ "x64" ], @@ -2092,9 +2092,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", - "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", + "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", "cpu": [ "arm64" ], @@ -2108,9 +2108,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", - "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", + "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", "cpu": [ "ia32" ], @@ -2124,9 +2124,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz", - "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", + "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", "cpu": [ "x64" ], @@ -15772,13 +15772,12 @@ } }, "node_modules/next": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz", - "integrity": "sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==", - "deprecated": "This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/security-update-2025-12-11 for more details.", + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz", + "integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==", "license": "MIT", "dependencies": { - "@next/env": "14.2.3", + "@next/env": "14.2.35", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -15793,15 +15792,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.3", - "@next/swc-darwin-x64": "14.2.3", - "@next/swc-linux-arm64-gnu": "14.2.3", - "@next/swc-linux-arm64-musl": "14.2.3", - "@next/swc-linux-x64-gnu": "14.2.3", - "@next/swc-linux-x64-musl": "14.2.3", - "@next/swc-win32-arm64-msvc": "14.2.3", - "@next/swc-win32-ia32-msvc": "14.2.3", - "@next/swc-win32-x64-msvc": "14.2.3" + "@next/swc-darwin-arm64": "14.2.33", + "@next/swc-darwin-x64": "14.2.33", + "@next/swc-linux-arm64-gnu": "14.2.33", + "@next/swc-linux-arm64-musl": "14.2.33", + "@next/swc-linux-x64-gnu": "14.2.33", + "@next/swc-linux-x64-musl": "14.2.33", + "@next/swc-win32-arm64-msvc": "14.2.33", + "@next/swc-win32-ia32-msvc": "14.2.33", + "@next/swc-win32-x64-msvc": "14.2.33" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", diff --git a/package.json b/package.json index 5e5d6c9..5c935e2 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "media-chrome": "^4.18.3", "motion": "^12.38.0", "nanoid": "^5.1.7", - "next": "14.2.3", + "next": "14.2.35", "next-i18next": "^15.2.0", "next-themes": "^0.2.1", "npm-run-all2": "^8.0.4", From 0e84bbac4f61084675848c02aef01cce9e36f21c Mon Sep 17 00:00:00 2001 From: NeonTechnoX <89855167+NeonTechno@users.noreply.github.com> Date: Tue, 13 Oct 2026 14:55:34 +0000 Subject: [PATCH 3/3] fix: unblock website, portal, and explorer deployments --- app-portal/src/app/privacy/page.tsx | 4 +-- app-portal/src/app/terms/page.tsx | 2 +- explorer/package.json | 3 ++ package.json | 2 +- src/app/layout.tsx | 2 ++ src/components/ui/label.tsx | 15 +++++++++ src/components/ui/toaster.tsx | 49 +++++++++++++++++++++++++++++ src/components/ui/use-toast.ts | 18 +++++++++++ src/hooks/index.ts | 7 +++++ src/hooks/useWallet.ts | 1 + 10 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 src/components/ui/label.tsx create mode 100644 src/components/ui/toaster.tsx create mode 100644 src/components/ui/use-toast.ts create mode 100644 src/hooks/index.ts diff --git a/app-portal/src/app/privacy/page.tsx b/app-portal/src/app/privacy/page.tsx index 86a48cf..cfdbf3b 100644 --- a/app-portal/src/app/privacy/page.tsx +++ b/app-portal/src/app/privacy/page.tsx @@ -6,11 +6,11 @@ export default function PrivacyPage() {

Privacy Policy

Last updated: 7 September 2026

-

1. Who operates the Portal

The service is operated under the name Decentralized Rights Protocol (DRP). The public contact address for privacy and service questions is contact@decentralizedrights.com. If DRP is later operated by a registered legal entity, this notice should be updated with that entity's legal name, registered address and applicable registration details.

+

1. Who operates the Portal

The service is operated under the name Decentralized Rights Protocol (DRP). The public contact address for privacy and service questions is contact@decentralizedrights.com. If DRP is later operated by a registered legal entity, this notice should be updated with that entity's legal name, registered address and applicable registration details.

2. Data we collect

We aim to collect only data needed to provide and secure the Portal. Depending on the feature you use, this may include a wallet/public address, activity or proof information you submit, evidence files you choose to upload, transaction or verification identifiers, basic account/contact information when you voluntarily provide it, and technical/security information needed to operate the service.

Do not submit passwords, private keys, seed phrases, government identification numbers, health information, or other sensitive information unless a feature explicitly requests it and the applicable notice explains why it is needed.

3. Why we use it

We use information to authenticate and secure access, process proof submissions, provide verification and rewards features, prevent abuse, maintain audit and security records, provide support, and meet legal obligations. We do not sell personal data.

4. Blockchain and decentralized records

Some records may be written to blockchain, decentralized storage or other distributed systems. Such records can be difficult or impossible to alter or delete after publication. You should not submit personal information that you do not want associated with a potentially persistent public record. Where possible, DRP should use hashes, identifiers and minimised data rather than unnecessary personal information.

-

5. Service providers

The Portal may use infrastructure providers such as Vercel, Convex, Render, Storacha/IPFS, wallet providers and blockchain/network infrastructure. They may process information on DRP's behalf or as independent providers. Their own terms and privacy notices may also apply.

+

5. Service providers

The Portal may use infrastructure providers such as Vercel, Convex, Render, Storacha/IPFS, wallet providers and blockchain/network infrastructure. They may process information on DRP's behalf or as independent providers. Their own terms and privacy notices may also apply.

6. Retention and security

We retain information only for as long as reasonably necessary for the stated purpose, security, dispute handling and legal obligations. We use access controls, encryption in transit and other reasonable safeguards, but no online system can be guaranteed completely secure.

7. Your rights

Depending on applicable law, you may have rights to access, correct, delete, restrict or object to certain processing, and to withdraw consent where consent is the legal basis. Some rights may be limited where information is required for security, legal compliance, or has already been irreversibly committed to a decentralized network.

8. Ghana data protection

DRP is designed with Ghana's Data Protection Act, 2012 (Act 843) in mind. Where Ghana data-protection obligations apply, processing should be fair, lawful, transparent and limited to necessary purposes. The Ghana Data Protection Commission is the relevant regulator.

diff --git a/app-portal/src/app/terms/page.tsx b/app-portal/src/app/terms/page.tsx index 602d2c1..0c0c925 100644 --- a/app-portal/src/app/terms/page.tsx +++ b/app-portal/src/app/terms/page.tsx @@ -10,7 +10,7 @@ export default function TermsPage() {

2. What DRP provides

The Portal provides software for submitting, viewing and verifying activity or status claims and interacting with DRP infrastructure. Features may change, be unavailable, or remain in testing. Descriptions of planned protocol capabilities are not promises that a feature is currently available.

3. No guarantee of verification or rewards

Submitting a proof does not guarantee approval, verification, eligibility, rewards, token value, governance rights, or any particular outcome. Verification decisions may depend on protocol rules, evidence quality, network availability and applicable governance processes.

4. Wallets and blockchain transactions

You are responsible for your wallet, device, credentials and transaction approvals. DRP will never ask you to disclose a private key or seed phrase. Blockchain transactions can be irreversible and may incur network fees. Confirm transaction details before signing.

-

5. User submissions

You must have the right to submit any text, files, images, video or other evidence you provide. Do not upload another person's private information without a lawful basis and appropriate permission. Do not submit unlawful, fraudulent, defamatory, infringing, malicious or abusive material.

+

5. User submissions

You must have the right to submit any text, files, images, video or other evidence you provide. Do not upload another person's private information without a lawful basis and appropriate permission. Do not submit unlawful, fraudulent, defamatory, infringing, malicious or abusive material.

6. Intellectual property

DRP software, branding, documentation and content are protected by applicable intellectual-property laws unless a specific licence states otherwise. You retain rights you already have in your submissions, subject to the permissions needed to operate verification and display features.

7. Prohibited conduct

Do not attempt to compromise the Portal, bypass access controls, submit fabricated evidence, manipulate verification, abuse rewards, impersonate another person, upload malware, or use the service in violation of applicable law.

8. Disclaimers

The Portal is provided on an availability basis. DRP does not guarantee uninterrupted operation, error-free verification, blockchain finality, or absolute security. Nothing on the Portal is legal, financial, investment, medical or human-rights legal advice.

diff --git a/explorer/package.json b/explorer/package.json index 15e3af9..7e2e8a4 100644 --- a/explorer/package.json +++ b/explorer/package.json @@ -20,5 +20,8 @@ }, "postcss": { "plugins": {} + }, + "engines": { + "node": "22.x" } } diff --git a/package.json b/package.json index 5c935e2..37d0141 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "typescript": "^5.9.3" }, "engines": { - "node": ">=18.0.0" + "node": "22.x" }, "overrides": { "convex": { diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a0f2def..d6cac64 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,6 +6,7 @@ import { ThemeProvider } from "@/components/theme-provider"; import { Analytics } from "@vercel/analytics/react"; import { SpeedInsights } from "@vercel/speed-insights/next"; import { AppProviders } from "@/components/providers"; +import { Toaster } from "@/components/ui/toaster"; import { cn } from "@/lib/utils"; export const metadata: Metadata = { @@ -119,6 +120,7 @@ export default function RootLayout({
{children}
+ diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx new file mode 100644 index 0000000..5335eea --- /dev/null +++ b/src/components/ui/label.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; + +export type LabelProps = React.ComponentPropsWithoutRef<"label">; + +export const Label = React.forwardRef( + ({ className, ...props }, ref) => ( +