From a748a504f577278a6ad8c33e8812741a5d1caa45 Mon Sep 17 00:00:00 2001 From: defiQUG Date: Wed, 1 Jul 2026 01:41:42 -0700 Subject: [PATCH] feat(omnl-banking-portal): hub/bridge routes, hash anchors, and /omnl nginx proxy Add DBIS Hub landing page with /hub and /bridge routes, central-bank hash scroll targets, nginx /omnl/ proxy to token-aggregation for local dev and production hosts, and a public-url-zardasht tunnel URL template for operator handoff. Co-authored-by: Cursor --- deploy/nginx/omnl-bank.conf | 7 + deploy/nginx/omnl-common-locations.conf | 12 + deploy/nginx/omnl-lxc-portal.conf | 8 + deploy/public-url-zardasht.txt.example | 6 + frontend-dapp/src/App.tsx | 3 + .../src/components/layout/Layout.tsx | 4 +- .../components/layout/OmnlProductLayout.tsx | 6 +- .../central-bank/CentralBankDashboard.tsx | 12 + .../central-bank/ChainMatrixPanel.tsx | 218 +++++++++--------- frontend-dapp/src/pages/CentralBankPage.tsx | 11 + frontend-dapp/src/pages/HubPage.tsx | 76 ++++++ 11 files changed, 250 insertions(+), 113 deletions(-) create mode 100644 deploy/public-url-zardasht.txt.example create mode 100644 frontend-dapp/src/pages/HubPage.tsx diff --git a/deploy/nginx/omnl-bank.conf b/deploy/nginx/omnl-bank.conf index 01176f0..ed838c8 100644 --- a/deploy/nginx/omnl-bank.conf +++ b/deploy/nginx/omnl-bank.conf @@ -63,6 +63,13 @@ server { proxy_read_timeout 120s; } + # OMNL operator HTML consoles (token-aggregation) + location /omnl/ { + proxy_pass http://omnl_api/omnl/; + proxy_set_header Host $host; + proxy_read_timeout 120s; + } + location /health { return 200 'OMNL Bank online — 128 chains'; add_header Content-Type text/plain; diff --git a/deploy/nginx/omnl-common-locations.conf b/deploy/nginx/omnl-common-locations.conf index 8fd30c9..e08127f 100644 --- a/deploy/nginx/omnl-common-locations.conf +++ b/deploy/nginx/omnl-common-locations.conf @@ -33,6 +33,18 @@ location /exchange/ { proxy_read_timeout 120s; } +# token-aggregation HTML consoles (/omnl/compliance, /omnl/dashboard, /omnl/terminal) +location /omnl/ { + include /etc/nginx/omnl-portal-auth-current.conf.inc; + proxy_pass http://omnl_api/omnl/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 120s; +} + location /health { return 200 'OMNL Bank online — 128 chains'; add_header Content-Type text/plain; diff --git a/deploy/nginx/omnl-lxc-portal.conf b/deploy/nginx/omnl-lxc-portal.conf index b37013b..f96c6bf 100644 --- a/deploy/nginx/omnl-lxc-portal.conf +++ b/deploy/nginx/omnl-lxc-portal.conf @@ -56,6 +56,14 @@ http { proxy_read_timeout 120s; } + location /omnl/ { + include /srv/zardasht-portal/deploy/nginx/omnl-portal-auth-current.conf.inc; + proxy_pass http://omnl_lxc_api/omnl/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_read_timeout 120s; + } + location /assets/ { expires 1y; add_header Cache-Control "public, immutable"; diff --git a/deploy/public-url-zardasht.txt.example b/deploy/public-url-zardasht.txt.example new file mode 100644 index 0000000..6355ae3 --- /dev/null +++ b/deploy/public-url-zardasht.txt.example @@ -0,0 +1,6 @@ +# Copy to logs/public-url-zardasht.txt after cloudflared quick tunnel starts (logs/ is gitignored). +# Example: echo "https://YOUR-SUBDOMAIN.trycloudflare.com" > logs/public-url-zardasht.txt +# +# Institutional share: use production FQDNs from config/omnl-banking-portal-link-manifest.v1.json +# Entry path for demo tunnel: /hub +https://YOUR-SUBDOMAIN.trycloudflare.com diff --git a/frontend-dapp/src/App.tsx b/frontend-dapp/src/App.tsx index 3feb53d..e9e451e 100644 --- a/frontend-dapp/src/App.tsx +++ b/frontend-dapp/src/App.tsx @@ -15,6 +15,7 @@ import HistoryPage from './pages/HistoryPage' import AdminPanel from './pages/AdminPanel' import DocsPage from './pages/DocsPage' import WalletsDemoPage from './pages/WalletsDemoPage' +import HubPage from './pages/HubPage' import Layout from './components/layout/Layout' import OmnlProductLayout from './components/layout/OmnlProductLayout' import ToastProvider from './components/ui/ToastProvider' @@ -49,6 +50,7 @@ function App() { }> + } /> } /> } /> } /> @@ -62,6 +64,7 @@ function App() { } > } /> + } /> } /> } /> } /> diff --git a/frontend-dapp/src/components/layout/Layout.tsx b/frontend-dapp/src/components/layout/Layout.tsx index 7e415ce..d55e4c6 100644 --- a/frontend-dapp/src/components/layout/Layout.tsx +++ b/frontend-dapp/src/components/layout/Layout.tsx @@ -26,9 +26,9 @@ export default function Layout({ children }: LayoutProps) {
Bridge diff --git a/frontend-dapp/src/components/layout/OmnlProductLayout.tsx b/frontend-dapp/src/components/layout/OmnlProductLayout.tsx index 769c383..52e401e 100644 --- a/frontend-dapp/src/components/layout/OmnlProductLayout.tsx +++ b/frontend-dapp/src/components/layout/OmnlProductLayout.tsx @@ -12,6 +12,8 @@ import NasaIcon, { type NasaIconName } from '../icons/NasaIcon'; const PRODUCTS: { path: string; label: string; icon: NasaIconName }[] = [ + { path: '/hub', label: 'Hub', icon: 'satellite' }, + { path: '/central-bank', label: 'Central Bank', icon: 'central-bank' }, { path: '/office-24', label: 'Office 24', icon: 'office' }, @@ -46,7 +48,7 @@ export default function OmnlProductLayout() {
- + @@ -88,7 +90,7 @@ export default function OmnlProductLayout() { +

@@ -144,8 +146,14 @@ export default function CentralBankDashboard() { + + + +
+
+ + + +
diff --git a/frontend-dapp/src/features/central-bank/ChainMatrixPanel.tsx b/frontend-dapp/src/features/central-bank/ChainMatrixPanel.tsx index d99a1b0..4fa9b2b 100644 --- a/frontend-dapp/src/features/central-bank/ChainMatrixPanel.tsx +++ b/frontend-dapp/src/features/central-bank/ChainMatrixPanel.tsx @@ -1,109 +1,109 @@ -import { useEffect, useState } from 'react'; -import { fetchOmnlChainRegistry, type ChainRegistryResponse, type OmnlChainSummary } from '../../config/supported-chains'; -import NasaIcon, { StatusIcon } from '../../components/icons/NasaIcon'; - -type Filter = 'all' | 'active' | 'primary' | 'l2'; - -export default function ChainMatrixPanel() { - const [registry, setRegistry] = useState(null); - const [filter, setFilter] = useState('active'); - const [search, setSearch] = useState(''); - - useEffect(() => { - fetchOmnlChainRegistry().then(setRegistry); - }, []); - - const chains = (registry?.chains ?? []).filter((c) => { - if (filter === 'active' && c.status !== 'active') return false; - if (filter === 'primary' && c.omnlRole !== 'settlement-hub' && c.omnlRole !== 'mirror-target') return false; - if (filter === 'l2' && c.tier !== 'l2') return false; - if (search) { - const q = search.toLowerCase(); - return c.name.toLowerCase().includes(q) || String(c.chainId).includes(q) || c.nativeSymbol.toLowerCase().includes(q); - } - return true; - }); - - return ( -
-
-
-

- - 128-chain network matrix -

-

- {registry?.stats?.active ?? 0} active · {registry?.stats?.staged ?? 0} staged ·{' '} - {registry?.stats?.reserved ?? 0} reserved · primary {registry?.primaryChainId ?? 138} -

-
-
- - setSearch(e.target.value)} - className="nasa-input !min-h-[36px] !w-48 text-sm" - /> -
-
- -
- {(['all', 'active', 'primary', 'l2'] as Filter[]).map((f) => ( - - ))} -
- -
- - - - - - - - - - - - - {chains.map((c: OmnlChainSummary) => ( - - - - - - - - - ))} - -
IDNetworkRoleStatusSwapBridge
{c.chainId}{c.name}{c.omnlRole} - - {c.status} - -
-
-
- ); -} +import { useEffect, useState } from 'react'; +import { fetchOmnlChainRegistry, type ChainRegistryResponse, type OmnlChainSummary } from '../../config/supported-chains'; +import NasaIcon, { StatusIcon } from '../../components/icons/NasaIcon'; + +type Filter = 'all' | 'active' | 'primary' | 'l2'; + +export default function ChainMatrixPanel() { + const [registry, setRegistry] = useState(null); + const [filter, setFilter] = useState('active'); + const [search, setSearch] = useState(''); + + useEffect(() => { + fetchOmnlChainRegistry().then(setRegistry); + }, []); + + const chains = (registry?.chains ?? []).filter((c) => { + if (filter === 'active' && c.status !== 'active') return false; + if (filter === 'primary' && c.omnlRole !== 'settlement-hub' && c.omnlRole !== 'mirror-target') return false; + if (filter === 'l2' && c.tier !== 'l2') return false; + if (search) { + const q = search.toLowerCase(); + return c.name.toLowerCase().includes(q) || String(c.chainId).includes(q) || c.nativeSymbol.toLowerCase().includes(q); + } + return true; + }); + + return ( +
+
+
+

+ + 128-chain network matrix +

+

+ {registry?.stats?.active ?? 0} active · {registry?.stats?.staged ?? 0} staged ·{' '} + {registry?.stats?.reserved ?? 0} reserved · primary {registry?.primaryChainId ?? 138} +

+
+
+ + setSearch(e.target.value)} + className="nasa-input !min-h-[36px] !w-48 text-sm" + /> +
+
+ +
+ {(['all', 'active', 'primary', 'l2'] as Filter[]).map((f) => ( + + ))} +
+ +
+ + + + + + + + + + + + + {chains.map((c: OmnlChainSummary) => ( + + + + + + + + + ))} + +
IDNetworkRoleStatusSwapBridge
{c.chainId}{c.name}{c.omnlRole} + + {c.status} + +
+
+
+ ); +} diff --git a/frontend-dapp/src/pages/CentralBankPage.tsx b/frontend-dapp/src/pages/CentralBankPage.tsx index cdd635a..c6772a0 100644 --- a/frontend-dapp/src/pages/CentralBankPage.tsx +++ b/frontend-dapp/src/pages/CentralBankPage.tsx @@ -1,5 +1,16 @@ +import { useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; import CentralBankDashboard from '../features/central-bank/CentralBankDashboard'; export default function CentralBankPage() { + const { hash } = useLocation(); + + useEffect(() => { + if (!hash) return; + const id = hash.replace(/^#/, ''); + const el = document.getElementById(id); + el?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }, [hash]); + return ; } diff --git a/frontend-dapp/src/pages/HubPage.tsx b/frontend-dapp/src/pages/HubPage.tsx new file mode 100644 index 0000000..d0d694e --- /dev/null +++ b/frontend-dapp/src/pages/HubPage.tsx @@ -0,0 +1,76 @@ +import { Link } from 'react-router-dom'; +import NasaIcon, { type NasaIconName } from '../components/icons/NasaIcon'; + +const BANKING: { path: string; label: string; icon: NasaIconName }[] = [ + { path: '/central-bank', label: 'Z Online Bank / Central Bank', icon: 'central-bank' }, + { path: '/central-bank#z-full-settlement', label: 'M0→M4 settlement', icon: 'money' }, + { path: '/central-bank#z-settlement-protocols', label: 'Wire & chain protocols', icon: 'network' }, + { path: '/central-bank#z-settlement-protocols-chains', label: '128-chain matrix', icon: 'network' }, + { path: '/office-24', label: 'Office 24', icon: 'office' }, + { path: '/trade', label: 'DBIS Trade', icon: 'trade' }, + { path: '/swap', label: 'Digital Swap', icon: 'swap' }, +]; + +const CHAIN138: { path: string; label: string; icon: NasaIconName }[] = [ + { path: '/bridge', label: 'Bridge', icon: 'bridge' }, + { path: '/reserve', label: 'Reserve', icon: 'ledger' }, + { path: '/history', label: 'History', icon: 'chart' }, + { path: '/wallets', label: 'Wallets', icon: 'globe' }, + { path: '/docs', label: 'Developers / API docs', icon: 'link' }, + { path: '/admin', label: 'Admin', icon: 'satellite' }, +]; + +const OMNL_OPS: { path: string; label: string; icon: NasaIconName }[] = [ + { path: '/omnl/compliance', label: 'OMNL Compliance console', icon: 'ledger' }, + { path: '/omnl/dashboard', label: 'OMNL API snapshot', icon: 'chart' }, + { path: '/omnl/terminal', label: 'Settlement terminal', icon: 'rail' }, +]; + +function LinkGrid({ + title, + items, +}: { + title: string; + items: { path: string; label: string; icon: NasaIconName }[]; +}) { + return ( +
+

{title}

+
    + {items.map(({ path, label, icon }) => ( +
  • + + + {label} + +
  • + ))} +
+
+ ); +} + +export default function HubPage() { + return ( +
+
+

DBIS · OMNL · Chain 138

+

+ + DBIS Hub +

+

+ Mission control entry — banking portals, settlement surfaces, and Chain 138 tools on this host. +

+
+
+ + +
+ +
+ ); +}