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

@ -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
@ -26,4 +26,7 @@ PUBLIC_B2_ENDPOINT=https://s3.us-west-002.backblazeb2.com
PUBLIC_B2_REGION=us-west-002
# OpenAI (for AI features)
OPENROUTER_API_KEY=your_openrouter_api_key
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