chore: sync Office 24 Zardasht identity and deploy paths
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m29s
CI/CD Pipeline / Security Scanning (push) Successful in 3m16s
CI/CD Pipeline / Lint and Format (push) Failing after 46s
CI/CD Pipeline / Terraform Validation (push) Failing after 25s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 27s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 52s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 30s
Validation / validate-genesis (push) Successful in 27s
Validation / validate-terraform (push) Failing after 30s
Validation / validate-kubernetes (push) Failing after 11s
Validation / validate-smart-contracts (push) Failing after 10s
Validation / validate-security (push) Failing after 1m31s
Validation / validate-documentation (push) Failing after 19s
Verify Deployment / Verify Deployment (push) Failing after 59s
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m29s
CI/CD Pipeline / Security Scanning (push) Successful in 3m16s
CI/CD Pipeline / Lint and Format (push) Failing after 46s
CI/CD Pipeline / Terraform Validation (push) Failing after 25s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 27s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 52s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 30s
Validation / validate-genesis (push) Successful in 27s
Validation / validate-terraform (push) Failing after 30s
Validation / validate-kubernetes (push) Failing after 11s
Validation / validate-smart-contracts (push) Failing after 10s
Validation / validate-security (push) Failing after 1m31s
Validation / validate-documentation (push) Failing after 19s
Verify Deployment / Verify Deployment (push) Failing after 59s
Align externalId, office name, and portal topology with live Fineract (HOSPITALLERS-ZARDASHT-IRAQ-IRAN). Default LXC root to /srv/zardasht-portal and SSH alias dev-bis-zardasht in host config. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
"chainId": 138,
|
||||
"brandName": "DBIS Exchange",
|
||||
"officeId": 24,
|
||||
"settlementOfficeExternalId": "HOSPITALLERS-ALI-IRAQ-IRAN",
|
||||
"settlementOfficeExternalId": "HOSPITALLERS-ZARDASHT-IRAQ-IRAN",
|
||||
"chainRegistry": "config/omnl-supported-chains.v1.json",
|
||||
"maxSupportedChains": 128,
|
||||
"routers": {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"chainId": 138,
|
||||
"brandName": "DBIS Exchange",
|
||||
"officeId": 24,
|
||||
"settlementOfficeExternalId": "HOSPITALLERS-ALI-IRAQ-IRAN",
|
||||
"settlementOfficeExternalId": "HOSPITALLERS-ZARDASHT-IRAQ-IRAN",
|
||||
"routers": {
|
||||
"enhancedSwapRouterV2": "0xa421706768aeb7fafa2d912c5e10824ef3437ad4",
|
||||
"uniswapV2": "0x3019A7fDc76ba7F64F18d78e66842760037ee638",
|
||||
|
||||
@@ -489,8 +489,8 @@
|
||||
{
|
||||
"lineId": "0xaede6a63b3f49d0d18b13267855274e250516a97c84dcf0d31e17f359ceca4ff",
|
||||
"officeId": 24,
|
||||
"externalId": "HOSPITALLERS-ALI-IRAQ-IRAN",
|
||||
"entityName": "HOSPITALLERS \u2014 Ali (Iraq / Iran Operations)",
|
||||
"externalId": "HOSPITALLERS-ZARDASHT-IRAQ-IRAN",
|
||||
"entityName": "HOSPITALLERS — Zardasht (Iraq / Iran Operations)",
|
||||
"walletId": "HYBX-OFFICE-024",
|
||||
"treasuryWalletMainnet": "0x87dab11386841366682d6c5fd3cd90587552f8cd",
|
||||
"treasuryWalletChain138": "0xc93522ae4ab7482572cc29edd68fbb6d5ec6a585",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "Office 24 opening M1 allocation from Head Office (Fineract journal)",
|
||||
"version": "1.0.0",
|
||||
"officeId": 24,
|
||||
"externalId": "HOSPITALLERS-ALI-IRAQ-IRAN",
|
||||
"externalId": "HOSPITALLERS-ZARDASHT-IRAQ-IRAN",
|
||||
"referenceNumber": "HOSPITALLERS-24-OPENING-M1",
|
||||
"comments": "M1 allocation from Head Office — Dr 1410 Due From HO / Cr 2100 M1 Central Liabilities",
|
||||
"debitGlCode": "1410",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"$schema": "OMNL Office 24 — Ali HOSPITALLERS settlement profile",
|
||||
"version": "1.0.0",
|
||||
"officeId": 24,
|
||||
"externalId": "HOSPITALLERS-ALI-IRAQ-IRAN",
|
||||
"name": "HOSPITALLERS Ali Iraq-Iran",
|
||||
"externalId": "HOSPITALLERS-ZARDASHT-IRAQ-IRAN",
|
||||
"name": "HOSPITALLERS — Zardasht (Iraq / Iran Operations)",
|
||||
"fineractTenant": "omnl",
|
||||
"tenantUser": "ali_hospitallers_tenant",
|
||||
"adminUser": "ali_hospitallers_admin",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"version": "1.1.0",
|
||||
"description": "OMNL banking portal — Ali operator topology (verified via pnpm ali:hospitallers:verify-external)",
|
||||
"description": "OMNL banking portal — Zardasht operator topology (legacy SSH alias dev-bis-ali still works)",
|
||||
"cursorPath": {
|
||||
"sshAlias": "dev-bis-ali",
|
||||
"sshAlias": "dev-bis-zardasht",
|
||||
"publicHostname": "ssh-dev.d-bis.org",
|
||||
"devVmLanIp": "192.168.11.59",
|
||||
"user": "dev1",
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"bankingLxc": {
|
||||
"ctidEnv": "OMNL_PCT_CTID",
|
||||
"portalRoot": "/srv/ali-portal",
|
||||
"portalRoot": "/srv/zardasht-portal",
|
||||
"projectSource": "/home/projects/exchange",
|
||||
"appPort": 3000,
|
||||
"fullStackPorts": {
|
||||
@@ -33,9 +33,9 @@
|
||||
"publicDomains": "config/omnl-production-domains.v1.json"
|
||||
},
|
||||
"handoff": {
|
||||
"refreshCommand": "pnpm ali:hospitallers:handoff",
|
||||
"verifyCommand": "pnpm ali:hospitallers:verify-external",
|
||||
"onboardingDoc": "docs/04-configuration/ALI_ZARDASHT_REMOTE_OPERATOR_ONBOARDING.md",
|
||||
"refreshCommand": "pnpm zardasht:hospitallers:handoff",
|
||||
"verifyCommand": "pnpm zardasht:hospitallers:verify-external",
|
||||
"onboardingDoc": "docs/04-configuration/ZARDASHT_REMOTE_OPERATOR_ONBOARDING.md",
|
||||
"workflowDoc": "docs/04-configuration/ALI_GITEA_TWO_REPO_WORKFLOW.md",
|
||||
"forgeRegistry": "docs/04-configuration/FORGE_CANONICAL_REGISTRY.md"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Banking portal LXCs on Proxmox r630-03 (192.168.11.13). NPMplus maps nine public FQDNs to these four stacks.",
|
||||
"pveHost": "192.168.11.13",
|
||||
"pveNode": "r630-03",
|
||||
"portalRoot": "/srv/ali-portal",
|
||||
"portalRoot": "/srv/zardasht-portal",
|
||||
"containers": [
|
||||
{
|
||||
"ctid": 5825,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"originHost": "dev-bis-ali",
|
||||
"originHost": "dev-bis-zardasht",
|
||||
"originIp": "76.53.10.34",
|
||||
"frontendPort": 3002,
|
||||
"domains": [
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"enforceSingleOffice": true,
|
||||
"settlementOffice": {
|
||||
"officeId": 24,
|
||||
"externalId": "HOSPITALLERS-ALI-IRAQ-IRAN",
|
||||
"name": "HOSPITALLERS Ali Iraq-Iran",
|
||||
"externalId": "HOSPITALLERS-ZARDASHT-IRAQ-IRAN",
|
||||
"name": "HOSPITALLERS — Zardasht (Iraq / Iran Operations)",
|
||||
"profilePath": "config/offices/office-24-settlement.v1.json"
|
||||
},
|
||||
"defaultCurrency": "USD",
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"enforceSingleOffice": true,
|
||||
"settlementOffice": {
|
||||
"officeId": 24,
|
||||
"externalId": "HOSPITALLERS-ALI-IRAQ-IRAN",
|
||||
"name": "HOSPITALLERS Ali Iraq-Iran",
|
||||
"externalId": "HOSPITALLERS-ZARDASHT-IRAQ-IRAN",
|
||||
"name": "HOSPITALLERS — Zardasht (Iraq / Iran Operations)",
|
||||
"profilePath": "config/offices/office-24-settlement.v1.json"
|
||||
},
|
||||
"defaultCurrency": "USD",
|
||||
|
||||
@@ -29,7 +29,7 @@ http {
|
||||
listen [::]:3002 default_server;
|
||||
server_name _;
|
||||
|
||||
root /srv/ali-portal/frontend-dapp/dist;
|
||||
root /srv/zardasht-portal/frontend-dapp/dist;
|
||||
index index.html;
|
||||
|
||||
location /api/v1/ {
|
||||
|
||||
@@ -1,147 +1,294 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { useCentralBank } from './useCentralBank';
|
||||
|
||||
import ChainMatrixPanel from './ChainMatrixPanel';
|
||||
|
||||
import FineractLedgerBanner from '../omnl-dashboard/FineractLedgerBanner';
|
||||
|
||||
import DashboardStatCard from '../omnl-dashboard/DashboardStatCard';
|
||||
|
||||
import DashboardSection from '../omnl-dashboard/DashboardSection';
|
||||
|
||||
import QuickPortalLinks from '../omnl-dashboard/QuickPortalLinks';
|
||||
|
||||
import NasaPageHeader from '../omnl-dashboard/NasaPageHeader';
|
||||
|
||||
import NasaIcon from '../../components/icons/NasaIcon';
|
||||
|
||||
import { formatUsd } from '../../utils/formatMoney';
|
||||
|
||||
|
||||
|
||||
export default function CentralBankDashboard() {
|
||||
|
||||
const cb = useCentralBank();
|
||||
|
||||
const office = cb.office as {
|
||||
|
||||
officeId?: number;
|
||||
|
||||
name?: string;
|
||||
|
||||
externalId?: string;
|
||||
|
||||
settlement?: { moneyLayers?: string[]; glM0?: string; glM1?: string; glM2?: string };
|
||||
|
||||
} | null;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<div className="dash-page cb-page max-w-[1400px] mx-auto px-4 py-6">
|
||||
|
||||
<NasaPageHeader
|
||||
|
||||
icon="central-bank"
|
||||
|
||||
missionId="CB-138"
|
||||
|
||||
title="Central Bank Operations"
|
||||
|
||||
subtitle={`Live money supply for ${office?.name ?? 'HOSPITALLERS Ali Iraq-Iran'} (Office ${office?.officeId ?? 24}) · settlement · SWIFT · HYBX · Chain 138`}
|
||||
|
||||
badges={
|
||||
|
||||
<>
|
||||
|
||||
<span className="nasa-badge nasa-badge--telemetry">OMNL Central Bank</span>
|
||||
|
||||
<span className="nasa-badge nasa-badge--nominal">Production</span>
|
||||
|
||||
<span className="nasa-badge nasa-badge--caution">128 chains</span>
|
||||
|
||||
</>
|
||||
|
||||
}
|
||||
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<QuickPortalLinks />
|
||||
|
||||
|
||||
|
||||
{cb.error && (
|
||||
|
||||
<div className="dash-banner dash-banner--error mb-6">
|
||||
|
||||
<NasaIcon name="x" size={18} className="nasa-icon--critical shrink-0 mt-0.5" />
|
||||
|
||||
<div>
|
||||
|
||||
<p className="dash-banner__title">Failed to load dashboard</p>
|
||||
|
||||
<p className="dash-banner__detail">{cb.error}</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
|
||||
<FineractLedgerBanner
|
||||
|
||||
moneySupply={cb.moneySupply}
|
||||
|
||||
loading={cb.loading}
|
||||
|
||||
officeName={office?.name}
|
||||
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<h2 className="dash-section-title mb-1 flex items-center gap-2">
|
||||
|
||||
<NasaIcon name="money" size={14} className="nasa-icon--telemetry" />
|
||||
|
||||
Money supply
|
||||
|
||||
</h2>
|
||||
|
||||
<p className="dash-section-subtitle mb-4">Meta-fiat layers from Fineract general ledger · USD</p>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
||||
|
||||
<DashboardStatCard label="M0 reserve" value={formatUsd(cb.moneySupply?.M0?.gl1050)} hint={`GL 1050 · ${cb.moneySupply?.M0?.backingRatio ?? 1.2}× backing policy`} accent="blue" icon="ledger" />
|
||||
|
||||
<DashboardStatCard label="M1 circulating" value={formatUsd(cb.moneySupply?.M1?.circulating)} hint="GL 2100 · narrow money / eMoney" accent="green" icon="money" />
|
||||
|
||||
<DashboardStatCard label="M2 broad money" value={formatUsd(cb.moneySupply?.M2?.broadMoney)} hint="GL 2200 · token-load source" accent="gold" icon="rocket" />
|
||||
|
||||
<DashboardStatCard label="Due from head office" value={formatUsd(cb.moneySupply?.interoffice?.dueFromHeadOffice)} hint="GL 1410 · inter-office receivable" accent="blue" icon="rail" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
|
||||
<DashboardSection
|
||||
|
||||
title="Settlement service"
|
||||
|
||||
subtitle="Middleware health and refresh"
|
||||
|
||||
icon="satellite"
|
||||
|
||||
action={
|
||||
|
||||
<button type="button" className="dash-btn !w-auto px-4 flex items-center gap-1" onClick={() => cb.refresh()} disabled={cb.loading}>
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { useCentralBank } from './useCentralBank';
|
||||
|
||||
import ChainMatrixPanel from './ChainMatrixPanel';
|
||||
|
||||
import FineractLedgerBanner from '../omnl-dashboard/FineractLedgerBanner';
|
||||
|
||||
import DashboardStatCard from '../omnl-dashboard/DashboardStatCard';
|
||||
|
||||
import DashboardSection from '../omnl-dashboard/DashboardSection';
|
||||
|
||||
import QuickPortalLinks from '../omnl-dashboard/QuickPortalLinks';
|
||||
|
||||
import NasaPageHeader from '../omnl-dashboard/NasaPageHeader';
|
||||
|
||||
import NasaIcon from '../../components/icons/NasaIcon';
|
||||
|
||||
import { formatUsd } from '../../utils/formatMoney';
|
||||
|
||||
|
||||
|
||||
export default function CentralBankDashboard() {
|
||||
|
||||
const cb = useCentralBank();
|
||||
|
||||
const office = cb.office as {
|
||||
|
||||
officeId?: number;
|
||||
|
||||
name?: string;
|
||||
|
||||
externalId?: string;
|
||||
|
||||
settlement?: { moneyLayers?: string[]; glM0?: string; glM1?: string; glM2?: string };
|
||||
|
||||
} | null;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<div className="dash-page cb-page max-w-[1400px] mx-auto px-4 py-6">
|
||||
|
||||
<NasaPageHeader
|
||||
|
||||
icon="central-bank"
|
||||
|
||||
missionId="CB-138"
|
||||
|
||||
title="Central Bank Operations"
|
||||
|
||||
subtitle={`Live money supply for ${office?.name ?? 'HOSPITALLERS — Zardasht (Iraq / Iran Operations)'} (Office ${office?.officeId ?? 24}) · settlement · SWIFT · HYBX · Chain 138`}
|
||||
|
||||
badges={
|
||||
|
||||
<>
|
||||
|
||||
<span className="nasa-badge nasa-badge--telemetry">OMNL Central Bank</span>
|
||||
|
||||
<span className="nasa-badge nasa-badge--nominal">Production</span>
|
||||
|
||||
<span className="nasa-badge nasa-badge--caution">128 chains</span>
|
||||
|
||||
</>
|
||||
|
||||
}
|
||||
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<QuickPortalLinks />
|
||||
|
||||
|
||||
|
||||
{cb.error && (
|
||||
|
||||
<div className="dash-banner dash-banner--error mb-6">
|
||||
|
||||
<NasaIcon name="x" size={18} className="nasa-icon--critical shrink-0 mt-0.5" />
|
||||
|
||||
<div>
|
||||
|
||||
<p className="dash-banner__title">Failed to load dashboard</p>
|
||||
|
||||
<p className="dash-banner__detail">{cb.error}</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
|
||||
<FineractLedgerBanner
|
||||
|
||||
moneySupply={cb.moneySupply}
|
||||
|
||||
loading={cb.loading}
|
||||
|
||||
officeName={office?.name}
|
||||
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<h2 className="dash-section-title mb-1 flex items-center gap-2">
|
||||
|
||||
<NasaIcon name="money" size={14} className="nasa-icon--telemetry" />
|
||||
|
||||
Money supply
|
||||
|
||||
</h2>
|
||||
|
||||
<p className="dash-section-subtitle mb-4">Meta-fiat layers from Fineract general ledger · USD</p>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
||||
|
||||
<DashboardStatCard label="M0 reserve" value={formatUsd(cb.moneySupply?.M0?.gl1050)} hint={`GL 1050 · ${cb.moneySupply?.M0?.backingRatio ?? 1.2}× backing policy`} accent="blue" icon="ledger" />
|
||||
|
||||
<DashboardStatCard label="M1 circulating" value={formatUsd(cb.moneySupply?.M1?.circulating)} hint="GL 2100 · narrow money / eMoney" accent="green" icon="money" />
|
||||
|
||||
<DashboardStatCard label="M2 broad money" value={formatUsd(cb.moneySupply?.M2?.broadMoney)} hint="GL 2200 · token-load source" accent="gold" icon="rocket" />
|
||||
|
||||
<DashboardStatCard label="Due from head office" value={formatUsd(cb.moneySupply?.interoffice?.dueFromHeadOffice)} hint="GL 1410 · inter-office receivable" accent="blue" icon="rail" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
|
||||
<DashboardSection
|
||||
|
||||
title="Settlement service"
|
||||
|
||||
subtitle="Middleware health and refresh"
|
||||
|
||||
icon="satellite"
|
||||
|
||||
action={
|
||||
|
||||
<button type="button" className="dash-btn !w-auto px-4 flex items-center gap-1" onClick={() => cb.refresh()} disabled={cb.loading}>
|
||||
|
||||
<NasaIcon name="refresh" size={12} className={cb.loading ? 'nasa-icon--spin' : ''} />
|
||||
|
||||
{cb.loading ? 'Refreshing…' : 'Refresh'}
|
||||
|
||||
</button>
|
||||
|
||||
}
|
||||
|
||||
>
|
||||
|
||||
<dl>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt>Status</dt>
|
||||
|
||||
<dd className="dash-kv-value--ok">{(cb.health as { status?: string })?.status ?? '—'}</dd>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt>Office</dt>
|
||||
|
||||
<dd>{office?.officeId ?? 24} · {office?.externalId ?? 'HOSPITALLERS-ZARDASHT-IRAQ-IRAN'}</dd>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt>M2 tokens registered</dt>
|
||||
|
||||
<dd>{cb.tokenCount}</dd>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt>Active chains</dt>
|
||||
|
||||
<dd>
|
||||
|
||||
{(cb.health as { chainSupport?: { active?: number; total?: number } })?.chainSupport?.active ?? '—'}
|
||||
|
||||
{' / '}
|
||||
|
||||
{(cb.health as { chainSupport?: { active?: number; total?: number } })?.chainSupport?.total ?? 128}
|
||||
|
||||
</dd>
|
||||
|
||||
</div>
|
||||
|
||||
</dl>
|
||||
|
||||
</DashboardSection>
|
||||
|
||||
|
||||
|
||||
<DashboardSection title="General ledger map" subtitle={`Money layers · Office ${office?.officeId ?? 24}`} icon="ledger">
|
||||
|
||||
<div className="flex flex-wrap gap-2 mb-4">
|
||||
|
||||
{(office?.settlement?.moneyLayers ?? ['M0', 'M1', 'M2']).map((layer) => (
|
||||
|
||||
<span key={layer} className="nasa-badge nasa-badge--caution">{layer}</span>
|
||||
|
||||
))}
|
||||
|
||||
</div>
|
||||
|
||||
<dl>
|
||||
|
||||
<div className="dash-kv"><dt>M0 reserve</dt><dd>GL {office?.settlement?.glM0 ?? '1050'}</dd></div>
|
||||
|
||||
<div className="dash-kv"><dt>M1 liability</dt><dd>GL {office?.settlement?.glM1 ?? '2100'}</dd></div>
|
||||
|
||||
<div className="dash-kv"><dt>M2 broad</dt><dd>GL {office?.settlement?.glM2 ?? '2200'}</dd></div>
|
||||
|
||||
<div className="dash-kv"><dt>Inter-office (HO)</dt><dd>GL 1410</dd></div>
|
||||
|
||||
</dl>
|
||||
|
||||
<p className="dash-section-subtitle mt-4 flex flex-wrap gap-3">
|
||||
|
||||
<Link to="/office-24" className="text-[#00d4ff] hover:underline inline-flex items-center gap-1">
|
||||
|
||||
<NasaIcon name="office" size={12} /> Office 24 dashboard
|
||||
|
||||
</Link>
|
||||
|
||||
<Link to="/trade" className="text-[#00d4ff] hover:underline inline-flex items-center gap-1">
|
||||
|
||||
<NasaIcon name="trade" size={12} /> DBIS Trade
|
||||
|
||||
</Link>
|
||||
|
||||
</p>
|
||||
|
||||
</DashboardSection>
|
||||
|
||||
|
||||
|
||||
<DashboardSection title="Recent exchange activity" subtitle="Last 8 swaps on DBIS Exchange" icon="chart" className="lg:col-span-2">
|
||||
|
||||
<ul className="space-y-0 text-sm">
|
||||
|
||||
{((cb.monitor as { swaps?: { status: string; tokenIn: string; createdAt: string }[] })?.swaps ?? [])
|
||||
|
||||
.slice(0, 8)
|
||||
|
||||
.map((s, i) => (
|
||||
|
||||
<li key={i} className="flex justify-between gap-3 py-2.5 border-b border-[rgba(30,74,138,0.35)] last:border-0 text-sm font-mono">
|
||||
|
||||
<span className="text-[#7a9bb8] shrink-0">{s.status}</span>
|
||||
|
||||
<span className="text-[#e8f4ff] text-xs truncate">{s.tokenIn?.slice(0, 12)}…</span>
|
||||
|
||||
<span className="text-[#7a9bb8] text-xs shrink-0">{s.createdAt?.slice(0, 16)}</span>
|
||||
|
||||
</li>
|
||||
|
||||
))}
|
||||
|
||||
{!((cb.monitor as { swaps?: unknown[] })?.swaps?.length) && (
|
||||
|
||||
<li className="text-[#7a9bb8] py-3">No swaps recorded yet</li>
|
||||
|
||||
)}
|
||||
|
||||
</ul>
|
||||
|
||||
</DashboardSection>
|
||||
|
||||
|
||||
|
||||
<ChainMatrixPanel />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,151 +1,302 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { useOffice24 } from './useOffice24';
|
||||
|
||||
import FineractLedgerBanner from '../omnl-dashboard/FineractLedgerBanner';
|
||||
|
||||
import DashboardStatCard from '../omnl-dashboard/DashboardStatCard';
|
||||
|
||||
import DashboardSection from '../omnl-dashboard/DashboardSection';
|
||||
|
||||
import QuickPortalLinks from '../omnl-dashboard/QuickPortalLinks';
|
||||
|
||||
import NasaPageHeader from '../omnl-dashboard/NasaPageHeader';
|
||||
|
||||
import NasaIcon, { StatusIcon } from '../../components/icons/NasaIcon';
|
||||
|
||||
import { formatUsd } from '../../utils/formatMoney';
|
||||
|
||||
|
||||
|
||||
export default function Office24Dashboard() {
|
||||
|
||||
const { office, tokens, health, moneySupply, loading, refresh } = useOffice24();
|
||||
|
||||
const profile = office as {
|
||||
|
||||
officeId?: number;
|
||||
|
||||
externalId?: string;
|
||||
|
||||
name?: string;
|
||||
|
||||
locked?: boolean;
|
||||
|
||||
tenantUser?: string;
|
||||
|
||||
settlement?: { defaultCurrency?: string; moneyLayers?: string[] };
|
||||
|
||||
rails?: { swift?: { enabled?: boolean }; hybx?: { enabled?: boolean }; chain138?: { enabled?: boolean } };
|
||||
|
||||
} | null;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<div className="dash-page o24-page max-w-[1400px] mx-auto px-4 py-6">
|
||||
|
||||
<div className="flex flex-wrap items-start justify-between gap-4 mb-2">
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
|
||||
<NasaPageHeader
|
||||
|
||||
icon="office"
|
||||
|
||||
missionId="O24-138"
|
||||
|
||||
title={profile?.name ?? 'HOSPITALLERS Ali Iraq-Iran'}
|
||||
|
||||
subtitle={profile?.externalId ?? 'HOSPITALLERS-ALI-IRAQ-IRAN'}
|
||||
|
||||
badges={
|
||||
|
||||
<>
|
||||
|
||||
<span className="nasa-badge nasa-badge--nominal">Office 24</span>
|
||||
|
||||
{profile?.locked && <span className="nasa-badge nasa-badge--caution">Single office · locked</span>}
|
||||
|
||||
</>
|
||||
|
||||
}
|
||||
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2 pt-2">
|
||||
|
||||
<Link to="/central-bank" className="nasa-btn inline-flex items-center gap-1">
|
||||
|
||||
<NasaIcon name="central-bank" size={12} /> Central Bank
|
||||
|
||||
</Link>
|
||||
|
||||
<Link to="/trade" className="nasa-btn nasa-btn--primary inline-flex items-center gap-1">
|
||||
|
||||
<NasaIcon name="trade" size={12} /> DBIS Trade
|
||||
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<QuickPortalLinks />
|
||||
|
||||
|
||||
|
||||
<FineractLedgerBanner moneySupply={moneySupply} loading={loading} officeName={profile?.name} />
|
||||
|
||||
|
||||
|
||||
<h2 className="dash-section-title mb-1 flex items-center gap-2">
|
||||
|
||||
<NasaIcon name="ledger" size={14} className="nasa-icon--telemetry" />
|
||||
|
||||
Office balances
|
||||
|
||||
</h2>
|
||||
|
||||
<p className="dash-section-subtitle mb-4">Live Fineract · {profile?.settlement?.defaultCurrency ?? 'USD'}</p>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
||||
|
||||
<DashboardStatCard label="Office ID" value={String(profile?.officeId ?? 24)} hint="Fineract office · HOSPITALLERS Ali" accent="green" icon="office" />
|
||||
|
||||
<DashboardStatCard label="M1 circulating" value={formatUsd(moneySupply?.M1?.circulating)} hint="GL 2100 · spendable M1 liability" accent="green" icon="money" />
|
||||
|
||||
<DashboardStatCard label="Due from head office" value={formatUsd(moneySupply?.interoffice?.dueFromHeadOffice)} hint="GL 1410 · HO allocation receivable" accent="blue" icon="rail" />
|
||||
|
||||
<DashboardStatCard label="M2 tokens" value={String(tokens.length)} hint="Registered · swap · convert · transfer" accent="gold" icon="rocket" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
||||
|
||||
<DashboardSection
|
||||
|
||||
title="Settlement rails"
|
||||
|
||||
subtitle="Enabled payment and chain paths"
|
||||
|
||||
icon="network"
|
||||
|
||||
action={
|
||||
|
||||
<button type="button" onClick={() => refresh()} className="text-xs text-[#00d4ff] hover:underline inline-flex items-center gap-1">
|
||||
|
||||
<NasaIcon name="refresh" size={12} className={loading ? 'nasa-icon--spin' : ''} />
|
||||
|
||||
{loading ? 'Refreshing…' : 'Refresh'}
|
||||
|
||||
</button>
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { useOffice24 } from './useOffice24';
|
||||
|
||||
import FineractLedgerBanner from '../omnl-dashboard/FineractLedgerBanner';
|
||||
|
||||
import DashboardStatCard from '../omnl-dashboard/DashboardStatCard';
|
||||
|
||||
import DashboardSection from '../omnl-dashboard/DashboardSection';
|
||||
|
||||
import QuickPortalLinks from '../omnl-dashboard/QuickPortalLinks';
|
||||
|
||||
import NasaPageHeader from '../omnl-dashboard/NasaPageHeader';
|
||||
|
||||
import NasaIcon, { StatusIcon } from '../../components/icons/NasaIcon';
|
||||
|
||||
import { formatUsd } from '../../utils/formatMoney';
|
||||
|
||||
|
||||
|
||||
export default function Office24Dashboard() {
|
||||
|
||||
const { office, tokens, health, moneySupply, loading, refresh } = useOffice24();
|
||||
|
||||
const profile = office as {
|
||||
|
||||
officeId?: number;
|
||||
|
||||
externalId?: string;
|
||||
|
||||
name?: string;
|
||||
|
||||
locked?: boolean;
|
||||
|
||||
tenantUser?: string;
|
||||
|
||||
settlement?: { defaultCurrency?: string; moneyLayers?: string[] };
|
||||
|
||||
rails?: { swift?: { enabled?: boolean }; hybx?: { enabled?: boolean }; chain138?: { enabled?: boolean } };
|
||||
|
||||
} | null;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<div className="dash-page o24-page max-w-[1400px] mx-auto px-4 py-6">
|
||||
|
||||
<div className="flex flex-wrap items-start justify-between gap-4 mb-2">
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
|
||||
<NasaPageHeader
|
||||
|
||||
icon="office"
|
||||
|
||||
missionId="O24-138"
|
||||
|
||||
title={profile?.name ?? 'HOSPITALLERS — Zardasht (Iraq / Iran Operations)'}
|
||||
|
||||
subtitle={profile?.externalId ?? 'HOSPITALLERS-ZARDASHT-IRAQ-IRAN'}
|
||||
|
||||
badges={
|
||||
|
||||
<>
|
||||
|
||||
<span className="nasa-badge nasa-badge--nominal">Office 24</span>
|
||||
|
||||
{profile?.locked && <span className="nasa-badge nasa-badge--caution">Single office · locked</span>}
|
||||
|
||||
</>
|
||||
|
||||
}
|
||||
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2 pt-2">
|
||||
|
||||
<Link to="/central-bank" className="nasa-btn inline-flex items-center gap-1">
|
||||
|
||||
<NasaIcon name="central-bank" size={12} /> Central Bank
|
||||
|
||||
</Link>
|
||||
|
||||
<Link to="/trade" className="nasa-btn nasa-btn--primary inline-flex items-center gap-1">
|
||||
|
||||
<NasaIcon name="trade" size={12} /> DBIS Trade
|
||||
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<QuickPortalLinks />
|
||||
|
||||
|
||||
|
||||
<FineractLedgerBanner moneySupply={moneySupply} loading={loading} officeName={profile?.name} />
|
||||
|
||||
|
||||
|
||||
<h2 className="dash-section-title mb-1 flex items-center gap-2">
|
||||
|
||||
<NasaIcon name="ledger" size={14} className="nasa-icon--telemetry" />
|
||||
|
||||
Office balances
|
||||
|
||||
</h2>
|
||||
|
||||
<p className="dash-section-subtitle mb-4">Live Fineract · {profile?.settlement?.defaultCurrency ?? 'USD'}</p>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
||||
|
||||
<DashboardStatCard label="Office ID" value={String(profile?.officeId ?? 24)} hint="Fineract office · HOSPITALLERS Ali" accent="green" icon="office" />
|
||||
|
||||
<DashboardStatCard label="M1 circulating" value={formatUsd(moneySupply?.M1?.circulating)} hint="GL 2100 · spendable M1 liability" accent="green" icon="money" />
|
||||
|
||||
<DashboardStatCard label="Due from head office" value={formatUsd(moneySupply?.interoffice?.dueFromHeadOffice)} hint="GL 1410 · HO allocation receivable" accent="blue" icon="rail" />
|
||||
|
||||
<DashboardStatCard label="M2 tokens" value={String(tokens.length)} hint="Registered · swap · convert · transfer" accent="gold" icon="rocket" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
||||
|
||||
<DashboardSection
|
||||
|
||||
title="Settlement rails"
|
||||
|
||||
subtitle="Enabled payment and chain paths"
|
||||
|
||||
icon="network"
|
||||
|
||||
action={
|
||||
|
||||
<button type="button" onClick={() => refresh()} className="text-xs text-[#00d4ff] hover:underline inline-flex items-center gap-1">
|
||||
|
||||
<NasaIcon name="refresh" size={12} className={loading ? 'nasa-icon--spin' : ''} />
|
||||
|
||||
{loading ? 'Refreshing…' : 'Refresh'}
|
||||
|
||||
</button>
|
||||
|
||||
}
|
||||
|
||||
>
|
||||
|
||||
<dl>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt className="flex items-center gap-1"><NasaIcon name="globe" size={12} /> SWIFT</dt>
|
||||
|
||||
<dd className="flex items-center justify-end gap-1">
|
||||
|
||||
<StatusIcon ok={!!profile?.rails?.swift?.enabled} />
|
||||
|
||||
{profile?.rails?.swift?.enabled ? 'Enabled' : 'Off'}
|
||||
|
||||
</dd>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt className="flex items-center gap-1"><NasaIcon name="rail" size={12} /> HYBX</dt>
|
||||
|
||||
<dd className="flex items-center justify-end gap-1">
|
||||
|
||||
<StatusIcon ok={!!profile?.rails?.hybx?.enabled} />
|
||||
|
||||
{profile?.rails?.hybx?.enabled ? 'Enabled' : 'Off'}
|
||||
|
||||
</dd>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt className="flex items-center gap-1"><NasaIcon name="network" size={12} /> Chain 138</dt>
|
||||
|
||||
<dd className="flex items-center justify-end gap-1">
|
||||
|
||||
<StatusIcon ok={!!profile?.rails?.chain138?.enabled} />
|
||||
|
||||
{profile?.rails?.chain138?.enabled ? 'Enabled' : 'Off'}
|
||||
|
||||
</dd>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt className="flex items-center gap-1"><NasaIcon name="trade" size={12} /> DBIS Exchange</dt>
|
||||
|
||||
<dd className="dash-kv-value--ok flex items-center justify-end gap-1">
|
||||
|
||||
<StatusIcon ok={(health as { status?: string })?.status === 'ok'} />
|
||||
|
||||
{(health as { status?: string })?.status ?? 'ok'}
|
||||
|
||||
</dd>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="dash-kv">
|
||||
|
||||
<dt>Fineract tenant</dt>
|
||||
|
||||
<dd className="text-xs font-mono">{profile?.tenantUser ?? 'ali_hospitallers_tenant'}</dd>
|
||||
|
||||
</div>
|
||||
|
||||
</dl>
|
||||
|
||||
</DashboardSection>
|
||||
|
||||
|
||||
|
||||
<DashboardSection title="M2 token registry" subtitle="Tradable lines on Chain 138" icon="rocket" className="lg:col-span-2">
|
||||
|
||||
<div className="overflow-x-auto max-h-[420px] overflow-y-auto rounded border border-[#1e4a8a]">
|
||||
|
||||
<table className="w-full text-sm nasa-table">
|
||||
|
||||
<thead className="sticky top-0">
|
||||
|
||||
<tr className="text-left">
|
||||
|
||||
<th className="py-2.5 px-3">Symbol</th>
|
||||
|
||||
<th className="py-2.5 px-3">Line</th>
|
||||
|
||||
<th className="py-2.5 px-3">Swap</th>
|
||||
|
||||
<th className="py-2.5 px-3">Convert</th>
|
||||
|
||||
<th className="py-2.5 px-3">Transfer</th>
|
||||
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
{tokens.map((t) => (
|
||||
|
||||
<tr key={t.address}>
|
||||
|
||||
<td className="py-2.5 px-3 font-medium font-mono text-[#e8f4ff]">{t.symbol}</td>
|
||||
|
||||
<td className="py-2.5 px-3 text-[#7a9bb8] text-xs">{t.omnlLine ?? 'M2'}</td>
|
||||
|
||||
<td className="py-2.5 px-3"><StatusIcon ok={t.swappable !== false} /></td>
|
||||
|
||||
<td className="py-2.5 px-3"><StatusIcon ok={t.convertible !== false} /></td>
|
||||
|
||||
<td className="py-2.5 px-3">
|
||||
|
||||
<StatusIcon ok={!!(t.transferableInternal || t.transferableExternal)} />
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
))}
|
||||
|
||||
{!tokens.length && (
|
||||
|
||||
<tr>
|
||||
|
||||
<td colSpan={5} className="py-6 px-3 text-center text-[#7a9bb8]">No M2 tokens loaded</td>
|
||||
|
||||
</tr>
|
||||
|
||||
)}
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</DashboardSection>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ log "=== 4/5 Push Fineract/API env to each LXC ==="
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
for CTID in 5825 5826 5827 5828; do
|
||||
bash scripts/deployment/push-portal-env-to-lxc.sh "$CTID" || log "WARN: env push failed for CT $CTID"
|
||||
omnl_pve_ssh "pct exec ${CTID} -- bash ${OMNL_PORTAL_ROOT:-/srv/ali-portal}/scripts/deployment/start-omnl-banking-portal.sh" 2>/dev/null || true
|
||||
omnl_pve_ssh "pct exec ${CTID} -- bash ${OMNL_PORTAL_ROOT:-/srv/zardasht-portal}/scripts/deployment/start-omnl-banking-portal.sh" 2>/dev/null || true
|
||||
done
|
||||
else
|
||||
log "WARN: no $ENV_FILE — skip LXC Fineract env"
|
||||
|
||||
@@ -8,7 +8,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/lib/omnl-pve-ssh.sh"
|
||||
|
||||
CTID="${OMNL_PCT_CTID:-5825}"
|
||||
PORTAL_ROOT="${OMNL_PORTAL_ROOT:-/srv/ali-portal}"
|
||||
PORTAL_ROOT="${OMNL_PORTAL_ROOT:-/srv/zardasht-portal}"
|
||||
PROJECT_SRC="${OMNL_PROJECT_SRC:-/home/projects/exchange}"
|
||||
STAGE="/tmp/omnl-banking-portal-$(date +%Y%m%d%H%M%S).tar.gz"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ set -euo pipefail
|
||||
CTID="${1:?CTID required}"
|
||||
REPO_DIR="${OMNL_BANK_ROOT:-$HOME/smom-dbis-138}"
|
||||
ENV_FILE="${OMNL_BANK_ENV:-$REPO_DIR/.env}"
|
||||
PORTAL_ROOT="${OMNL_PORTAL_ROOT:-/srv/ali-portal}"
|
||||
PORTAL_ROOT="${OMNL_PORTAL_ROOT:-/srv/zardasht-portal}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=lib/omnl-pve-ssh.sh
|
||||
source "${SCRIPT_DIR}/lib/omnl-pve-ssh.sh"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
# Start OMNL services from /srv/ali-portal inside PCT
|
||||
# Start OMNL services from /srv/zardasht-portal inside PCT
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="${OMNL_PORTAL_ROOT:-/srv/ali-portal}"
|
||||
ROOT="${OMNL_PORTAL_ROOT:-/srv/zardasht-portal}"
|
||||
LOG_DIR="${OMNL_BANK_LOG_DIR:-/var/log/omnl-bank}"
|
||||
NGINX_TEMPLATE="${ROOT}/deploy/nginx/omnl-lxc-portal.conf"
|
||||
mkdir -p "$LOG_DIR"
|
||||
@@ -48,7 +48,7 @@ fuser -k "${FRONTEND_PORT}/tcp" 2>/dev/null || true
|
||||
sleep 1
|
||||
|
||||
if command -v nginx >/dev/null 2>&1 && [ -f "$NGINX_TEMPLATE" ]; then
|
||||
sed "s|/srv/ali-portal|${ROOT}|g" "$NGINX_TEMPLATE" > "${LOG_DIR}/nginx.conf"
|
||||
sed "s|/srv/zardasht-portal|${ROOT}|g; s|/srv/ali-portal|${ROOT}|g" "$NGINX_TEMPLATE" > "${LOG_DIR}/nginx.conf"
|
||||
nginx -t -c "${LOG_DIR}/nginx.conf"
|
||||
nohup nginx -c "${LOG_DIR}/nginx.conf" >"${LOG_DIR}/frontend.log" 2>&1 &
|
||||
echo $! >"${LOG_DIR}/frontend.pid"
|
||||
|
||||
Reference in New Issue
Block a user