Problem
In backend/src/api/validation.ts, createPortfolioSchema validates userAddress only as z.string().min(1). The codebase already has a working stellarAddressSchema (using the Stellar SDK's StrKey.isValidEd25519PublicKey) in the same file, but createPortfolioSchema does not use it.
This means any caller can create portfolios under arbitrary identifiers, which pollutes the database with unlinked records and could cause collisions if two different users happen to use the same string.
Proposed Fix
1. Use existing stellarAddressSchema
Change the userAddress field in createPortfolioSchema from z.string().min(1) to stellarAddressSchema.
2. Handle demo mode
The frontend falls back to "demo-user" when no wallet is connected. Options:
- Add a separate
demoAddress field for demo mode and validate userAddress only when in non-demo mode
- Or require wallet connection before portfolio creation
3. Add validation tests
Test that invalid addresses are rejected and valid G... addresses are accepted.
Files to modify
backend/src/api/validation.ts — update createPortfolioSchema
backend/src/api/routes.ts — update POST /portfolio handler if needed
frontend/src/components/PortfolioSetup.tsx — send actual publicKey instead of "demo-user"
backend/src/api/__tests__/routes.test.ts — add validation tests
Acceptance Criteria
Affected Area
Backend and Frontend
Problem
In
backend/src/api/validation.ts,createPortfolioSchemavalidatesuserAddressonly asz.string().min(1). The codebase already has a workingstellarAddressSchema(using the Stellar SDK'sStrKey.isValidEd25519PublicKey) in the same file, butcreatePortfolioSchemadoes not use it.This means any caller can create portfolios under arbitrary identifiers, which pollutes the database with unlinked records and could cause collisions if two different users happen to use the same string.
Proposed Fix
1. Use existing
stellarAddressSchemaChange the
userAddressfield increatePortfolioSchemafromz.string().min(1)tostellarAddressSchema.2. Handle demo mode
The frontend falls back to
"demo-user"when no wallet is connected. Options:demoAddressfield for demo mode and validateuserAddressonly when in non-demo mode3. Add validation tests
Test that invalid addresses are rejected and valid G... addresses are accepted.
Files to modify
backend/src/api/validation.ts— updatecreatePortfolioSchemabackend/src/api/routes.ts— updatePOST /portfoliohandler if neededfrontend/src/components/PortfolioSetup.tsx— send actualpublicKeyinstead of"demo-user"backend/src/api/__tests__/routes.test.ts— add validation testsAcceptance Criteria
userAddressfield usesstellarAddressSchemainstead ofz.string().min(1)"demo-user"fallbackPOST /portfoliowithuserAddress: "not-a-valid-key"returns 400POST /portfoliowith valid G... address returns 201userAddressvalidationAffected Area
Backend and Frontend