@@ -29,190 +29,6 @@ const parseHistorySource = (value: unknown): 'all' | 'offchain' | 'simulated' |
2929 return 'all'
3030}
3131
32- // ================================
33- // HEALTH CHECK ROUTES
34- // ================================
35-
36- // Health check with enhanced status
37- router . get ( '/health' , ( req , res ) => {
38- res . json ( {
39- status : 'ok' ,
40- timestamp : new Date ( ) . toISOString ( ) ,
41- mode : deploymentMode ,
42- features : {
43- contract_deployed : true ,
44- real_price_feeds : true ,
45- automatic_monitoring : true ,
46- circuit_breakers : true ,
47- demo_portfolios : featureFlags . demoMode ,
48- risk_management : true ,
49- rebalance_history : true ,
50- auto_rebalancer : autoRebalancer ? autoRebalancer . getStatus ( ) . isRunning : false ,
51- flags : publicFeatureFlags
52- }
53- } )
54- } )
55-
56- // ================================
57- // PORTFOLIO MANAGEMENT ROUTES
58- // ================================
59-
60- // Create portfolio with enhanced validation
61- router . post ( '/portfolio' , writeRateLimiter , async ( req , res ) => {
62- try {
63- const { userAddress, allocations, threshold } = req . body
64-
65- if ( ! userAddress || ! allocations || threshold === undefined ) {
66- return res . status ( 400 ) . json ( { error : 'Missing required fields: userAddress, allocations, threshold' } )
67- }
68-
69- // Enhanced validation
70- const total = Object . values ( allocations as Record < string , number > ) . reduce ( ( sum , val ) => sum + val , 0 )
71- if ( Math . abs ( total - 100 ) > 0.01 ) {
72- return res . status ( 400 ) . json ( { error : 'Allocations must sum to 100%' } )
73- }
74-
75- // Validate threshold range
76- if ( threshold < 1 || threshold > 50 ) {
77- return res . status ( 400 ) . json ( { error : 'Threshold must be between 1% and 50%' } )
78- }
79-
80- // Validate asset allocations
81- for ( const [ asset , percentage ] of Object . entries ( allocations as Record < string , number > ) ) {
82- if ( percentage < 0 || percentage > 100 ) {
83- return res . status ( 400 ) . json ( { error : `Invalid percentage for ${ asset } : must be between 0-100%` } )
84- }
85- }
86-
87- const portfolioId = await stellarService . createPortfolio ( userAddress , allocations , threshold )
88-
89- const reflector = new ReflectorService ( )
90- const prices = await reflector . getCurrentPrices ( )
91- await analyticsService . captureSnapshot ( portfolioId , prices )
92-
93- await rebalanceHistoryService . recordRebalanceEvent ( {
94- portfolioId,
95- trigger : 'Portfolio Created' ,
96- trades : 0 ,
97- gasUsed : '0 XLM' ,
98- status : 'completed' ,
99- isAutomatic : false
100- } )
101-
102- logger . info ( 'Portfolio created successfully' , {
103- portfolioId,
104- userAddress,
105- allocations,
106- threshold,
107- mode : deploymentMode
108- } )
109-
110- res . json ( {
111- portfolioId,
112- status : 'created' ,
113- mode : deploymentMode ,
114- message : featureFlags . demoMode
115- ? 'Portfolio created with simulated $10,000 balance'
116- : 'Portfolio created with real on-chain balances'
117- } )
118- } catch ( error ) {
119- logger . error ( 'Failed to create portfolio' , { error : getErrorObject ( error ) } )
120- res . status ( 500 ) . json ( {
121- error : getErrorMessage ( error )
122- } )
123- }
124- } )
125-
126- // Get portfolio with real-time data
127- router . get ( '/portfolio/:id' , async ( req , res ) => {
128- try {
129- const portfolioId = req . params . id
130-
131- if ( ! portfolioId ) {
132- return res . status ( 400 ) . json ( { error : 'Portfolio ID required' } )
133- }
134-
135- const portfolio = await stellarService . getPortfolio ( portfolioId )
136- const prices = await reflectorService . getCurrentPrices ( )
137-
138- await analyticsService . captureSnapshot ( portfolioId , prices )
139-
140- let riskMetrics = null
141- try {
142- const allocationsRecord = getPortfolioAllocationsAsRecord ( portfolio )
143- riskMetrics = riskManagementService . analyzePortfolioRisk ( allocationsRecord , prices )
144- } catch ( riskError ) {
145- console . warn ( 'Risk analysis failed:' , riskError )
146- }
147-
148- res . json ( {
149- portfolio,
150- prices,
151- riskMetrics,
152- mode : deploymentMode ,
153- lastUpdated : new Date ( ) . toISOString ( )
154- } )
155- } catch ( error ) {
156- logger . error ( 'Failed to fetch portfolio' , { error : getErrorObject ( error ) , portfolioId : req . params . id } )
157- res . status ( 500 ) . json ( {
158- error : getErrorMessage ( error )
159- } )
160- }
161- } )
162-
163- // Get user portfolios
164- router . get ( '/user/:address/portfolios' , async ( req , res ) => {
165- try {
166- const userAddress = req . params . address
167- const portfolios = await portfolioStorage . getUserPortfolios ( userAddress )
168-
169- res . json ( portfolios )
170- } catch ( error ) {
171- logger . error ( 'Failed to fetch user portfolios' , { error : getErrorObject ( error ) , userAddress : req . params . address } )
172- res . status ( 500 ) . json ( { error : 'Failed to fetch portfolios' } )
173- }
174- } )
175-
176- // ================================
177- // REBALANCING ROUTES
178- // ================================
179-
180- // Enhanced rebalance with comprehensive safety checks
181- router . post ( '/portfolio/:id/rebalance' , writeRateLimiter , async ( req , res ) => {
182- try {
183- const portfolioId = req . params . id
184-
185- if ( ! portfolioId ) {
186- return res . status ( 400 ) . json ( { error : 'Portfolio ID required' } )
187- }
188-
189- // Get current prices for safety checks
190- const prices = await reflectorService . getCurrentPrices ( )
191-
192- // Check circuit breakers before proceeding
193- const marketCheck = await CircuitBreakers . checkMarketConditions ( prices )
194- if ( ! marketCheck . safe ) {
195- return res . status ( 400 ) . json ( {
196- error : `Rebalance blocked by safety systems: ${ marketCheck . reason } ` ,
197- reason : 'circuit_breaker' ,
198- canRetry : true
199- } )
200- }
201-
202- // Enhanced risk management check
203- const portfolio = await stellarService . getPortfolio ( portfolioId )
204- const riskCheck = riskManagementService . shouldAllowRebalance ( portfolio , prices )
205-
206- if ( ! riskCheck . allowed ) {
207- return res . status ( 400 ) . json ( {
208- error : `Rebalance blocked by risk management: ${ riskCheck . reason } ` ,
209- reason : 'risk_management' ,
210- reasonCode : riskCheck . reasonCode ,
211- alerts : riskCheck . alerts ,
212- riskMetrics : riskCheck . riskMetrics ,
213- canRetry : true
214- } )
215- }
21632
21733router . get ( '/rebalance/history' , async ( req , res ) => {
21834 try {
@@ -341,14 +157,7 @@ router.get('/risk/metrics/:portfolioId', async (req, res) => {
341157 concentrationRisk : 0 ,
342158 liquidityRisk : 0 ,
343159 correlationRisk : 0 ,
344- overallRiskLevel : 'low' as const ,
345- ewmaVolatility : 0 ,
346- var95 : 0 ,
347- cvar95 : 0 ,
348- maxDrawdown : 0 ,
349- drawdownBand : 'normal' as const ,
350- correlations : { } ,
351- sampleSize : 0
160+
352161 }
353162 } )
354163 }
0 commit comments