fix: public ledger endpoint for dashboard money-supply
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Has been cancelled
CI/CD Pipeline / Security Scanning (push) Has been cancelled
CI/CD Pipeline / Lint and Format (push) Has been cancelled
CI/CD Pipeline / Terraform Validation (push) Has been cancelled
CI/CD Pipeline / Kubernetes Validation (push) Has been cancelled
Validation / validate-genesis (push) Has been cancelled
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

Add /public/money-supply route and restrict office param to numeric IDs so
NPM proxies no longer hit the authenticated /money-supply/:id handler.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-29 00:59:49 -07:00
parent a29b32f042
commit a2c088bed0
3 changed files with 38 additions and 31 deletions

View File

@@ -13,9 +13,12 @@ export type MoneySupply = {
};
async function loadMoneySupply(): Promise<MoneySupply | null> {
const publicRes = await fetch(settlementApi('/money-supply/public'));
const publicRes = await fetch(settlementApi('/public/money-supply'));
if (publicRes.ok) return publicRes.json();
const legacyRes = await fetch(settlementApi('/money-supply/public'));
if (legacyRes.ok) return legacyRes.json();
const apiKey = import.meta.env.VITE_OMNL_API_KEY;
if (!apiKey) return null;

View File

@@ -24,7 +24,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('/money-supply/public')).then((r) => (r.ok ? r.json() : null)),
fetch(settlementApi('/public/money-supply')).then((r) => (r.ok ? r.json() : null)),
]);
setOffice(o);
setTokens(Array.isArray(t.tokens) ? t.tokens : []);

View File

@@ -23,6 +23,35 @@ function requireApiKey(req: Request, res: Response): boolean {
return false;
}
async function respondPublicMoneySupply(res: Response, officeId: number): Promise<void> {
const cfg = loadConfig();
const allow =
cfg.production.onlineBankMode || process.env.OMNL_PUBLIC_MONEY_SUPPLY === '1';
if (!allow) {
res.status(404).json({ error: 'Public money supply disabled' });
return;
}
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);
res.json({
...snapshot,
fineractConnected,
fineractLive: fineractConnected && hasActivity,
interoffice: {
dueFromHeadOffice: balances['1410'] ?? '0',
gl1410: balances['1410'] ?? '0',
},
});
} catch (e) {
res.status(500).json({ error: e instanceof Error ? e.message : String(e) });
}
}
export function createSettlementRouter(): Router {
const router = Router();
const officeId = settlementOfficeId();
@@ -59,34 +88,9 @@ export function createSettlementRouter(): Router {
});
});
router.get('/money-supply/public', async (_req, res) => {
const cfg = loadConfig();
const allow =
cfg.production.onlineBankMode || process.env.OMNL_PUBLIC_MONEY_SUPPLY === '1';
if (!allow) {
res.status(404).json({ error: 'Public money supply disabled' });
return;
}
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);
res.json({
...snapshot,
fineractConnected,
fineractLive: fineractConnected && hasActivity,
interoffice: {
dueFromHeadOffice: balances['1410'] ?? '0',
gl1410: balances['1410'] ?? '0',
},
});
} catch (e) {
res.status(500).json({ error: e instanceof Error ? e.message : String(e) });
}
});
router.get('/public/money-supply', (_req, res) => respondPublicMoneySupply(res, officeId));
router.get('/money-supply/public', (_req, res) => respondPublicMoneySupply(res, officeId));
router.get('/money-supply', async (req, res) => {
if (!requireApiKey(req, res)) return;
@@ -97,7 +101,7 @@ export function createSettlementRouter(): Router {
}
});
router.get('/money-supply/:officeIdParam', async (req, res) => {
router.get('/money-supply/:officeIdParam(\\d+)', async (req, res) => {
if (!requireApiKey(req, res)) return;
try {
const requested = parseInt(req.params.officeIdParam, 10);