https://github.com/knightchaser/kcx
A Free-From-Risk crypto trading simulation named KCX(Knightchaser's Cryptocurrency eXchange), built with Svelte + FastAPI + Docker + α
https://github.com/knightchaser/kcx
cryptocurrency fastapi redis simulated-trading simulation sqlite3 svelte trading
Last synced: 9 months ago
JSON representation
A Free-From-Risk crypto trading simulation named KCX(Knightchaser's Cryptocurrency eXchange), built with Svelte + FastAPI + Docker + α
- Host: GitHub
- URL: https://github.com/knightchaser/kcx
- Owner: KnightChaser
- Created: 2024-05-10T10:11:52.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-09-03T04:11:37.000Z (over 1 year ago)
- Last Synced: 2025-03-31T07:22:13.779Z (11 months ago)
- Topics: cryptocurrency, fastapi, redis, simulated-trading, simulation, sqlite3, svelte, trading
- Language: Svelte
- Homepage: https://kcx.knightchaser.com
- Size: 13 MB
- Stars: 5
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# KCX
> **K**nightchaser's **C**ryptocurrency e**X**change
## TECH STACK
- **Service buildup**








- **Deployment**


- **You can able to deploy on**


## A Free-From-Risk cryptocurrency exchange simulation web application
~~You can try KCX at **[https://kcx.knightchaser.com/](https://kcx.knightchaser.com/)**, hosted via AWS Lightsail by the repository owner. Note that the specifications, service status, and other things might be changed depending on the development contexts and situations. (Try only for fun! :D)~~
## Notice of public service discontinuation
The KCX service on the AWS LightSail **has been discontinued since Sep. 3, 2024** due to financial issues. During the services with 87 days, 3,566 transactions worth 16.7 trillion KRW(12.525 billion US$) were made(If all money in the services were REAL). Thanks for loving this project, my first attempt to make a modern website!
## Service environmental variables
Currently, there are environment variables to set up the services as you need. Read the next chapter(`Deployment`) for complete contextual information.
```env
SQLALCHEMY_DB_SQLITE3_FILENAME="kcx.db"
TEST_ACCOUNT_ID="test"
TEST_ACCOUNT_PW="test"
TEST_ACCOUNT_EMAIL="test@kcx.org"
COMMON_STARTING_BALANCE_IN_KRW=20000000000 # 20 billion KRW
# An example SECRET KEY for JWT. Change this to a random in production!
JWT_SECRET_KEY="KCXU$3R$3CR3T4JWT_"
JWT_TOKEN_EXPIRES_MINUTES=360 # 6 hours
# A custom API server built with Redis
REDIS_PORT=6379
REDIS_DB=0
REDIS_UDPATE_INTERVAL_IN_SECONDS=1
USER_RANKING_UPDATE_INTERVAL_IN_SECONDS=10
# Service configuration
# - Money balance (Disable(false) this if you want to use a fixed starting balance for all users)
ALLOW_ARBITRARY_BALANCE_DEPOSIT=false
ALLOW_ARBITRARY_BALANCE_WITHDRAW=false
```
- Permanent data for this service will be stored in SQLite3. Configure `SQLALCHEMY_DB_SQLITE3_FILENAME` to change the filename (if you want).
- As a default, there are default account settings.
- The service will create a default account for testing when the service starts. (Will not if it's already created)
- Configure `TEST_ACCOUNT_ID`(ID = username), `TEST_ACCOUNT_PW`(password), and `TEST_ACCOUNT_EMAIL`(email) for the test account.
- `COMMON_STARTING_BALANCE_IN_KRW` defines how much fund will be initially granted to the new user.
- This server uses JWT for user authentication. Configure `JWT_SECRET_KEY` for JWT server key(change to another random value or your own) and `JWT_TOKEN_EXPIRES_MINUTES` for JWT expiary period.
- For the price information, this service uses the market data provided from UpBIT. Of course this also mimics the cryptocurrency exchange, there are a lot of requests about the crypto market data(Generally 3 to 5 requests per second per connected user) To reduce the direct API request to UpBIT, this use REDIS database as a cache. The server caches the market data every second and multiple connected users obtain the data from this REDIS cache.
- `REDIS_UPDATE_INTERVAL_IN_SECONDS` means which second this service refreshes the market data from UpBIT to the REDIS cache periodically. Basically, you can safely request up to 5 requests per second to UpBIT according to the current policy.
- `USER_RANKING_UPDATE_INTERVAL_IN_SECONDS` means which second this service calculate the users' ranking data according to the calculated estimated total asset value periodically (for leaderboard). Note that this ranking calculation relatively takes a lot of computational loads(iterating all users and calculating all types of assets for estimation), so don't make it too short.
- `ALLOW_ARBITRARY_BALANCE_*` configures whether the user controls their virtual balances on their own. If these are set true, then they can unlimitedly deposit(increase) and withdraw(decrease) the wallet, that may impact on the leaderboard. If you run this service for competitions or some rules, set it to false so no one except for the administrator can control the user's balances. (By accessing the SQLite3 database.)
**Plus**, there is a feature of sending verification emails for changing account email address/password, or recoverying password. Get a possible **SMTP(Simple Mail Transfer Protocol)** account, and create the following environment variable file named **`/backend/.secrets.smtp`**, fill the contents like below. If you use **Gmail** for SMTP, the configuration would like below.
```env
# backend/.secrets.smtp
SMTP_USERNAME="knightchaser_example" # Gmail address without "@gmail.com"
SMTP_PASSWORD="abcd efgh ijkl mnop" # App password
SMTP_SERVER="smtp.gmail.com"
SMTP_PORT=587
```
## Deployment
- Clone the repository on your server/environments
```sh
https://github.com/KnightChaser/kcx.git
```
- To intiate the service, you'll have to use **`docker-compose`**(Or, `docker compose` for Docker Compose v2. Not matter which version you use).
- If you are going to run service locally(such as windows), execute the following commands(the system(Windows/Linux) should be able to operate the docker applications)
```sh
docker-compose -f docker-compose.yml build
docker-compose -f docker-compose.yml up -d
```
- If you are going to run service globally with TLS/SSL certificates(For production. `https://kcx.knightchaser.com` is currently running on this way.), check the prerequisites and operate the docker.
- Ensure that you have your own **domain**(FQDN) such as `*.knightchaser.com` and it's registered on the global DNS server. (i.e. Route53 in AWS)
- Ensure that the **valid TLS/SSL certificates** are issued and prepared on your system. (i.e. A certificate issued by Certbot via `letsencrypt`)
- Ensure that you properly adjusted the settings(described in the next chapter; **`Note about TLS/SSL`**.). Then, boot up the service with the following commands.
```sh
docker-compose -f docker-compose-server-deploy.yml build
docker-compose -f docker-compose-server-deploy.yml up -d
```
## Service data
- **All service data** will be stored in `/data`. Back up this directory periodically in case of deployment!
- Currently, the data directory will have the following major entires
```
data
┣ database
┃ ┗ (SQLite3 database file)
┗ uploads
┃ ┗ profile_images
┃ ┃ ┣ (user profile pictures)
...
```
## Note about TLS/SSL
- The TLS/SSL extensions are expected to be in `/etc/letsencrypt` in general if you use `letsencrypt`.
```
(/etc/letsencrypt)
├── live
│ ├── README
│ └── knightchaser.com
│ ├── README
│ ├── cert.pem -> ../../archive/knightchaser.com/cert1.pem
│ ├── chain.pem -> ../../archive/knightchaser.com/chain1.pem
│ ├── fullchain.pem -> ../../archive/knightchaser.com/fullchain1.pem
│ └── privkey.pem -> ../../archive/knightchaser.com/privkey1.pem
```
- In **`nginx.conf`**, the basic structure will be the below example. (The given example is `https://kcx.knightchaser.com`'s.) Change `server_name`, `ssl_certificate`, and `ssl_certificate_key` properties to your own.
```nginx
events { }
http {
server {
listen 80;
server_name kcx.knightchaser.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name kcx.knightchaser.com;
ssl_certificate /etc/letsencrypt/live/knightchaser.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/knightchaser.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://frontend:5173;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/ {
proxy_pass http://backend:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
```
- In the **Docker compsure file(`docker-compose-server-deploy.yml`)**, adjust the `volumes` part of **`nginx`** to yours(if it's needed). If you follow the standard `letsencrypt`'s TLS/SSL issuing procedure with Certbot, this adjustment won't be necessary.
```yml
...
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- /etc/letsencrypt:/etc/letsencrypt
depends_on:
- frontend
- backend
networks:
- kcx-network
```
- In **`/frontend/.env`**(Vite environment variable file), adjust the backend API URL to your domain. Since the suffix string `/api` is the hardcoded value of this project for consistency, you will only have to adjust the URL part. `https://kcx.knightchaser.com` part for the example below.
```
VITE_BACKEND_API_URL="https://kcx.knightchaser.com/api"
```
- Miscellaneous: **TLS/SSL** uses the port `443`. Allow `80` and `443` ports at least.