feat: bridges, PMM, flash workflow, token-aggregation, and deployment docs
- CCIP/trustless bridge contracts, GRU tokens, DEX/PMM tests, reserve vault. - Token-aggregation service routes, planner, chain config, relay env templates. - Config snapshots and multi-chain deployment markdown updates. - gitignore services/btc-intake/dist/ (tsc output); do not track dist. Run forge build && forge test before deploy (large solc graph). Made-with: Cursor
This commit is contained in:
@@ -14,6 +14,7 @@ import heatmapRoutes from './routes/heatmap';
|
||||
import arbitrageRoutes from './routes/arbitrage';
|
||||
import aggregatorRouteMatrixRoutes from './routes/aggregator-routes';
|
||||
import partnerPayloadRoutes from './routes/partner-payloads';
|
||||
import plannerV2Routes from './routes/planner-v2';
|
||||
import { MultiChainIndexer } from '../indexer/chain-indexer';
|
||||
import { getDatabasePool } from '../database/client';
|
||||
import winston from 'winston';
|
||||
@@ -39,19 +40,42 @@ const logger = winston.createLogger({
|
||||
export class ApiServer {
|
||||
private app: Express;
|
||||
private port: number;
|
||||
private indexer: MultiChainIndexer;
|
||||
private indexerEnabled: boolean;
|
||||
private indexer: MultiChainIndexer | null;
|
||||
|
||||
private resolveTrustProxySetting(): boolean | number | string {
|
||||
const raw = (process.env.EXPRESS_TRUST_PROXY ?? process.env.TRUST_PROXY ?? '1').trim();
|
||||
const normalized = raw.toLowerCase();
|
||||
|
||||
if (normalized === 'true') return true;
|
||||
if (normalized === 'false') return false;
|
||||
if (/^\d+$/.test(raw)) return parseInt(raw, 10);
|
||||
return raw;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.app = express();
|
||||
this.port = parseInt(process.env.PORT || '3000', 10);
|
||||
this.indexer = new MultiChainIndexer();
|
||||
this.indexerEnabled = this.resolveFeatureFlag('ENABLE_INDEXER', true);
|
||||
this.indexer = this.indexerEnabled ? new MultiChainIndexer() : null;
|
||||
|
||||
this.setupMiddleware();
|
||||
this.setupRoutes();
|
||||
this.setupErrorHandling();
|
||||
}
|
||||
|
||||
private resolveFeatureFlag(name: string, fallback: boolean): boolean {
|
||||
const raw = (process.env[name] || '').trim().toLowerCase();
|
||||
if (!raw) return fallback;
|
||||
if (['1', 'true', 'yes', 'on'].includes(raw)) return true;
|
||||
if (['0', 'false', 'no', 'off'].includes(raw)) return false;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
private setupMiddleware(): void {
|
||||
const trustProxy = this.resolveTrustProxySetting();
|
||||
this.app.set('trust proxy', trustProxy);
|
||||
|
||||
// CORS
|
||||
this.app.use(cors());
|
||||
|
||||
@@ -69,6 +93,8 @@ export class ApiServer {
|
||||
this.app.use((req: Request, res: Response, next: NextFunction) => {
|
||||
logger.info(`${req.method} ${req.path}`, {
|
||||
ip: req.ip,
|
||||
forwardedFor: req.get('x-forwarded-for'),
|
||||
trustProxy,
|
||||
userAgent: req.get('user-agent'),
|
||||
});
|
||||
next();
|
||||
@@ -88,7 +114,7 @@ export class ApiServer {
|
||||
timestamp: new Date().toISOString(),
|
||||
services: {
|
||||
database: 'connected',
|
||||
indexer: 'running',
|
||||
indexer: this.indexerEnabled ? 'running' : 'disabled',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -112,6 +138,7 @@ export class ApiServer {
|
||||
this.app.use('/api/v1', arbitrageRoutes);
|
||||
this.app.use('/api/v1', aggregatorRouteMatrixRoutes);
|
||||
this.app.use('/api/v1', partnerPayloadRoutes);
|
||||
this.app.use('/api/v2', plannerV2Routes);
|
||||
|
||||
// Admin routes (stricter rate limit)
|
||||
this.app.use('/api/v1/admin', strictRateLimiter, adminRoutes);
|
||||
@@ -124,6 +151,7 @@ export class ApiServer {
|
||||
endpoints: {
|
||||
health: '/health',
|
||||
api: '/api/v1',
|
||||
apiV2: '/api/v2',
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -148,11 +176,12 @@ export class ApiServer {
|
||||
|
||||
async start(): Promise<void> {
|
||||
try {
|
||||
// Initialize indexer
|
||||
await this.indexer.initialize();
|
||||
|
||||
// Start indexing
|
||||
await this.indexer.startAll();
|
||||
if (this.indexer) {
|
||||
await this.indexer.initialize();
|
||||
await this.indexer.startAll();
|
||||
} else {
|
||||
logger.info('Token aggregation indexer disabled by ENABLE_INDEXER flag');
|
||||
}
|
||||
|
||||
// Start server
|
||||
this.app.listen(this.port, () => {
|
||||
@@ -167,7 +196,7 @@ export class ApiServer {
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
this.indexer.stopAll();
|
||||
this.indexer?.stopAll();
|
||||
logger.info('Server stopped');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user