diff --git a/config/dbis-exchange.production.v1.json b/config/dbis-exchange.production.v1.json index 120776b..d0e4fe2 100644 --- a/config/dbis-exchange.production.v1.json +++ b/config/dbis-exchange.production.v1.json @@ -1,53 +1,26 @@ { - "$schema": "DBIS Exchange — production (128-chain OMNL Bank)", - "version": "1.0.0", - "chainId": 138, - "brandName": "DBIS Exchange", - "officeId": 24, - "settlementOfficeExternalId": "HOSPITALLERS-ALI-IRAQ-IRAN", - "chainRegistry": "config/omnl-supported-chains.v1.json", - "maxSupportedChains": 128, - "routers": { - "enhancedSwapRouterV2": "0xa421706768aeb7fafa2d912c5e10824ef3437ad4", - "uniswapV2": "0x3019A7fDc76ba7F64F18d78e66842760037ee638", - "sushiV2": "0xB37b93D38559f53b62ab020A14919f2630a1aE34" - }, - "factory": { - "uniswapV2": "0x0C30F6e67Ab3667fCc2f5CEA8e274ef1FB920279" - }, - "tokens": [], - "defaultSlippageBps": 50, - "production": { - "requireApiKey": true, - "monitorSwaps": true, - "postSwapSettlementAudit": true, - "onlineBankMode": true - } - } - - diff --git a/config/settlement-middleware.production.v1.json b/config/settlement-middleware.production.v1.json index 999ed84..00edf6c 100644 --- a/config/settlement-middleware.production.v1.json +++ b/config/settlement-middleware.production.v1.json @@ -1,69 +1,48 @@ { - "$schema": "OMNL central-bank settlement — production profile", - "version": "1.0.0", - "omnlLegalName": "ORGANISATION MONDIALE DU NUMERIQUE L.P.B.C.", - "defaultOfficeId": 24, - "enforceSingleOffice": true, - "settlementOffice": { - "officeId": 24, - "externalId": "HOSPITALLERS-ALI-IRAQ-IRAN", - "name": "HOSPITALLERS Ali Iraq-Iran", - "profilePath": "config/offices/office-24-settlement.v1.json" - }, - "defaultCurrency": "USD", - "chainRegistry": "config/omnl-supported-chains.v1.json", - "maxSupportedChains": 128, - "rails": { - - "swift": { "enabled": true, "listenerUrl": "http://192.168.11.114:8788" }, - - "hybx": { "enabled": true, "sidecarUrl": "http://192.168.11.89:8080" }, - - "chain138": { "enabled": true, "rpcEnv": "RPC_URL_138", "defaultLineId": "USD-M2" }, - - "multiChain": { "enabled": true, "registryPath": "config/omnl-supported-chains.v1.json", "primaryChainId": 138 } - + "swift": { + "enabled": true, + "listenerUrl": "http://192.168.11.114:8788" + }, + "hybx": { + "enabled": true, + "sidecarUrl": "http://192.168.11.89:8080" + }, + "chain138": { + "enabled": true, + "rpcEnv": "RPC_URL_138", + "defaultLineId": "USD-M2" + }, + "multiChain": { + "enabled": true, + "registryPath": "config/omnl-supported-chains.v1.json", + "primaryChainId": 138 + } }, - "moneySupply": { - "glM0": "1050", - "glM1": "2100", - "glM2": "2200", - "glSettlement": "1000" - }, - "production": { - "requireApiKey": true, - "allowHybxProduction": true, - "allowChainMintExecute": true, - "onlineBankMode": true - } - } - - diff --git a/frontend-dapp/package.json b/frontend-dapp/package.json index f73ba82..b81e00d 100644 --- a/frontend-dapp/package.json +++ b/frontend-dapp/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "dev": "vite", - "build": "NODE_OPTIONS='--max-old-space-size=4096' vite build", + "build": "node --max-old-space-size=4096 ./node_modules/vite/bin/vite.js build", "build:check": "tsc && NODE_OPTIONS='--max-old-space-size=4096' vite build", "preview": "vite preview", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", diff --git a/frontend-dapp/src/config/dex.ts b/frontend-dapp/src/config/dex.ts index b2973c0..f44337a 100644 --- a/frontend-dapp/src/config/dex.ts +++ b/frontend-dapp/src/config/dex.ts @@ -1,141 +1,60 @@ /** DBIS Exchange — Chain 138 DEX addresses (Pancake/Uniswap V2 compatible) */ - export const DBIS_EXCHANGE_CHAIN_ID = 138; - - - export const TOKEN_AGGREGATION_URL = - import.meta.env.VITE_TOKEN_AGGREGATION_URL || 'http://localhost:3000'; - - - export const DBIS_EXCHANGE_URL = - import.meta.env.VITE_DBIS_EXCHANGE_URL || 'http://localhost:3012'; - - - export const SETTLEMENT_MIDDLEWARE_URL = - import.meta.env.VITE_SETTLEMENT_MIDDLEWARE_URL || 'http://localhost:3011'; - - - export const ENHANCED_SWAP_ROUTER_V2 = - import.meta.env.VITE_ENHANCED_SWAP_ROUTER_V2 || - '0xa421706768aeb7fafa2d912c5e10824ef3437ad4'; - - - export const UNISWAP_V2_ROUTER_138 = - import.meta.env.VITE_UNISWAP_V2_ROUTER_138 || - '0x3019A7fDc76ba7F64F18d78e66842760037ee638'; - - - export type DexToken = { - symbol: string; - name: string; - address: string; - decimals: number; - native?: boolean; - omnlLine?: string; - moneyLayer?: string; - currencyCode?: string; - swappable?: boolean; - convertible?: boolean; - transferableInternal?: boolean; - transferableExternal?: boolean; - }; - - - /** Fallback when exchange API unavailable */ - export const DEFAULT_TOKENS: DexToken[] = [ - { symbol: 'ETH', name: 'Ether', address: '0x0000000000000000000000000000000000000000', decimals: 18, native: true, omnlLine: 'USD-M2', moneyLayer: 'M2' }, - { symbol: 'WETH', name: 'Wrapped Ether', address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', decimals: 18, omnlLine: 'USD-M2', moneyLayer: 'M2' }, - { symbol: 'USDT', name: 'Tether USD', address: '0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1', decimals: 6, omnlLine: 'USD-M2', moneyLayer: 'M2' }, - { symbol: 'USDC', name: 'USD Coin', address: '0x71D6687F38b93CCad569Fa6352c876eea967201b', decimals: 6, omnlLine: 'USD-M2', moneyLayer: 'M2' }, - { symbol: 'cUSDT', name: 'Compliant USDT', address: '0x93E66202A11B1772E55407B32B44e5Cd8eda7f22', decimals: 6, omnlLine: 'USD-M2', moneyLayer: 'M2' }, - { symbol: 'cUSDC', name: 'Compliant USDC', address: '0xf22258f57794CC8E06237084b353Ab30fFfa640b', decimals: 6, omnlLine: 'USD-M2', moneyLayer: 'M2' }, - ]; - - - export function parseAmountToWei(amount: string, decimals: number): string { - const [whole, frac = ''] = amount.split('.'); - const padded = (frac + '0'.repeat(decimals)).slice(0, decimals); - return BigInt(`${whole}${padded}` || '0').toString(); - } - - - export function formatAmountFromWei(wei: string, decimals: number): string { - const v = BigInt(wei || '0'); - const base = 10n ** BigInt(decimals); - const whole = v / base; - const frac = v % base; - if (frac === 0n) return whole.toString(); - return `${whole}.${frac.toString().padStart(decimals, '0').replace(/0+$/, '')}`; - } - - - export async function fetchExchangeTokens(): Promise { - try { - const res = await fetch(`${DBIS_EXCHANGE_URL.replace(/\/$/, '')}/api/v1/exchange/tokens`); - if (!res.ok) return DEFAULT_TOKENS; - const data = await res.json(); - return Array.isArray(data.tokens) && data.tokens.length > 0 ? data.tokens : DEFAULT_TOKENS; - } catch { - return DEFAULT_TOKENS; - } - } - - diff --git a/services/dbis-exchange/src/adapters/settlement.ts b/services/dbis-exchange/src/adapters/settlement.ts index f48873c..8f9454b 100644 --- a/services/dbis-exchange/src/adapters/settlement.ts +++ b/services/dbis-exchange/src/adapters/settlement.ts @@ -1,317 +1,150 @@ import axios from 'axios'; - import { JsonRpcProvider, Contract, formatUnits } from 'ethers'; - import { settlementUrl } from '../config'; - import type { M2TokenCapabilities } from '@dbis/settlement-core'; - - const ERC20_ABI = ['function balanceOf(address) view returns (uint256)', 'function decimals() view returns (uint8)']; - - - export async function fetchFundLedger(officeId: number, apiKey?: string) { - const headers: Record = {}; - if (apiKey) headers.Authorization = `Bearer ${apiKey}`; - const { data } = await axios.get(`${settlementUrl()}/api/v1/settlement/money-supply`, { - headers, - timeout: 60000, - }); - return { officeId, fundLedger: data }; - } - - - export async function fetchOfficeProfile() { - const { data } = await axios.get(`${settlementUrl()}/api/v1/settlement/office`, { timeout: 15000 }); - return data; - } - - - export async function auditSwapToSettlement(payload: { - idempotencyKey: string; - amount: string; - currency: string; - recipientAddress: string; - remittanceInfo: string; - tokenLineId?: string; - apiKey?: string; - }) { - const lineId = payload.tokenLineId ?? `${payload.currency}-M2`; - const headers: Record = { 'Content-Type': 'application/json' }; - if (payload.apiKey) headers.Authorization = `Bearer ${payload.apiKey}`; - const { data } = await axios.post( - `${settlementUrl()}/api/v1/settlement/convert/fiat-to-crypto`, - { - idempotencyKey: payload.idempotencyKey, - amount: payload.amount, - currency: payload.currency, - creditorIban: 'GB82WEST12345698765432', - beneficiaryName: 'DBIS Exchange settlement audit', - remittanceInfo: payload.remittanceInfo, - convertToCrypto: { - enabled: true, - targetChainId: 138, - tokenLineId: lineId, - recipientAddress: payload.recipientAddress, - }, - }, - { headers, timeout: 120000, validateStatus: () => true }, - ); - return data; - } - - - export async function requestM2TokenLoad(payload: { - idempotencyKey: string; - lineId: string; - symbol: string; - tokenAddress: string; - amount: string; - recipientAddress: string; - currency?: string; - apiKey?: string; - }) { - const headers: Record = { 'Content-Type': 'application/json' }; - if (payload.apiKey) headers.Authorization = `Bearer ${payload.apiKey}`; - const { data } = await axios.post( - `${settlementUrl()}/api/v1/settlement/token-load`, - { - idempotencyKey: payload.idempotencyKey, - lineId: payload.lineId, - symbol: payload.symbol, - tokenAddress: payload.tokenAddress, - amount: payload.amount, - recipientAddress: payload.recipientAddress, - currency: payload.currency, - }, - { headers, timeout: 120000, validateStatus: () => true }, - ); - return data; - } - - - export async function requestInternalTransfer(payload: { - idempotencyKey: string; - tokenAddress: string; - tokenSymbol: string; - amount: string; - recipientAddress: string; - senderAddress?: string; - apiKey?: string; - }) { - const headers: Record = { 'Content-Type': 'application/json' }; - if (payload.apiKey) headers.Authorization = `Bearer ${payload.apiKey}`; - const { data } = await axios.post( - `${settlementUrl()}/api/v1/settlement/transfer/internal`, - { - ...payload, - moneyLayers: ['M2'], - }, - { headers, timeout: 120000, validateStatus: () => true }, - ); - return data; - } - - - export async function requestExternalTransfer(payload: { - idempotencyKey: string; - tokenAddress: string; - tokenSymbol: string; - amount: string; - recipientAddress: string; - creditorIban: string; - beneficiaryName?: string; - currency?: string; - remittanceInfo?: string; - apiKey?: string; - }) { - const headers: Record = { 'Content-Type': 'application/json' }; - if (payload.apiKey) headers.Authorization = `Bearer ${payload.apiKey}`; - const { data } = await axios.post( - `${settlementUrl()}/api/v1/settlement/transfer/external`, - { - ...payload, - moneyLayers: ['M2'], - rail: 'SWIFT', - }, - { headers, timeout: 120000, validateStatus: () => true }, - ); - return data; - } - - - export async function fetchCryptoLedger( - rpcUrl: string, - wallet: string, - tokens: { address: string; symbol: string; decimals: number; native?: boolean }[], - ) { - const provider = new JsonRpcProvider(rpcUrl); - const balances: Record = {}; - for (const t of tokens) { - if (t.native || t.address === '0x0000000000000000000000000000000000000000') { - const wei = await provider.getBalance(wallet); - balances[t.symbol] = formatUnits(wei, 18); - continue; - } - try { - const c = new Contract(t.address, ERC20_ABI, provider); - const raw = await c.balanceOf(wallet); - balances[t.symbol] = formatUnits(raw, t.decimals); - } catch { - balances[t.symbol] = '0'; - } - } - return { wallet, balances }; - } - - - export function resolveTokenLine(token: M2TokenCapabilities): string { - return token.omnlLine; - } - - diff --git a/services/dbis-exchange/src/config.ts b/services/dbis-exchange/src/config.ts index 4293d45..45cc695 100644 --- a/services/dbis-exchange/src/config.ts +++ b/services/dbis-exchange/src/config.ts @@ -1,149 +1,77 @@ import fs from 'fs'; - import path from 'path'; - import { - mergeExchangeTokensWithM2Registry, - type M2TokenCapabilities, - type M2TokenRegistryFile, - } from '@dbis/settlement-core'; - - export type ExchangeConfig = { - version: string; - chainId: number; - brandName: string; - officeId: number; - settlementOfficeExternalId: string; - + chainRegistry?: string; + maxSupportedChains?: number; routers: Record; - factory: Record; - tokens: { - symbol: string; - name: string; - address: string; - decimals: number; - native?: boolean; - omnlLine?: string; - moneyLayer?: string; - swappable?: boolean; - convertible?: boolean; - transferableInternal?: boolean; - transferableExternal?: boolean; - }[]; - defaultSlippageBps: number; - production: { - requireApiKey: boolean; - monitorSwaps: boolean; - postSwapSettlementAudit: boolean; - + onlineBankMode?: boolean; }; - }; - - let cached: ExchangeConfig | null = null; - let cachedM2: M2TokenRegistryFile | null = null; - - export function loadM2TokenRegistry(): M2TokenRegistryFile { - if (cachedM2) return cachedM2; - const p = - process.env.OMNL_M2_TOKEN_REGISTRY || - path.resolve(__dirname, '../../../config/omnl-m2-token-registry.v1.json'); - cachedM2 = JSON.parse(fs.readFileSync(p, 'utf8')) as M2TokenRegistryFile; - return cachedM2; - } - - export function loadExchangeTokens(): M2TokenCapabilities[] { - const cfg = loadExchangeConfig(); - return mergeExchangeTokensWithM2Registry(cfg.tokens, loadM2TokenRegistry()); - } - - export function loadExchangeConfig(): ExchangeConfig { - if (cached) return cached; - const p = - process.env.DBIS_EXCHANGE_CONFIG || - path.resolve(__dirname, '../../../config/dbis-exchange.v1.json'); - cached = JSON.parse(fs.readFileSync(p, 'utf8')) as ExchangeConfig; - return cached; - } - - export function exchangePort(): number { - return parseInt(process.env.DBIS_EXCHANGE_PORT || '3012', 10); - } - - export function tokenAggUrl(): string { - return (process.env.TOKEN_AGGREGATION_URL || 'http://localhost:3000').replace(/\/$/, ''); - } - - export function settlementUrl(): string { - return (process.env.SETTLEMENT_MIDDLEWARE_URL || 'http://localhost:3011').replace(/\/$/, ''); - } - - diff --git a/services/settlement-middleware/src/config.ts b/services/settlement-middleware/src/config.ts index c125f4d..47be1db 100644 --- a/services/settlement-middleware/src/config.ts +++ b/services/settlement-middleware/src/config.ts @@ -41,6 +41,11 @@ export type MiddlewareConfig = { swift: { enabled: boolean; listenerUrl: string }; hybx: { enabled: boolean; sidecarUrl: string }; chain138: { enabled: boolean; rpcEnv: string; defaultLineId: string }; + multiChain?: { + enabled: boolean; + registryPath: string; + primaryChainId: number; + }; }; moneySupply: { glM0: string; @@ -52,6 +57,7 @@ export type MiddlewareConfig = { requireApiKey: boolean; allowHybxProduction: boolean; allowChainMintExecute: boolean; + onlineBankMode?: boolean; }; };