Skip to content

S4: centralize XDR flow, validate frontend env, centralize auth token storage, add pool DTO validation#813

Merged
Akshola00 merged 2 commits into
Web3Novalabs:mainfrom
OtowoSamuel:feat/s4-xdr-env-auth-dto-validation
Jun 30, 2026
Merged

S4: centralize XDR flow, validate frontend env, centralize auth token storage, add pool DTO validation#813
Akshola00 merged 2 commits into
Web3Novalabs:mainfrom
OtowoSamuel:feat/s4-xdr-env-auth-dto-validation

Conversation

@OtowoSamuel

Copy link
Copy Markdown
Contributor

Summary

This PR implements four S4 reliability improvements across frontend and server:

  • Add shared XDR transaction hook for sign-and-submit flow state handling
  • Add required frontend public env validation at startup
  • Add centralized typed auth token storage helpers
  • Add class-validator DTOs for pool create and donate endpoints

Changes

Frontend

  • Added useXdrTransaction hook in nevo_frontend/hooks/useXdrTransaction.ts
    • Exposes submit, status, txHash, error
    • Handles: fetch unsigned XDR -> Freighter sign -> submit signed XDR
  • Added nevo_frontend/lib/env.ts
    • Validates required vars: NEXT_PUBLIC_API_BASE_URL, NEXT_PUBLIC_STELLAR_NETWORK
    • Throws clear startup errors if missing
  • Wired env validation into nevo_frontend/lib/api-client.ts at module load time
  • Added nevo_frontend/lib/auth-storage.ts
    • getToken, setToken, clearToken
    • Uses a single key constant: nevo_jwt
  • Updated token consumers to use centralized helpers:
    • nevo_frontend/lib/api-client.ts
    • nevo_frontend/src/store/walletStore.ts
    • nevo_frontend/lib/jwt-storage.ts now delegates to auth-storage
  • Added required vars to nevo_frontend/.env.example

Server

  • Updated/create pool DTO validation rules in nevo_server/src/pools/dto/create-pool.dto.ts
  • Added donate DTO in nevo_server/src/pools/dto/donate-pool.dto.ts
  • Exported donate DTO from nevo_server/src/pools/dto/index.ts
  • Updated nevo_server/src/pools/pools.controller.ts to use DTO body types on:
    • POST /pools
    • POST /pools/:id/donate
  • Updated service type import in nevo_server/src/pools/pools.service.ts
  • Global ValidationPipe was already enabled in nevo_server/src/main.ts with whitelist settings

Verification

  • Frontend build passed with required env vars set
  • Server build passed
  • Repository-wide server lint currently has pre-existing unrelated failures; changed pool validation files lint clean in targeted check

Closes #801
Closes #798
Closes #799
Closes #804

Copilot AI review requested due to automatic review settings June 29, 2026 15:27
@drips-wave

drips-wave Bot commented Jun 29, 2026

Copy link
Copy Markdown

@OtowoSamuel Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets S4 reliability improvements across the Nevo frontend (Next.js) and server (NestJS) by centralizing common transaction/auth flows on the frontend and introducing DTO-based runtime validation on the server for pool write endpoints.

Changes:

  • Frontend: added a shared useXdrTransaction hook for the unsigned-XDR → sign → submit flow, plus centralized JWT storage helpers.
  • Frontend: added startup env validation and wired it into the API client at module load time, and updated .env.example.
  • Server: introduced class-validator DTOs for pool creation and donation, and updated controller/service typing accordingly.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
nevo_server/src/pools/pools.service.ts Imports CreatePoolDto from DTO module instead of controller typing.
nevo_server/src/pools/pools.controller.ts Switched create/donate request bodies to DTO classes; removed ad-hoc donate validation; changed donations route handler.
nevo_server/src/pools/dto/index.ts Re-exported the new donate DTO.
nevo_server/src/pools/dto/donate-pool.dto.ts Added runtime validation DTO for donate requests.
nevo_server/src/pools/dto/create-pool.dto.ts Updated pool creation DTO validation rules and field types.
nevo_frontend/src/store/walletStore.ts Centralized token persistence via auth-storage helpers.
nevo_frontend/lib/stellar.ts Added Freighter signing wrapper and introduced a network passphrase constant used for signing.
nevo_frontend/lib/jwt-storage.ts Delegated legacy JWT helpers to the new centralized token storage.
nevo_frontend/lib/env.ts Added required public env validation + strongly-typed env export.
nevo_frontend/lib/auth-storage.ts Added centralized typed JWT storage helpers (getToken/setToken/clearToken).
nevo_frontend/lib/api-client.ts Validates env at module load; switches auth header sourcing to centralized token helper; base URL now comes from validated env.
nevo_frontend/hooks/useXdrTransaction.ts New hook to unify sign-and-submit flow state handling.
nevo_frontend/.env.example Added required frontend runtime env entries.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 64 to 67
@Get(':id/donations')
getDonations(
@Param('id', ParseIntPipe) id: number,
@Query('page') page = '1',
@Query('limit') limit = '20',
) {
getDonations(@Param('id', ParseIntPipe) id: number) {
return this.donationsService.findByPool(String(id));
}
Comment on lines +1 to +7
import { IsNotEmpty, IsNumberString } from 'class-validator';

export class DonatePoolDto {
@IsNumberString()
@IsNotEmpty()
amount: string;
}
Comment on lines 27 to 30

@IsString()
category: string;
@IsNumberString()
goal: string;

Comment on lines +16 to +20
if (typeof payload === 'string') {
return payload;
}

return payload.unsignedXdr;
Comment on lines +51 to +55
const hash = extractTxHash(submitResult);

setTxHash(hash || null);
setStatus('success');
return hash;
Comment on lines +10 to +12
# Required frontend runtime config
NEXT_PUBLIC_API_BASE_URL=http://localhost:3000
NEXT_PUBLIC_STELLAR_NETWORK=testnet
Comment on lines 16 to 19
const HORIZON = 'https://horizon.stellar.org';
const NETWORK_PASSPHRASE =
process.env.NEXT_PUBLIC_NETWORK_PASSPHRASE ?? Networks.TESTNET;
const ZERO_BALANCES: AccountBalances = { xlm: '0', usdc: '0' };
Comment thread nevo_frontend/lib/env.ts
Comment on lines +3 to +27
'NEXT_PUBLIC_STELLAR_NETWORK',
] as const;

type RequiredPublicEnvVar = (typeof REQUIRED_PUBLIC_ENV_VARS)[number];

function getRequiredPublicEnvVar(name: RequiredPublicEnvVar): string {
const value = process.env[name];
if (!value) {
throw new Error(`Missing required env var: ${name}`);
}
return value;
}

export function validatePublicEnv(): void {
REQUIRED_PUBLIC_ENV_VARS.forEach((name) => {
getRequiredPublicEnvVar(name);
});
}

export const env = {
NEXT_PUBLIC_API_BASE_URL: getRequiredPublicEnvVar('NEXT_PUBLIC_API_BASE_URL'),
NEXT_PUBLIC_STELLAR_NETWORK: getRequiredPublicEnvVar(
'NEXT_PUBLIC_STELLAR_NETWORK'
),
} as const;
@Akshola00 Akshola00 merged commit 32f954a into Web3Novalabs:main Jun 30, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants