diff --git a/backend/src/controllers/stream.controller.ts b/backend/src/controllers/stream.controller.ts index 9999752a..968def20 100644 --- a/backend/src/controllers/stream.controller.ts +++ b/backend/src/controllers/stream.controller.ts @@ -286,8 +286,7 @@ export const listStreams = async (req: Request, res: Response) => { : 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 = [ @@ -425,9 +424,9 @@ export const getStreamEvents = async (req: Request, res: Response) => { ); let offset = 0; - if (rawOffset && typeof rawOffset === "string") { - offset = Number.parseInt(rawOffset, 10) || 0; - } else if (rawPage && typeof rawPage === "string" && !cursor) { + if (rawOffset && typeof rawOffset === 'string') { + 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); } @@ -749,9 +748,7 @@ export const topUpStreamHandler = async (req: Request, res: Response) => { .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 e0a921e3..7ba3433a 100644 --- a/frontend/src/components/dashboard/dashboard-view.tsx +++ b/frontend/src/components/dashboard/dashboard-view.tsx @@ -107,6 +107,8 @@ const SIDEBAR_ITEMS: SidebarItem[] = [ /** Shimmer card used as a placeholder while data loads */ function SkeletonCard({ className = "" }: { className?: string }) { return ( +