Knightchaser's Cryptocurrency eXchange
- Service buildup
- Deployment
- You can able to deploy on
You can try KCX at 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)
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!
Currently, there are environment variables to set up the services as you need. Read the next chapter(Deployment
) for complete contextual information.
SQLALCHEMY_DB_SQLITE3_FILENAME="kcx.db"
TEST_ACCOUNT_ID="test"
TEST_ACCOUNT_PW="test"
TEST_ACCOUNT_EMAIL="[email protected]"
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), andTEST_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) andJWT_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 <PROJECT_DIR>/backend/.secrets.smtp
, fill the contents like below. If you use Gmail for SMTP, the configuration would like below.
# 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
- Clone the repository on your server/environments
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)
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.
- Ensure that you have your own domain(FQDN) such as
docker-compose -f docker-compose-server-deploy.yml build
docker-compose -f docker-compose-server-deploy.yml up -d
- All service data will be stored in
<PROJECT_DIR>/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)
...
- The TLS/SSL extensions are expected to be in
/etc/letsencrypt
in general if you useletsencrypt
.
(/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 ishttps://kcx.knightchaser.com
's.) Changeserver_name
,ssl_certificate
, andssl_certificate_key
properties to your own.
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 thevolumes
part ofnginx
to yours(if it's needed). If you follow the standardletsencrypt
's TLS/SSL issuing procedure with Certbot, this adjustment won't be necessary.
...
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
<PROJECT_DIR>/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
. Allow80
and443
ports at least.