"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.processTokenLoad = processTokenLoad; const uuid_1 = require("uuid"); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const settlement_core_1 = require("@dbis/settlement-core"); const config_1 = require("../config"); const fineract_1 = require("../adapters/fineract"); const omnl_1 = require("../adapters/omnl"); const settlement_store_1 = require("../store/settlement-store"); function loadTokenRegistry() { const registryPath = process.env.OMNL_M2_TOKEN_REGISTRY || path_1.default.resolve(__dirname, '../../../config/omnl-m2-token-registry.v1.json'); return JSON.parse(fs_1.default.readFileSync(registryPath, 'utf8')); } function resolveTokenAddress(req) { if (req.tokenAddress?.startsWith('0x')) return req.tokenAddress; const registry = loadTokenRegistry(); const byLine = (0, settlement_core_1.findM2TokenByLineId)(registry, req.lineId); if (byLine?.address.startsWith('0x') && byLine.address !== '0x0000000000000000000000000000000000000000') { return byLine.address; } if (req.symbol) { const bySym = registry.tokens.find((t) => t.symbol.toLowerCase() === req.symbol.toLowerCase()); if (bySym?.address.startsWith('0x') && bySym.address !== '0x0000000000000000000000000000000000000000') { return bySym.address; } } return undefined; } async function processTokenLoad(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: { idempotencyKey: req.idempotencyKey, officeId, valueDate: now.slice(0, 10), currency: req.currency ?? 'USD', amount: req.amount, creditorIban: 'INTERNAL-M2-TOKEN-LOAD', beneficiaryName: req.recipientAddress, remittanceInfo: `M2→M3 token load ${req.lineId} → ${req.symbol ?? req.tokenAddress ?? 'token'}`, moneyLayers: ['M2', 'M3'], rail: 'INTERNAL', convertToCrypto: { enabled: true, targetChainId: 138, tokenLineId: req.lineId, recipientAddress: req.recipientAddress, }, }, errors: [], createdAt: now, updatedAt: now, }; const advance = (phase, patch = {}) => { record = { ...record, phase, updatedAt: new Date().toISOString(), ...patch }; settlement_store_1.settlementStore.save(record); }; try { advance('VALIDATED'); advance('VERBIAGE_ROLLED', { verbiageDocument: [ `OMNL M2→M3 fiat-backed token load`, `Office ${officeId} · line ${req.lineId}`, `Amount ${req.amount} · recipient ${req.recipientAddress}`, `GL ${settlement_core_1.GL_CODES.M2_BROAD} → ${settlement_core_1.GL_CODES.M3_TOKEN_LIABILITY}`, ].join('\n'), }); const balances = await (0, fineract_1.fetchGlBalances)(officeId); const snap = (0, settlement_core_1.buildMoneySupplySnapshot)(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 (M2 load ${loadAmount}/${req.amount}, M3 headroom ${m3Check.loadAmount})`); advance('FAILED'); return record; } const amount = parseFloat(loadAmount) || 0; if (amount > 0) { const [debitGlId, creditGlId] = await Promise.all([ (0, fineract_1.resolveGlAccountId)(profile.settlement.glM2 ?? settlement_core_1.GL_CODES.M2_BROAD), (0, fineract_1.resolveGlAccountId)(profile.settlement.glM3 ?? settlement_core_1.GL_CODES.M3_TOKEN_LIABILITY), ]); const je = await (0, fineract_1.postJournalEntry)({ officeId, transactionDate: now.slice(0, 10), referenceNumber: req.idempotencyKey, comments: `M2→M3 token load ${req.lineId}`, debits: [{ glAccountId: debitGlId, amount }], credits: [{ glAccountId: creditGlId, amount }], }); advance('FINERACT_POSTED', { fineractJournalRef: String(je.resourceId) }); } else { advance('FINERACT_POSTED'); } advance('HYBX_RAIL_DISPATCHED'); advance('ISO20022_ARCHIVED'); const mint = await (0, omnl_1.requestTokenMint)({ lineId: req.lineId, amount: loadAmount, recipient: req.recipientAddress, settlementRef: record.settlementId, dryRun: !cfg.production.allowChainMintExecute, symbol: req.symbol, tokenAddress: resolveTokenAddress(req), }); advance('CHAIN_MINT_REQUESTED', { chainTxHash: mint.txHash }); advance('SETTLED'); return record; } catch (err) { record.errors.push(err instanceof Error ? err.message : String(err)); advance('FAILED'); return record; } }