@@ -46,8 +46,9 @@ portfoliosRouter.get('/portfolios', async (req: Request, res: Response) => {
4646 const search = req . query . search as string || ''
4747 const limit = parseInt ( req . query . limit as string ) || 20
4848 const offset = parseInt ( req . query . offset as string ) || 0
49+ const includeArchived = req . query . include_archived === 'true'
4950
50- const portfolios = await portfolioStorage . searchPortfolios ( search , limit , offset )
51+ const portfolios = await portfolioStorage . searchPortfolios ( search , limit , offset , includeArchived )
5152 return ok ( res , { portfolios, limit, offset } )
5253 } catch ( error ) {
5354 logger . error ( '[ERROR] Search portfolios failed' , { error : getErrorObject ( error ) } )
@@ -343,6 +344,66 @@ portfoliosRouter.get('/portfolio/:id/share', async (req: Request, res: Response)
343344 }
344345} )
345346
347+ // ================================
348+ // ARCHIVE / RESTORE ROUTES
349+ // ================================
350+
351+ portfoliosRouter . delete ( '/portfolio/:id' , ...protectedWriteLimiter , async ( req : Request , res : Response ) => {
352+ try {
353+ const portfolioId = req . params . id
354+ if ( ! portfolioId ) return fail ( res , 400 , 'VALIDATION_ERROR' , 'Portfolio ID required' )
355+
356+ const portfolio = await portfolioStorage . getPortfolio ( portfolioId )
357+ if ( ! portfolio ) return fail ( res , 404 , 'NOT_FOUND' , 'Portfolio not found' )
358+
359+ const authConfig = getAuthConfig ( )
360+ if ( authConfig . enabled && ( ! req . user || portfolio . userAddress !== req . user . address ) ) {
361+ return fail ( res , 403 , 'FORBIDDEN' , 'You can only archive your own portfolio' )
362+ }
363+
364+ if ( portfolio . archivedAt ) {
365+ return fail ( res , 400 , 'ALREADY_ARCHIVED' , 'Portfolio is already archived' )
366+ }
367+
368+ const archived = await portfolioStorage . archivePortfolio ( portfolioId )
369+ if ( ! archived ) return fail ( res , 500 , 'INTERNAL_ERROR' , 'Failed to archive portfolio' )
370+
371+ logger . info ( '[ARCHIVE] Portfolio archived' , { portfolioId } )
372+ return ok ( res , { portfolioId, status : 'archived' , archivedAt : new Date ( ) . toISOString ( ) } )
373+ } catch ( error ) {
374+ logger . error ( '[ERROR] Archive portfolio failed' , { error : getErrorObject ( error ) } )
375+ return fail ( res , 500 , 'INTERNAL_ERROR' , getErrorMessage ( error ) )
376+ }
377+ } )
378+
379+ portfoliosRouter . post ( '/portfolio/:id/restore' , ...protectedWriteLimiter , async ( req : Request , res : Response ) => {
380+ try {
381+ const portfolioId = req . params . id
382+ if ( ! portfolioId ) return fail ( res , 400 , 'VALIDATION_ERROR' , 'Portfolio ID required' )
383+
384+ const portfolio = await portfolioStorage . getPortfolio ( portfolioId )
385+ if ( ! portfolio ) return fail ( res , 404 , 'NOT_FOUND' , 'Portfolio not found' )
386+
387+ const authConfig = getAuthConfig ( )
388+ if ( authConfig . enabled && ( ! req . user || portfolio . userAddress !== req . user . address ) ) {
389+ return fail ( res , 403 , 'FORBIDDEN' , 'You can only restore your own portfolio' )
390+ }
391+
392+ if ( ! portfolio . archivedAt ) {
393+ return fail ( res , 400 , 'NOT_ARCHIVED' , 'Portfolio is not archived' )
394+ }
395+
396+ const restored = await portfolioStorage . restorePortfolio ( portfolioId )
397+ if ( ! restored ) return fail ( res , 500 , 'INTERNAL_ERROR' , 'Failed to restore portfolio' )
398+
399+ logger . info ( '[RESTORE] Portfolio restored' , { portfolioId } )
400+ return ok ( res , { portfolioId, status : 'restored' } )
401+ } catch ( error ) {
402+ logger . error ( '[ERROR] Restore portfolio failed' , { error : getErrorObject ( error ) } )
403+ return fail ( res , 500 , 'INTERNAL_ERROR' , getErrorMessage ( error ) )
404+ }
405+ } )
406+
346407// ================================
347408// DRAFT PORTFOLIO ROUTES
348409// ================================
@@ -559,7 +620,8 @@ portfoliosRouter.get('/user/:address/portfolios', async (req: Request, res: Resp
559620 }
560621 }
561622
562- const list = await portfolioStorage . getUserPortfolios ( address )
623+ const includeArchived = req . query . include_archived === 'true'
624+ const list = await portfolioStorage . getUserPortfolios ( address , includeArchived )
563625
564626 return ok ( res , { portfolios : list } )
565627 } catch ( error ) {
0 commit comments