Progressive Web Application (PWA) for investors to view their portfolio balance, performance, and request withdrawals or deposits.
- 🔐 Google Authentication - Secure login with Firebase Auth
- 📊 Dashboard - Portfolio metrics and performance tracking
- 💰 Depósitos - View deposit addresses (USDT/USDC only)
- 📤 Retiros - Submit partial or full withdrawal requests
- 🧾 Historial - Movements table (planned)
- 📱 PWA Support - Install as native app on mobile devices
- 🎨 Responsive Design - Optimized for mobile and desktop
- Frontend: React 18 + Vite
- Styling: Tailwind CSS
- Authentication: Firebase Auth (Google Sign-In)
- Data Source: Winbit Rails API (PostgreSQL)
- Hosting: Firebase Hosting
- Email: EmailJS
- Testing: Vitest + React Testing Library
The investor panel can live either:
- As a route under the same domain (recommended):
/app(e.g.winbit.../app) - As a subdomain:
app.winbit...
In both cases, the investor panel routes remain protected behind Firebase Auth.
When hosting the panel under /app, the development URL is typically:
http://localhost:5173/app/
- Default language: Español
- Language switcher: Header (top-right) (Spanish / English)
- Language preference: stored in localStorage
- Translation system:
react-i18next
The app uses Argentine number formatting:
- Thousands separator: Point (
.) - Example:15.226 - Decimal separator: Comma (
,) - Example:15.226,00 - Currency format:
$15.226,00(no space between $ and number) - Percentage format:
+1,50%(always show sign for positive values) - Return values: Show
+sign for positive results (except portfolio value) - Zero values: No sign for zero (
$0,00,0,00%)
- Portfolio value:
$15.226,50(no sign) - Positive returns:
+$1.500,75and+1,50% - Negative returns:
-$500,25and-2,30% - Zero:
$0,00and0,00%
- Node.js 18+ and npm
- Firebase project with Authentication and Hosting enabled
- Winbit Rails backend running (see ../winbit-rails/README.md)
- EmailJS account for email notifications
git clone <repository-url>
cd winbit-app
npm installCreate a .env file in the root directory:
# Firebase Configuration (para autenticación con Google)
VITE_FIREBASE_API_KEY=your_firebase_api_key
VITE_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your_project_id
VITE_FIREBASE_STORAGE_BUCKET=your_project.firebasestorage.app
VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
VITE_FIREBASE_APP_ID=your_app_id
# Winbit Rails API URL
# Desarrollo local: http://localhost:3000
# Producción: https://winbit-rails-55a941b2fe50.herokuapp.com
VITE_API_URL=http://localhost:3000
# EmailJS Configuration
VITE_EMAILJS_SERVICE_ID=your_emailjs_service_id
VITE_EMAILJS_TEMPLATE_ID_WITHDRAWAL=your_withdrawal_template_id
VITE_EMAILJS_TEMPLATE_ID_DEPOSIT=your_deposit_template_id
VITE_EMAILJS_PUBLIC_KEY=your_emailjs_public_keyYour Google Sheet should have the following structure:
| Column A | Column B | Column C | Column D | Column E | Column F+ |
|---|---|---|---|---|---|
| Name | Balance | Invested | Returns% | Historical Data |
- Column A: Investor email (must match Google Sign-In email)
- Column B: Investor name
- Column C: Current balance (USD)
- Column D: Total invested (USD)
- Column E: Returns/Performance (%)
Edit src/config/wallets.js with your wallet addresses:
export const WALLETS = [
{
network: 'USDT (TRC20)',
address: 'your_usdt_trc20_address',
icon: '₮',
},
{
network: 'USDC (TRC20)',
address: 'your_usdc_trc20_address',
icon: '$',
},
// Pending: final list of supported networks + addresses
];# Start development server
npm run dev
# Run tests
npm run test
# Run tests with coverage
npm run test:coverage
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
# Build for production
npm run build
# Preview production build
npm run previewThe project uses Vitest and React Testing Library.
Current Test Coverage: ~89.6%
| Metric | Percentage |
|---|---|
| Lines | 89.6% |
| Statements | 89.6% |
| Branches | 72.45% |
| Functions | 83.33% |
- Total Tests: 167+ tests passing
- Test Framework: Vitest + React Testing Library
- Test Files: 40+ test files
- ✅ UI Components: 100% coverage (Button, Card, Input, Select, Spinner, Toast, etc.)
- ✅ Utils: 98.96% coverage (formatCurrency, formatDate, formatName, etc.)
- ✅ Hooks: 98.63% coverage (useAuth, useInvestorData, useInvestorHistory, useWallets)
- ✅ Services:
api.js- 93.88% (critical API service with Rails backend)email.js- 100%
- ✅ Pages: 92.23% average coverage
⚠️ Authentication: 53.42% (AuthProvider - Firebase integration, complex to test)
# Run all tests
npm run test
# Generate coverage report
npm run test:coverageVITE_API_URL=http://localhost:3000
VITE_FIREBASE_API_KEY=xxx
VITE_FIREBASE_AUTH_DOMAIN=xxx
# ... other Firebase config
⚠️ IMPORTANTE: Este archivo NO está en git. Debes crearlo manualmente.
# Rails API URL - Heroku production
VITE_API_URL=https://winbit-rails-55a941b2fe50.herokuapp.com
# Firebase config (same as development)
VITE_FIREBASE_API_KEY=xxx
VITE_FIREBASE_AUTH_DOMAIN=xxx
# ... other Firebase configVer .env.production.example para referencia completa.
URL de producción: https://winbit-6579c.web.app
- Install Firebase CLI (si no lo tienes):
npm install -g firebase-tools- Login to Firebase:
firebase login- Build y deploy:
# Asegúrate de tener .env.production configurado
npm run build # Usa .env.production automáticamente
firebase deploy # Deploy a Firebase HostingEl backend Rails debe permitir el origen de Firebase Hosting. Esto ya está configurado en Heroku:
# Variable de entorno en Heroku
CORS_ORIGINS=http://localhost:5173,https://winbit-6579c.web.app,https://winbit-6579c.firebaseapp.comSi necesitas agregar otro dominio:
heroku config:set CORS_ORIGINS="existing_origins,new_origin" -a winbit-railssrc/
├── components/
│ ├── ui/ # Reusable UI components
│ ├── layout/ # Layout components
│ └── features/ # Feature-specific components
│ ├── auth/ # Authentication
│ ├── dashboard/ # Dashboard features
│ ├── wallets/ # Wallet management
│ └── requests/ # Withdrawal/Deposit forms
├── hooks/ # Custom React hooks
├── services/ # API services
├── utils/ # Helper functions
├── pages/ # Page components
├── config/ # Configuration files
├── test/ # Test setup
├── App.jsx
└── main.jsx
- Portfolio updates are processed once per business day after the operational close
- Historical data available from investor's signup date
- Requests are received until 17:00 (GMT-3) and executed at 18:00 (GMT-3).
- Requests submitted after 17:00 (GMT-3) are processed the next day.
To finish the dashboard and history, we need the Google Sheet to explicitly define where these values come from:
- Dashboard metrics:
- Current portfolio value (USD)
- Total return since inception (USD)
- Total return since inception (%)
- Annual return (USD)
- Annual return (%)
- History table:
- Date, Movement type, Amount, Previous balance, New balance, Status
- Whether history is a single sheet with an
emailcolumn or per-investor tabs - Status values (e.g. Pending / Completed / Rejected)
- Only authenticated users with Google Sign-In
- User email must exist in Winbit Rails database as an active investor
- Firebase Auth validates authentication
- Rails API validates investor status before returning data
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)
Users can install Winbit as a native app:
- Visit the app in a supported browser
- Look for "Install" or "Add to Home Screen" prompt
- Follow browser-specific installation steps
- Ensure user's email exists in the Winbit Rails database as an investor
- Check that investor status is 'ACTIVE'
- Contact [email protected] to register as an investor
- Verify Rails backend is running at the correct URL
- Check that VITE_API_URL is configured correctly
- Ensure investor exists and is active in the database
If you see No 'Access-Control-Allow-Origin' header errors:
- Verify CORS_ORIGINS is set in Heroku:
heroku config:get CORS_ORIGINS -a winbit-rails
- Should include:
https://winbit-6579c.web.app,https://winbit-6579c.firebaseapp.com - Update if needed:
heroku config:set CORS_ORIGINS="http://localhost:5173,https://winbit-6579c.web.app,https://winbit-6579c.firebaseapp.com" -a winbit-rails
If you see auth/api-key-not-valid errors:
- Verify the API key in
.env.productionmatches your Firebase project - Check API key restrictions in Google Cloud Console
- Ensure the key has "Identity Toolkit API" enabled
- Verify authorized domains in Firebase Console include your hosting domain
Warnings like COOP policy would block the window.closed call are normal and don't affect functionality. These appear due to security headers in firebase.json and can be safely ignored.
- Verify EmailJS credentials are correct
- Check EmailJS service is active
- Confirm email templates are published
Private - All rights reserved © 2024 Winbit