feat: wire production settlement rails for M2 mint, transfers, and bank SWIFT
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m31s
CI/CD Pipeline / Security Scanning (push) Successful in 3m4s
CI/CD Pipeline / Lint and Format (push) Failing after 45s
CI/CD Pipeline / Terraform Validation (push) Failing after 28s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 28s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 44s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 36s
Validation / validate-genesis (push) Successful in 30s
Validation / validate-terraform (push) Failing after 30s
Validation / validate-kubernetes (push) Failing after 10s
Validation / validate-smart-contracts (push) Failing after 12s
Validation / validate-security (push) Failing after 1m52s
Validation / validate-documentation (push) Failing after 18s
Verify Deployment / Verify Deployment (push) Failing after 57s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-29 02:54:53 -07:00
parent 17e5cb3222
commit 458f3b420b
19 changed files with 538 additions and 120 deletions

View File

@@ -16,6 +16,11 @@ import { computeOmnlReconcileAnchor } from '../../services/omnl-reconcile-anchor
import { getOmnlIntegrationStatus } from '../../services/omnl-integration-status';
import { getOmnlApiCatalog } from '../../services/omnl-api-catalog';
import omnlOpenApi from '../../resources/omnl-openapi.json';
import {
executeErc20Transfer,
executeM2TokenMint,
chainRailConfigured,
} from '../../services/omnl-settlement-chain';
const router = Router();
router.use(omnlRateLimiter);
@@ -329,7 +334,7 @@ router.get('/omnl/health', async (req: Request, res: Response) => {
/**
* POST /omnl/settlement/token-load — M2 fiat-backed token mint (Office 24 settlement).
*/
router.post('/omnl/settlement/token-load', (req: Request, res: Response) => {
router.post('/omnl/settlement/token-load', async (req: Request, res: Response) => {
const { lineId, amount, recipient, settlementRef, dryRun, symbol, tokenAddress } = req.body as {
lineId?: string;
amount?: string;
@@ -348,29 +353,127 @@ router.post('/omnl/settlement/token-load', (req: Request, res: Response) => {
(process.env.SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE === '1' ||
process.env.OMNL_ALLOW_CHAIN_MINT_EXECUTE === '1');
const loadId = settlementRef ?? `TL-${Date.now()}`;
res.json({
status: execute ? 'QUEUED' : 'DRY_RUN',
loadId,
lineId,
amount,
recipient,
symbol: symbol ?? null,
tokenAddress: tokenAddress ?? null,
settlementRef: settlementRef ?? null,
moneyLayer: 'M2',
loadFromGl: '2200',
creditGl: '2300',
capabilities: {
swappable: true,
convertible: true,
transferableInternal: true,
transferableExternal: true,
},
txHash: execute ? undefined : null,
message: execute
? 'Token load queued for ComplianceCore mint pipeline (M2 → on-chain)'
: 'M2 token load validated — set SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=1 to mint on-chain',
});
const capabilities = {
swappable: true,
convertible: true,
transferableInternal: true,
transferableExternal: true,
};
if (!execute) {
res.json({
status: 'DRY_RUN',
loadId,
lineId,
amount,
recipient,
symbol: symbol ?? null,
tokenAddress: tokenAddress ?? null,
settlementRef: settlementRef ?? null,
moneyLayer: 'M2',
loadFromGl: '2200',
creditGl: '2300',
capabilities,
txHash: null,
chainRailConfigured: chainRailConfigured(),
message: 'M2 token load validated — set SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=1 to mint on-chain',
});
return;
}
if (!tokenAddress?.startsWith('0x')) {
res.status(400).json({
error: 'tokenAddress required for on-chain mint',
status: 'QUEUED',
loadId,
capabilities,
});
return;
}
try {
const { txHash } = await executeM2TokenMint({
tokenAddress,
recipient,
amount,
});
res.json({
status: 'SETTLED',
loadId,
lineId,
amount,
recipient,
symbol: symbol ?? null,
tokenAddress,
settlementRef: settlementRef ?? null,
moneyLayer: 'M2',
capabilities,
txHash,
message: 'M2 token minted on Chain 138 — tradable, swappable, transferable',
});
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
res.status(502).json({
error: msg,
status: 'CHAIN_MINT_FAILED',
loadId,
lineId,
capabilities,
});
}
});
/**
* POST /omnl/settlement/token-transfer — ERC-20 transfer to web3 wallet (internal rail).
*/
router.post('/omnl/settlement/token-transfer', async (req: Request, res: Response) => {
const { tokenAddress, amount, recipient, settlementRef, dryRun, symbol } = req.body as {
tokenAddress?: string;
amount?: string;
recipient?: string;
settlementRef?: string;
dryRun?: boolean;
symbol?: string;
};
if (!tokenAddress || !amount || !recipient) {
res.status(400).json({ error: 'tokenAddress, amount, recipient required' });
return;
}
const execute =
!dryRun &&
(process.env.SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE === '1' ||
process.env.OMNL_ALLOW_CHAIN_MINT_EXECUTE === '1');
if (!execute) {
res.json({
status: 'DRY_RUN',
transferId: settlementRef ?? `TT-${Date.now()}`,
tokenAddress,
amount,
recipient,
symbol: symbol ?? null,
txHash: null,
message: 'Transfer validated — enable SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=1 for on-chain delivery',
});
return;
}
try {
const { txHash } = await executeErc20Transfer({ tokenAddress, recipient, amount });
res.json({
status: 'SETTLED',
transferId: settlementRef ?? `TT-${Date.now()}`,
tokenAddress,
amount,
recipient,
symbol: symbol ?? null,
txHash,
message: 'ERC-20 transferred to recipient wallet on Chain 138',
});
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
res.status(502).json({ error: msg, status: 'CHAIN_TRANSFER_FAILED' });
}
});
export default router;