Files
smom-dbis-138/services/settlement-middleware/dist/workflows/external-transfer.js
zaragoza444 5229c2d888
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m13s
CI/CD Pipeline / Lint and Format (push) Has been cancelled
CI/CD Pipeline / Security Scanning (push) Has been cancelled
CI/CD Pipeline / Terraform Validation (push) Has been cancelled
CI/CD Pipeline / Kubernetes Validation (push) Has been cancelled
Deploy ChainID 138 / Deploy ChainID 138 (push) Has been cancelled
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (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
Verify Deployment / Verify Deployment (push) Has been cancelled
fix(omnl): production blockers for M0-M4 settlement stack
Exempt dashboard read APIs from anonymous rate limits, preserve nginx-injected auth, wire chain-mint and DB env through deploy/LXC scripts, resolve M3 token addresses from registry, and harden super-admin seeding.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 06:47:20 -07:00

155 lines
6.9 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processExternalTransfer = processExternalTransfer;
exports.getMoneySupply = getMoneySupply;
exports.getSettlementStatus = getSettlementStatus;
const uuid_1 = require("uuid");
const settlement_core_1 = require("@dbis/settlement-core");
const config_1 = require("../config");
const fineract_1 = require("../adapters/fineract");
const hybx_production_1 = require("../adapters/hybx-production");
const omnl_1 = require("../adapters/omnl");
const swift_1 = require("../adapters/swift");
const settlement_store_1 = require("../store/settlement-store");
async function processExternalTransfer(input) {
const cfg = (0, config_1.loadConfig)();
const profile = (0, config_1.loadOfficeProfile)();
const officeId = (0, config_1.settlementOfficeId)(input.officeId);
const req = { ...input, officeId };
const existing = settlement_store_1.settlementStore.getByIdempotencyKey(req.idempotencyKey);
if (existing?.phase === 'SETTLED')
return existing;
const now = new Date().toISOString();
let record = existing ?? {
settlementId: (0, uuid_1.v4)(),
idempotencyKey: req.idempotencyKey,
phase: 'RECEIVED',
request: req,
errors: [],
createdAt: now,
updatedAt: now,
};
const advance = (phase, patch = {}) => {
record = { ...record, phase, updatedAt: new Date().toISOString(), ...patch };
settlement_store_1.settlementStore.save(record);
};
try {
if (!(0, settlement_core_1.isIbanValid)(req.creditorIban)) {
throw new Error(`Invalid creditor IBAN: ${req.creditorIban}`);
}
advance('VALIDATED');
const verbiage = (0, settlement_core_1.rollExternalTransferVerbiage)(req);
advance('VERBIAGE_ROLLED', { verbiageDocument: verbiage });
const amount = parseFloat(req.amount) || 0;
const tf = req.tradeFinance;
const gl = tf ? (0, settlement_core_1.resolveInstrumentGl)(tf.instrument) : null;
const debitGl = gl?.debitGl ?? profile.settlement.glSettlement ?? cfg.moneySupply.glSettlement;
const creditGl = gl?.creditGl ?? profile.settlement.glM1 ?? cfg.moneySupply.glM1;
if (amount > 0) {
const [debitGlId, creditGlId] = await Promise.all([
(0, fineract_1.resolveGlAccountId)(debitGl),
(0, fineract_1.resolveGlAccountId)(creditGl),
]);
const je = await (0, fineract_1.postJournalEntry)({
officeId: req.officeId,
transactionDate: req.valueDate,
referenceNumber: req.idempotencyKey,
comments: verbiage.slice(0, 500),
debits: [{ glAccountId: debitGlId, amount }],
credits: [{ glAccountId: creditGlId, amount }],
});
advance('FINERACT_POSTED', { fineractJournalRef: String(je.resourceId) });
}
else {
advance('FINERACT_POSTED');
}
if (cfg.rails.hybx.enabled && req.rail !== 'INTERNAL') {
const hybx = new hybx_production_1.HybxProductionRail();
const pay = await hybx.dispatchPayment({
idempotencyKey: req.idempotencyKey,
amount: req.amount,
currency: req.currency,
creditorIban: req.creditorIban,
creditorBic: req.creditorBic,
beneficiaryName: req.beneficiaryName,
remittanceInfo: req.remittanceInfo,
rail: req.rail,
});
advance('HYBX_RAIL_DISPATCHED', { hybxPaymentId: pay.paymentId });
}
else {
advance('HYBX_RAIL_DISPATCHED');
}
const swiftKind = (0, settlement_core_1.swiftKindForRequest)(req);
const swiftRaw = swiftKind === 'MT102'
? (0, swift_1.buildMt102Stub)({
senderRef: req.idempotencyKey,
currency: req.currency,
amount: req.amount,
valueDate: req.valueDate,
orderingInstitution: req.orderingName ?? cfg.omnlLegalName,
beneficiary: req.beneficiaryName,
iban: req.creditorIban,
remittance: req.remittanceInfo,
})
: (0, swift_1.buildMt103Stub)({
senderRef: req.idempotencyKey,
currency: req.currency,
amount: req.amount,
valueDate: req.valueDate,
orderingCustomer: req.orderingName ?? cfg.omnlLegalName,
beneficiary: req.beneficiaryName,
iban: req.creditorIban,
bic: req.creditorBic,
remittance: req.remittanceInfo,
});
if (cfg.rails.swift.enabled) {
await (0, swift_1.forwardSwiftToListener)(swiftRaw);
}
const iso = await (0, omnl_1.archiveIso20022)({
messageType: swiftKind === 'MT102' ? 'pacs.008' : 'pacs.008',
direction: 'OUTBOUND',
raw: swiftRaw,
settlementRef: record.settlementId,
});
advance('ISO20022_ARCHIVED', { iso20022MessageId: iso.messageId });
if (req.convertToCrypto?.enabled) {
const balances = await (0, fineract_1.fetchGlBalances)(req.officeId);
const snap = (0, settlement_core_1.buildMoneySupplySnapshot)(req.officeId, balances);
const { loadAmount, fullyBacked } = (0, settlement_core_1.m2FiatToTokenLoadAmount)(req.amount, snap.M2.broadMoney);
const m3Check = (0, settlement_core_1.m3TokenLoadAmount)(loadAmount, snap.M2.broadMoney, snap.M3.tokenLiabilities);
if (!fullyBacked || !m3Check.fullyBacked) {
record.errors.push(`M2/M3 backing insufficient for token load (${loadAmount}/${req.amount}, M3 headroom ${m3Check.loadAmount})`);
advance('FAILED');
return record;
}
const mint = await (0, omnl_1.requestTokenMint)({
lineId: req.convertToCrypto.tokenLineId,
amount: m3Check.loadAmount,
recipient: req.convertToCrypto.recipientAddress,
settlementRef: record.settlementId,
dryRun: !cfg.production.allowChainMintExecute,
});
advance('CHAIN_MINT_REQUESTED', { chainTxHash: mint.txHash });
}
else {
advance('CHAIN_MINT_REQUESTED');
}
advance('SETTLED');
return record;
}
catch (err) {
const msg = err instanceof Error ? err.message : String(err);
record.errors.push(msg);
advance('FAILED');
return record;
}
}
async function getMoneySupply(officeId) {
const balances = await (0, fineract_1.fetchGlBalances)(officeId);
return (0, settlement_core_1.buildMoneySupplySnapshot)(officeId, balances);
}
function getSettlementStatus(id) {
return settlement_store_1.settlementStore.getById(id);
}