Compare commits
2 Commits
afa74f7d45
...
8982f76d15
| Author | SHA1 | Date | |
|---|---|---|---|
| 8982f76d15 | |||
| 22c36eff67 |
@@ -1 +1,122 @@
|
|||||||
Welcome the only Portfolio you'll ever need
|
# BTC Portfolio Tracker
|
||||||
|
|
||||||
|
A full-stack Bitcoin portfolio tracker with live EUR pricing, purchase history, and interactive charts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Live BTC price** — fetched from CoinGecko in EUR
|
||||||
|
- **Purchase tracking** — log BTC buys with amount (EUR) and price per BTC
|
||||||
|
- **Portfolio stats** — total invested, current value, profit/loss
|
||||||
|
- **Interactive charts** — portfolio value over time and 1-year BTC price history
|
||||||
|
- **Edit & delete** — manage purchases with inline editing
|
||||||
|
- **JWT authentication** — secure per-user portfolios
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
| Layer | Technology |
|
||||||
|
|----------|-------------------------------------|
|
||||||
|
| Frontend | React 18, Chart.js, dark theme |
|
||||||
|
| Backend | FastAPI, SQLAlchemy, SQLite |
|
||||||
|
| Auth | JWT (HS256, 24h expiry) + bcrypt |
|
||||||
|
| Pricing | CoinGecko API (EUR) |
|
||||||
|
| Deploy | Docker + Docker Compose |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Docker (recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <repo-url>
|
||||||
|
cd btc-portfolio
|
||||||
|
docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
- Frontend: [http://localhost:3000](http://localhost:3000)
|
||||||
|
- Backend API: [http://localhost:8000](http://localhost:8000)
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
|
**Backend**
|
||||||
|
```bash
|
||||||
|
cd btc-portfolio/backend
|
||||||
|
pip install -r requirements.txt
|
||||||
|
uvicorn app.main:app --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
**Frontend**
|
||||||
|
```bash
|
||||||
|
cd btc-portfolio/frontend
|
||||||
|
npm install
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
btc-portfolio/
|
||||||
|
├── backend/
|
||||||
|
│ └── app/
|
||||||
|
│ ├── main.py # FastAPI app + CORS
|
||||||
|
│ ├── models.py # User & Purchase ORM models
|
||||||
|
│ ├── auth.py # JWT + bcrypt
|
||||||
|
│ ├── dependencies.py # Auth dependency injection
|
||||||
|
│ ├── routes/
|
||||||
|
│ │ ├── users.py # POST /register, POST /login
|
||||||
|
│ │ ├── purchases.py # CRUD /purchases
|
||||||
|
│ │ ├── stats.py # GET /stats
|
||||||
|
│ │ └── history.py # GET /history (365-day BTC prices)
|
||||||
|
│ └── services/
|
||||||
|
│ └── btc.py # CoinGecko integration
|
||||||
|
└── frontend/
|
||||||
|
└── src/
|
||||||
|
├── App.js # Routing
|
||||||
|
├── pages/
|
||||||
|
│ └── Dashboard.js # Main view
|
||||||
|
└── components/
|
||||||
|
├── AddPurchase.js # Purchase form
|
||||||
|
├── PurchaseList.js # Purchase table (edit/delete)
|
||||||
|
├── PortfolioChart.js # Invested vs current value
|
||||||
|
└── BTCHistoryChart.js # 1-year BTC price history
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
| Method | Endpoint | Description | Auth |
|
||||||
|
|--------|-------------------|------------------------------|------|
|
||||||
|
| POST | `/register` | Create account | No |
|
||||||
|
| POST | `/login` | Get JWT token | No |
|
||||||
|
| GET | `/purchases` | List user purchases | Yes |
|
||||||
|
| POST | `/purchases` | Add a purchase | Yes |
|
||||||
|
| PUT | `/purchases/{id}` | Edit a purchase | Yes |
|
||||||
|
| DELETE | `/purchases/{id}` | Delete a purchase | Yes |
|
||||||
|
| GET | `/stats` | Portfolio stats (P&L) | Yes |
|
||||||
|
| GET | `/history` | 365-day BTC price history | Yes |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
SQLite, stored at `/app/data/btc_portfolio.db` (persisted via Docker volume).
|
||||||
|
|
||||||
|
| Table | Columns |
|
||||||
|
|-------------|------------------------------------------------------|
|
||||||
|
| `users` | id, username (unique), password (bcrypt hash) |
|
||||||
|
| `purchases` | id, amount_eur, price_eur, created_at, user_id (FK) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The `SECRET_KEY` in `auth.py` is hardcoded — use an environment variable in production.
|
||||||
|
- CoinGecko requests are unauthenticated; failures return `0.0` gracefully.
|
||||||
|
- CORS is restricted to `localhost:3000` by default.
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build: ./frontend
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
args:
|
||||||
|
- REACT_APP_API_URL=http://localhost:8000
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3001:3000"
|
||||||
environment:
|
|
||||||
- REACT_APP_API_URL=http://localhost:8000
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
Reference in New Issue
Block a user