fix: dashboard ledger fallback via health?ledger=1
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m16s
CI/CD Pipeline / Security Scanning (push) Successful in 2m27s
CI/CD Pipeline / Terraform Validation (push) Has been cancelled
CI/CD Pipeline / Kubernetes Validation (push) Has been cancelled
CI/CD Pipeline / Lint and Format (push) Has been cancelled
Validation / validate-genesis (push) Has started running
Validation / validate-terraform (push) Has been cancelled
Validation / validate-kubernetes (push) Has been cancelled
Validation / validate-smart-contracts (push) Has been cancelled
Validation / validate-security (push) Has been cancelled
Validation / validate-documentation (push) Has been cancelled
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m16s
CI/CD Pipeline / Security Scanning (push) Successful in 2m27s
CI/CD Pipeline / Terraform Validation (push) Has been cancelled
CI/CD Pipeline / Kubernetes Validation (push) Has been cancelled
CI/CD Pipeline / Lint and Format (push) Has been cancelled
Validation / validate-genesis (push) Has started running
Validation / validate-terraform (push) Has been cancelled
Validation / validate-kubernetes (push) Has been cancelled
Validation / validate-smart-contracts (push) Has been cancelled
Validation / validate-security (push) Has been cancelled
Validation / validate-documentation (push) Has been cancelled
NPM proxies block dedicated money-supply paths; embed public ledger snapshot in /health when ledger=1 and fall back from dashboard hooks. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -13,11 +13,16 @@ export type MoneySupply = {
|
||||
};
|
||||
|
||||
async function loadMoneySupply(): Promise<MoneySupply | null> {
|
||||
const publicRes = await fetch(settlementApi('/public/money-supply'));
|
||||
if (publicRes.ok) return publicRes.json();
|
||||
for (const path of ['/public/money-supply', '/money-supply/public']) {
|
||||
const res = await fetch(settlementApi(path));
|
||||
if (res.ok) return res.json();
|
||||
}
|
||||
|
||||
const legacyRes = await fetch(settlementApi('/money-supply/public'));
|
||||
if (legacyRes.ok) return legacyRes.json();
|
||||
const healthRes = await fetch(`${settlementApi('/health')}?ledger=1`);
|
||||
if (healthRes.ok) {
|
||||
const data = (await healthRes.json()) as { moneySupply?: MoneySupply };
|
||||
if (data.moneySupply) return data.moneySupply;
|
||||
}
|
||||
|
||||
const apiKey = import.meta.env.VITE_OMNL_API_KEY;
|
||||
if (!apiKey) return null;
|
||||
|
||||
@@ -10,6 +10,19 @@ export type M2Token = DexToken & {
|
||||
transferableExternal?: boolean;
|
||||
};
|
||||
|
||||
async function loadOfficeMoneySupply(): Promise<MoneySupply | null> {
|
||||
for (const path of ['/public/money-supply', '/money-supply/public']) {
|
||||
const res = await fetch(settlementApi(path));
|
||||
if (res.ok) return res.json();
|
||||
}
|
||||
const healthRes = await fetch(`${settlementApi('/health')}?ledger=1`);
|
||||
if (healthRes.ok) {
|
||||
const data = (await healthRes.json()) as { moneySupply?: MoneySupply };
|
||||
if (data.moneySupply) return data.moneySupply;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function useOffice24() {
|
||||
const [office, setOffice] = useState<Record<string, unknown> | null>(null);
|
||||
const [tokens, setTokens] = useState<M2Token[]>([]);
|
||||
@@ -24,7 +37,7 @@ export function useOffice24() {
|
||||
fetch(settlementApi('/office')).then((r) => r.json()),
|
||||
fetch(settlementApi('/tokens/m2')).then((r) => r.json()),
|
||||
fetch(exchangeApi('/health')).then((r) => r.json()),
|
||||
fetch(settlementApi('/public/money-supply')).then((r) => (r.ok ? r.json() : null)),
|
||||
fetch(loadOfficeMoneySupply()),
|
||||
]);
|
||||
setOffice(o);
|
||||
setTokens(Array.isArray(t.tokens) ? t.tokens : []);
|
||||
|
||||
@@ -57,7 +57,7 @@ export function createSettlementRouter(): Router {
|
||||
const officeId = settlementOfficeId();
|
||||
const profile = loadOfficeProfile();
|
||||
|
||||
router.get('/health', (_req, res) => {
|
||||
router.get('/health', async (req, res) => {
|
||||
let chainStats = { total: 0, active: 0 };
|
||||
try {
|
||||
const reg = loadOmnlChainRegistry();
|
||||
@@ -65,7 +65,7 @@ export function createSettlementRouter(): Router {
|
||||
} catch {
|
||||
/* optional */
|
||||
}
|
||||
res.json({
|
||||
const payload: Record<string, unknown> = {
|
||||
service: 'omnl-settlement-middleware',
|
||||
status: 'ok',
|
||||
mode: process.env.SETTLEMENT_MIDDLEWARE_CONFIG?.includes('production') ? 'production' : 'standard',
|
||||
@@ -77,7 +77,38 @@ export function createSettlementRouter(): Router {
|
||||
name: profile.name,
|
||||
},
|
||||
enforceSingleOffice: loadConfig().enforceSingleOffice ?? false,
|
||||
});
|
||||
};
|
||||
const includeLedger =
|
||||
req.query.ledger === '1' ||
|
||||
req.query.include === 'money-supply' ||
|
||||
req.query.include === 'ledger';
|
||||
if (includeLedger) {
|
||||
const cfg = loadConfig();
|
||||
const allow =
|
||||
cfg.production.onlineBankMode || process.env.OMNL_PUBLIC_MONEY_SUPPLY === '1';
|
||||
if (allow) {
|
||||
try {
|
||||
const [balances, fineractConnected] = await Promise.all([
|
||||
fetchGlBalances(officeId),
|
||||
fineractOfficeReachable(officeId),
|
||||
]);
|
||||
const snapshot = buildMoneySupplySnapshot(officeId, balances);
|
||||
const hasActivity = Object.values(balances).some((v) => Math.abs(parseFloat(v) || 0) > 0);
|
||||
payload.moneySupply = {
|
||||
...snapshot,
|
||||
fineractConnected,
|
||||
fineractLive: fineractConnected && hasActivity,
|
||||
interoffice: {
|
||||
dueFromHeadOffice: balances['1410'] ?? '0',
|
||||
gl1410: balances['1410'] ?? '0',
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
payload.moneySupplyError = e instanceof Error ? e.message : String(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
res.json(payload);
|
||||
});
|
||||
|
||||
router.get('/office', (_req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user