diff --git a/backend/src/controllers/stream.controller.ts b/backend/src/controllers/stream.controller.ts index bc1c114c..2ee5d5f1 100644 --- a/backend/src/controllers/stream.controller.ts +++ b/backend/src/controllers/stream.controller.ts @@ -258,7 +258,7 @@ export const listStreams = async (req: Request, res: Response) => { typeof limit === 'string' ? (Number.parseInt(limit, 10) || DEFAULT_STREAM_PAGE_SIZE) : DEFAULT_STREAM_PAGE_SIZE, MAX_STREAM_PAGE_SIZE ); - const parsedOffset = typeof offset === 'string' ? (Number.parseInt(offset, 10) || 0) : 0; + const parsedOffset = typeof offset === 'string' ? Math.max(0, Number.parseInt(offset, 10) || 0) : 0; // Validate sort field const validSortFields = ['createdAt', 'startTime', 'lastUpdateTime', 'depositedAmount', 'endTime']; @@ -375,7 +375,7 @@ export const getStreamEvents = async (req: Request, res: Response) => { let offset = 0; if (rawOffset && typeof rawOffset === 'string') { - offset = Number.parseInt(rawOffset, 10) || 0; + offset = Math.max(0, Number.parseInt(rawOffset, 10) || 0); } else if (rawPage && typeof rawPage === 'string' && !cursor) { const page = Number.parseInt(rawPage, 10) || 1; offset = Math.max(0, (page - 1) * limit); @@ -655,7 +655,7 @@ export const topUpStreamHandler = async (req: Request, res: Response) => { return res.status(200).json({ streamId, txHash, depositedAmount: newDeposited }); } catch (error: any) { logger.error(`[topUp] stream=${streamId} error:`, error); - return res.status(500).json({ error: error.message ?? 'Internal server error' }); + return res.status(400).json({ error: 'Failed to top up stream on chain', message: error.message ?? 'Unknown error' }); } }; diff --git a/backend/src/controllers/user.controller.ts b/backend/src/controllers/user.controller.ts index 95f6b3d3..ae31d17c 100644 --- a/backend/src/controllers/user.controller.ts +++ b/backend/src/controllers/user.controller.ts @@ -85,7 +85,7 @@ export const getUserEvents = async (req: Request, res: Response, next: NextFunct rawLimit && typeof rawLimit === 'string' ? (Number.parseInt(rawLimit, 10) || DEFAULT_EVENTS_PAGE_SIZE) : DEFAULT_EVENTS_PAGE_SIZE, MAX_EVENTS_PAGE_SIZE ); - const offset = rawOffset && typeof rawOffset === 'string' ? (Number.parseInt(rawOffset, 10) || 0) : 0; + const offset = rawOffset && typeof rawOffset === 'string' ? Math.max(0, Number.parseInt(rawOffset, 10) || 0) : 0; const whereClause = { stream: { diff --git a/backend/src/routes/v1/streams/index.ts b/backend/src/routes/v1/streams/index.ts index 77a4d834..abcdf5ab 100644 --- a/backend/src/routes/v1/streams/index.ts +++ b/backend/src/routes/v1/streams/index.ts @@ -1,16 +1,8 @@ import { Router } from 'express'; -import { requireAuth } from '../../../middleware/auth.js'; -import { withdrawHandler } from './withdraw.js'; import oldStreamRoutes from '../stream.routes.js'; - const router = Router(); // Mount the old routes first router.use('/', oldStreamRoutes); -/** - * Override/Add POST /api/v1/streams/:streamId/withdraw - */ -router.post('/:streamId/withdraw', requireAuth, withdrawHandler as any); - export default router; diff --git a/frontend/src/components/dashboard/dashboard-view.tsx b/frontend/src/components/dashboard/dashboard-view.tsx index 5dac949f..82994812 100644 --- a/frontend/src/components/dashboard/dashboard-view.tsx +++ b/frontend/src/components/dashboard/dashboard-view.tsx @@ -108,6 +108,8 @@ const SIDEBAR_ITEMS: SidebarItem[] = [ /** Shimmer card used as a placeholder while data loads */ function SkeletonCard({ className = "" }: { className?: string }) { return ( +