Merge pull request #85 from MD1125/documentation

Improve Documentation, Harden Build Scripts, and Enhance Number Formatting
This commit is contained in:
Face 2025-07-15 18:14:03 +03:00 committed by GitHub
commit e58d343673
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 349 additions and 69 deletions

View file

@ -11,14 +11,25 @@ RUN apt-get update -qq && \
python-is-python3 \
curl \
ca-certificates \
unzip && \
rm -rf /var/lib/apt/lists/*
unzip \
libc6 \
&& rm -rf /var/lib/apt/lists/*
FROM base-node AS build-main
# Copy package files
COPY website/package.json website/package-lock.json* ./
RUN npm install --include=dev
COPY website/. ./
# Install dependencies with platform-specific binaries
RUN npm install --include=dev --platform=linux --arch=x64
# Copy the rest of the application
COPY website/. .
# Create .svelte-kit directory if it doesn't exist
RUN mkdir -p .svelte-kit
# Generate SvelteKit types and build
RUN npm run build
FROM base-node AS build-websocket

161
README.md
View file

@ -18,33 +18,174 @@ Rugplay is a realistic cryptocurrency trading simulator that lets you experience
![Preview 2](github_assets/preview2.png)
![Preview](github_assets/preview.png)
## Setup
## Development Setup
1. Copy the environment file:
### Prerequisites
Before you begin, make sure you have the following installed:
- [Node.js](https://nodejs.org/) (LTS version recommended)
- [Bun](https://bun.sh/) (for websocket server)
- [Docker](https://www.docker.com/) (for running Redis and PostgreSQL)
### Getting Started
1. **Clone the repository**
```bash
cp website/.env.example website/.env
git clone https://github.com/outpoot/rugplay.git
cd rugplay
```
2. Edit `website/.env` with your actual values.
2. **Set up Redis**
3. Start with Docker (recommended):
Create a Redis Docker container:
```bash
docker run -d --name rugplay-redis -p 6379:6379 -v rugplay_redisdata:/data --restart unless-stopped redis:8-alpine redis-server --save 60 1
```
**Alternative:** You can also [download and install Redis directly](https://redis.io/downloads/) for your operating system, or use a managed Redis service such as Redis Cloud.
3. **Set up PostgreSQL**
You have two main options for your Postgres database:
- **Run Postgres locally with Docker:**
```bash
docker run -d --name rugplay-postgres -e POSTGRES_USER=pguser -e POSTGRES_PASSWORD=pgpass -e POSTGRES_DB=rugplay -p 5432:5432 -v rugplay_pgdata:/var/lib/postgresql/data --restart unless-stopped pgvector/pgvector:pg16
```
- **Use a managed cloud Postgres provider:**
Services like [Supabase](https://supabase.com/), [Neon](https://neon.tech/), or others let you create a Postgres database online, often with a free tier. Simply grab your connection details (host, user, password, database name) from your provider.
After your database is running, update your `DATABASE_URL` in the `.env` file to point to your Postgres instance.
If you are running Postgres locally, you can seed the database with:
```bash
docker exec -it rugplay-postgres psql -d rugplay -U pguser
```
Then, copy and paste the SQL from the migration files (e.g. `website/drizzle/0000_crazy_bloodstrike.sql`).
4. **Configure Google OAuth**
- Go to [Google Auth Platform dashboard](https://console.cloud.google.com/auth/clients)
- Create a new client:
- Application type: "Web application"
- Name: Your choice
- Authorized JavaScript origins: Can be left empty
- Authorized redirect URIs:
- http://localhost:3002/api/auth/callback/google
- http://localhost:5173/api/auth/callback/google
- Production URL
5. **Configure Environment Variables**
```bash
cd website
cp .env.example .env
```
Edit `.env` with your values. Example:
```ini
# --- Database ---
DATABASE_URL=postgres://pguser:pgpass@localhost:5432/rugplay # PostgreSQL connection string
POSTGRES_USER=pguser # PostgreSQL username (should match Docker config)
POSTGRES_PASSWORD=pgpass # PostgreSQL password (should match Docker config)
POSTGRES_DB=rugplay # PostgreSQL database name (should match Docker config)
# --- Redis ---
REDIS_URL=redis://localhost:6379 # Redis connection string
# --- Auth ---
PRIVATE_BETTER_AUTH_SECRET=your_secret_here # Any alphanumeric string for session encryption
PUBLIC_BETTER_AUTH_URL=http://localhost:5173 # For development, use http://localhost:5173. For production, use http://localhost:3002
# --- Google OAuth ---
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# --- Websocket ---
PUBLIC_WEBSOCKET_URL=ws://localhost:8080 # URL of the websocket server
# --- Optional: AWS (for additional features) ---
AWS_ACCESS_KEY_ID=your_aws_access_key
AWS_SECRET_ACCESS_KEY=your_aws_secret_key
AWS_REGION=us-east-1
# --- Optional: OpenRouter (for AI features) ---
OPENROUTER_API_KEY=your_openrouter_api_key
```
**Notes:**
- For production, change `PUBLIC_BETTER_AUTH_URL` to `http://localhost:3002` or your deployed domain.
- The `DATABASE_URL` should match your Postgres Docker container settings.
- The `REDIS_URL` should match your Redis Docker container settings.
- AWS and OpenRouter variables are optional and only needed for advanced features.
6. **Install Dependencies**
Set up the websocket server:
```bash
cd website/websocket
bun install
```
Set up the main website:
```bash
cd ../
npm install --include=dev
```
### Running the Application
1. **Start the websocket server**
```bash
cd website/websocket
bun run src/main.ts
```
2. **Start the main website (Development Mode)**
In a new terminal:
```bash
cd website
npm run dev
```
The development server will be available at http://localhost:5173
### Production Deployment
#### Using Docker (Recommended)
1. **Build and start with Docker:**
```bash
./build.sh
```
4. The app will be available at http://localhost:3002
This will automatically start all required services, including the Database, Redis and the websocket server, as Docker containers. You do not need to run the websocket server manually when using Docker Compose for deployment.
## Development
2. The app will be available at http://localhost:3002
#### Manual Deployment
1. **Build the website:**
```bash
cd website
npm install
npm run dev
npm run build
npm run preview
```
The development server runs on http://localhost:5173
2. **Start the websocket server:**
```bash
cd website/websocket
bun run src/main.ts
```
## License

View file

@ -1,10 +1,6 @@
#!/bin/bash
set -e
cd "$(dirname "$0")"
echo "🚀 Starting Rugplay deployment..."
echo "📥 Pulling latest changes..."
git pull

View file

@ -1,5 +1,3 @@
version: '3.8'
services:
app:
build:

View file

@ -12,7 +12,7 @@ REDIS_URL=redis://redis:6379
# Authentication
PRIVATE_BETTER_AUTH_SECRET=your_super_secret_auth_key_here
PUBLIC_BETTER_AUTH_URL=http://localhost:3002
PUBLIC_BETTER_AUTH_URL=http://localhost:5173 # Change for Production to http://localhost:3002
# Google OAuth (optional - for social login)
GOOGLE_CLIENT_ID=your_google_client_id
@ -27,3 +27,6 @@ PUBLIC_B2_REGION=us-west-002
# OpenAI (for AI features)
OPENROUTER_API_KEY=your_openrouter_api_key
# Websocket URL
PUBLIC_WEBSOCKET_URL=http://localhost:8080

View file

@ -1,38 +1,65 @@
# sv
# Rugplay Website
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
This is the main website component of Rugplay, built with SvelteKit. It handles the user interface, trading functionality, and market visualization.
## Creating a project
## Development
If you're seeing this, you've probably already done this step. Congrats!
### Prerequisites
- Node.js (LTS version)
- Redis running in the background
- OpenRouter API key (for AI features)
- AWS S3/B2 Storage (for file uploads)
### Environment Variables
Create a `.env` file based on `.env.example`:
```bash
# create a new project in the current directory
npx sv create
# create a new project in my-app
npx sv create my-app
cp .env.example .env
```
## Developing
Key variables to configure:
- `PUBLIC_BETTER_AUTH_URL`: Set to `http://localhost:3002` if you want to deploy
- `OPENROUTER_API_KEY`: Your OpenRouter API key for AI features
- AWS credentials (optional but recommended)
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
### Running in Development
```bash
npm install
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
The development server will be available at http://localhost:5173
To create a production version of your app:
### Building for Production
```bash
npm run build
npm run preview
```
You can preview the production build with `npm run preview`.
## Project Structure
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
- `src/routes/`: Page components and API endpoints
- `src/lib/`: Shared components and utilities
- `src/lib/components/`: Reusable UI components
- `static/`: Static assets (images, fonts, etc.)
## Features
- User authentication and profile management
- Real-time trading interface
- Market visualization with Treemap
- Leaderboards and statistics
- Integration with websocket server for live updates
## Contributing
1. Make sure Redis is running
2. Start the websocket server (see `websocket/README.md`)
3. Run the website in development mode
4. Make your changes
5. Test thoroughly
6. Submit a pull request

View file

@ -10,7 +10,6 @@
"dependencies": {
"@aws-sdk/client-s3": "^3.815.0",
"@aws-sdk/s3-request-presigner": "^3.815.0",
"@sveltejs/adapter-node": "^5.2.12",
"@tailwindcss/postcss": "^4.1.7",
"@tailwindcss/typography": "^0.5.16",
"@visx/scale": "^3.12.0",
@ -34,6 +33,7 @@
"@internationalized/date": "^3.8.1",
"@lucide/svelte": "^0.482.0",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-node": "^5.2.12",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@types/canvas-confetti": "^1.9.0",
@ -57,7 +57,8 @@
"vite-plugin-iso-import": "^1.2.0"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "*"
"@rollup/rollup-linux-x64-gnu": "*",
"lightningcss-linux-x64-gnu": "*"
}
},
"node_modules/@alloc/quick-lru": {
@ -1507,6 +1508,7 @@
},
"node_modules/@polka/url": {
"version": "1.0.0-next.29",
"dev": true,
"license": "MIT"
},
"node_modules/@redis/bloom": {
@ -1563,6 +1565,7 @@
"version": "28.0.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.3.tgz",
"integrity": "sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"commondir": "^1.0.1",
@ -1588,6 +1591,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"dev": true,
"dependencies": {
"@types/estree": "*"
}
@ -1596,6 +1600,7 @@
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz",
"integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.1.0"
},
@ -1615,6 +1620,7 @@
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz",
"integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"@types/resolve": "1.20.2",
@ -1638,6 +1644,7 @@
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz",
"integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
@ -1662,6 +1669,7 @@
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
@ -1674,6 +1682,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
@ -1686,6 +1695,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
@ -1698,6 +1708,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
@ -1710,6 +1721,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
@ -1722,6 +1734,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
@ -1734,6 +1747,7 @@
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1746,6 +1760,7 @@
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1758,6 +1773,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1770,6 +1786,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1782,6 +1799,7 @@
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1794,6 +1812,7 @@
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1806,6 +1825,7 @@
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1818,6 +1838,7 @@
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1830,6 +1851,7 @@
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1854,6 +1876,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -1866,6 +1889,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
@ -1878,6 +1902,7 @@
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
@ -1888,6 +1913,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -2554,6 +2580,8 @@
"version": "5.2.12",
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.12.tgz",
"integrity": "sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-json": "^6.1.0",
@ -2566,6 +2594,7 @@
},
"node_modules/@sveltejs/kit": {
"version": "2.21.1",
"dev": true,
"license": "MIT",
"dependencies": {
"@sveltejs/acorn-typescript": "^1.0.5",
@ -2595,6 +2624,7 @@
},
"node_modules/@sveltejs/vite-plugin-svelte": {
"version": "4.0.4",
"dev": true,
"license": "MIT",
"dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.0||^3.0.0",
@ -2614,6 +2644,7 @@
},
"node_modules/@sveltejs/vite-plugin-svelte-inspector": {
"version": "3.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "^4.3.7"
@ -2777,6 +2808,7 @@
},
"node_modules/@types/cookie": {
"version": "0.6.0",
"dev": true,
"license": "MIT"
},
"node_modules/@types/d3-array": {
@ -2850,7 +2882,8 @@
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
"dev": true
},
"node_modules/@visx/scale": {
"version": "3.12.0",
@ -3315,7 +3348,8 @@
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
"dev": true
},
"node_modules/content-disposition": {
"version": "1.0.0",
@ -3338,6 +3372,7 @@
},
"node_modules/cookie": {
"version": "0.6.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@ -3461,6 +3496,7 @@
},
"node_modules/deepmerge": {
"version": "4.3.1",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@ -3501,6 +3537,7 @@
},
"node_modules/devalue": {
"version": "5.1.1",
"dev": true,
"license": "MIT"
},
"node_modules/drizzle-kit": {
@ -3794,7 +3831,8 @@
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"node_modules/etag": {
"version": "1.8.1",
@ -3905,6 +3943,7 @@
},
"node_modules/fdir": {
"version": "6.4.4",
"dev": true,
"license": "MIT",
"peerDependencies": {
"picomatch": "^3 || ^4"
@ -3991,6 +4030,7 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@ -4181,6 +4221,7 @@
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"dev": true,
"dependencies": {
"hasown": "^2.0.2"
},
@ -4194,7 +4235,8 @@
"node_modules/is-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
"dev": true
},
"node_modules/is-promise": {
"version": "4.0.0",
@ -4224,6 +4266,7 @@
},
"node_modules/kleur": {
"version": "4.1.5",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@ -4262,6 +4305,26 @@
"lightningcss-win32-x64-msvc": "1.30.1"
}
},
"node_modules/lightningcss-linux-x64-gnu": {
"version": "1.30.1",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz",
"integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==",
"cpu": [
"x64"
],
"license": "MPL-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-win32-x64-msvc": {
"version": "1.30.1",
"cpu": [
@ -4447,6 +4510,7 @@
},
"node_modules/mri": {
"version": "1.2.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
@ -4454,6 +4518,7 @@
},
"node_modules/mrmime": {
"version": "2.0.1",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@ -4628,7 +4693,8 @@
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"node_modules/path-to-regexp": {
"version": "8.2.0",
@ -4646,6 +4712,7 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
@ -4887,6 +4954,7 @@
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
"dev": true,
"dependencies": {
"is-core-module": "^2.16.0",
"path-parse": "^1.0.7",
@ -4916,6 +4984,7 @@
},
"node_modules/rollup": {
"version": "4.41.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.7"
@ -4958,6 +5027,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@ -4999,6 +5069,7 @@
},
"node_modules/sade": {
"version": "1.8.1",
"dev": true,
"license": "MIT",
"dependencies": {
"mri": "^1.1.0"
@ -5223,6 +5294,7 @@
},
"node_modules/sirv": {
"version": "3.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"@polka/url": "^1.0.0-next.24",
@ -5286,6 +5358,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -5572,6 +5645,7 @@
},
"node_modules/totalist": {
"version": "3.0.1",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@ -5706,6 +5780,7 @@
},
"node_modules/vite": {
"version": "5.4.19",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.21.3",
@ -5776,6 +5851,7 @@
},
"node_modules/vite/node_modules/esbuild": {
"version": "0.21.5",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@ -5815,6 +5891,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -5826,6 +5903,7 @@
},
"node_modules/vitefu": {
"version": "1.0.6",
"dev": true,
"license": "MIT",
"workspaces": [
"tests/deps/*",

View file

@ -19,6 +19,7 @@
"@internationalized/date": "^3.8.1",
"@lucide/svelte": "^0.482.0",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-node": "^5.2.12",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@types/canvas-confetti": "^1.9.0",
@ -44,7 +45,6 @@
"dependencies": {
"@aws-sdk/client-s3": "^3.815.0",
"@aws-sdk/s3-request-presigner": "^3.815.0",
"@sveltejs/adapter-node": "^5.2.12",
"@tailwindcss/postcss": "^4.1.7",
"@tailwindcss/typography": "^0.5.16",
"@visx/scale": "^3.12.0",
@ -65,6 +65,7 @@
"svelte-lightweight-charts": "^2.2.0"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "*"
"@rollup/rollup-linux-x64-gnu": "*",
"lightningcss-linux-x64-gnu": "*"
}
}

View file

@ -1,23 +1,27 @@
// src/lib/auth.ts (or your auth config file)
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { env } from '$env/dynamic/private';
import { env as privateEnv } from '$env/dynamic/private';
import { env as publicEnv } from '$env/dynamic/public';
import { db } from "./server/db";
import * as schema from "./server/db/schema";
import { generateUsername } from "./utils/random";
import { uploadProfilePicture } from "./server/s3";
import { apiKey } from "better-auth/plugins";
if (!env.GOOGLE_CLIENT_ID) throw new Error('GOOGLE_CLIENT_ID is not set');
if (!env.GOOGLE_CLIENT_SECRET) throw new Error('GOOGLE_CLIENT_SECRET is not set');
if (!privateEnv.GOOGLE_CLIENT_ID) throw new Error('GOOGLE_CLIENT_ID is not set');
if (!privateEnv.GOOGLE_CLIENT_SECRET) throw new Error('GOOGLE_CLIENT_SECRET is not set');
if (!publicEnv.PUBLIC_BETTER_AUTH_URL) throw new Error('PUBLIC_BETTER_AUTH_URL is not set');
export const auth = betterAuth({
baseURL: env.PUBLIC_BETTER_AUTH_URL,
secret: env.PRIVATE_BETTER_AUTH_SECRET,
baseURL: publicEnv.PUBLIC_BETTER_AUTH_URL,
secret: privateEnv.PRIVATE_BETTER_AUTH_SECRET,
appName: "Rugplay",
trustedOrigins: [
env.BETTER_AUTH_URL, "http://rugplay.com", "http://localhost:5173",
publicEnv.PUBLIC_BETTER_AUTH_URL,
"http://rugplay.com",
"http://localhost:5173",
],
plugins: [
@ -41,8 +45,8 @@ export const auth = betterAuth({
}),
socialProviders: {
google: {
clientId: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET,
clientId: privateEnv.GOOGLE_CLIENT_ID,
clientSecret: privateEnv.GOOGLE_CLIENT_SECRET,
mapProfileToUser: async (profile) => {
const newUsername = generateUsername();
let s3ImageKey: string | null = null;
@ -78,7 +82,7 @@ export const auth = betterAuth({
user: {
additionalFields: {
username: { type: "string", required: true, input: false },
isAdmin: { type: "boolean", required: false, input: false },
isAdmin: { type: "boolean", required: true, input: false },
isBanned: { type: "boolean", required: false, input: false },
banReason: { type: "string", required: false, input: false },
baseCurrencyBalance: { type: "string", required: false, input: false },

View file

@ -203,13 +203,15 @@
<!-- Page dots -->
<div class="flex items-center justify-center gap-2">
{#each tips as _, index}
{#each tips as tip, index}
<button
onclick={() => goToPage(index)}
class="h-2 w-2 rounded-full transition-colors {index === currentPage
? 'bg-primary'
: 'bg-muted-foreground/30 hover:bg-muted-foreground/50'}"
/>
aria-label={`Go to tip ${index + 1}: ${tip.title}`}
aria-current={index === currentPage ? 'page' : undefined}
></button>
{/each}
</div>
</div>

View file

@ -63,6 +63,8 @@ export function formatPrice(price: number): string {
export function formatValue(value: number | string): string {
const numValue = typeof value === 'string' ? parseFloat(value) : value;
if (typeof numValue !== 'number' || isNaN(numValue)) return '$0.00';
if (numValue >= 1e12) return `$${(numValue / 1e12).toFixed(2)}T`;
if (numValue >= 1e9) return `$${(numValue / 1e9).toFixed(2)}B`;
if (numValue >= 1e6) return `$${(numValue / 1e6).toFixed(2)}M`;
if (numValue >= 1e3) return `$${(numValue / 1e3).toFixed(2)}K`;

View file

@ -1,15 +1,32 @@
# websocket
# Websocket Server
To install dependencies:
This is the websocket server component of Rugplay, built with [Bun](https://bun.sh) - a fast all-in-one JavaScript runtime.
## Prerequisites
- [Bun](https://bun.sh) (v1.2.11 or later)
- [Redis](https://redis.io/downloads/) running in the background
## Development
### Initial Setup
```bash
bun install
```
To run:
### Running the Server
```bash
bun run src/main.ts
```
This project was created using `bun init` in bun v1.2.11. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
## Production
For production deployment, you do not need to start the WebSocket server separately. Simply run `build.sh` in the main directory, and the WebSocket server will be included as part of the deployment process.
## Notes
- This project was created using `bun init` in bun v1.2.11
- The websocket server handles real-time updates for the trading platform
- Make sure Redis is running before starting the server