Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion backend/src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ export const registerUser = async (req: Request, res: Response, next: NextFuncti
*/
export const getUser = async (req: Request, res: Response, next: NextFunction) => {
try {
const publicKey = req.params.publicKey as string;
const { publicKey } = req.params;
if (typeof publicKey !== 'string') {
return res.status(400).json({ error: 'Invalid publicKey parameter' });
}
if (!/^G[A-Z2-7]{55}$/.test(publicKey)) {
return res.status(400).json({ error: 'Invalid Stellar public key format' });
}

const user = await prisma.user.findUnique({
where: { publicKey },
Expand Down
25 changes: 22 additions & 3 deletions backend/tests/user.controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,26 @@ describe('User Controller', () => {
});

describe('getUser', () => {
it('should return 400 if publicKey is missing', async () => {
req.params = {};

await getUser(req as Request, res as Response, next);

expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith({ error: 'Invalid publicKey parameter' });
});

it('should return 400 if publicKey is malformed', async () => {
req.params = { publicKey: 'invalid-key' };

await getUser(req as Request, res as Response, next);

expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith({ error: 'Invalid Stellar public key format' });
});

it('should return 404 if user not found', async () => {
req.params = { publicKey: 'GNOTFOUND' };
req.params = { publicKey: 'GD2XP6FNWL6IWULVMPNA2RV2T7GLCJHK3RH75GBCY7TSVIWDITJN4FXJ' };
(prisma.user.findUnique as any).mockResolvedValue(null);

await getUser(req as Request, res as Response, next);
Expand All @@ -85,8 +103,9 @@ describe('User Controller', () => {
});

it('should return user if found', async () => {
req.params = { publicKey: 'GUSER1' };
const mockUser = { publicKey: 'GUSER1', sentStreams: [], receivedStreams: [] };
const publicKey = 'GD2XP6FNWL6IWULVMPNA2RV2T7GLCJHK3RH75GBCY7TSVIWDITJN4FXJ';
req.params = { publicKey };
const mockUser = { publicKey, sentStreams: [], receivedStreams: [] };
(prisma.user.findUnique as any).mockResolvedValue(mockUser);

await getUser(req as Request, res as Response, next);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/FAQ.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const faqs = [
},
{
q: 'Which chains do you support?',
a: 'We are currently live on Ethereum Mainnet, Arbitrum, and Optimism. Polygon and Base support is coming in Q3 2026.',
a: 'FlowFi is built on Stellar using Soroban smart contracts. We currently run on Stellar Testnet, with mainnet support planned as the protocol matures.',
},
{
q: 'Can recipients withdraw at any time?',
Expand Down
18 changes: 9 additions & 9 deletions frontend/src/components/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

import Link from 'next/link';
import { Button } from './ui/Button';
import { MobileMockup } from './MobileMockup';

Expand Down Expand Up @@ -26,15 +27,14 @@ export const Hero = () => {
</p>

<div className="mt-12 flex animate-slide-up flex-col gap-5 sm:flex-row [animation-delay:0.2s] w-full justify-center lg:justify-start">
<Button variant="primary" size="lg" glow className="min-w-[200px]">
Start Streaming
<svg className="ml-2 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
</svg>
</Button>
<Button variant="outline" size="lg" className="min-w-[200px]">
Governance App
</Button>
<Link href="/dashboard">
<Button variant="primary" size="lg" glow className="min-w-[200px]">
Start Streaming
<svg className="ml-2 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
</svg>
</Button>
</Link>
</div>

<div className="mt-20 flex items-center gap-4 animate-fade-in [animation-delay:0.4s]">
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/Stats.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@


const stats = [
{ label: 'Total Value Locked', value: '$240M+', gradient: 'text-gradient' },
{ label: 'Active Streams', value: '85k+', gradient: 'text-white' },
{ label: 'Network Savings', value: '$4.2M', gradient: 'text-gradient-secondary' },
{ label: 'Network', value: 'Stellar Testnet', gradient: 'text-gradient' },
{ label: 'Status', value: 'Early Access', gradient: 'text-white' },
{ label: 'Settlement', value: 'Real-time', gradient: 'text-gradient-secondary' },

];

Expand Down
Loading