├── .gitignore
├── logo.png
├── admin
├── .env.template
├── Dockerfile
└── default.conf
├── nuxt
├── Dockerfile
└── .env.template
├── backend
└── Dockerfile
├── frontend
├── Dockerfile
├── nginx.conf
└── default.conf
├── NOTICE
├── README.md
├── LICENSE.md
└── opencex.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | env.txt
2 | .idea
3 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polygant/OpenCEX/HEAD/logo.png
--------------------------------------------------------------------------------
/admin/.env.template:
--------------------------------------------------------------------------------
1 | const localConfig = {
2 | api: "https://${DOMAIN}/apiadmin/",
3 | base: "${ADMIN_BASE_URL}",
4 | title: "${PROJECT_NAME}"
5 | }
6 | export default localConfig;
7 |
--------------------------------------------------------------------------------
/nuxt/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:14.18.1
2 | WORKDIR /app
3 | COPY package.json .
4 | COPY yarn.lock .
5 | COPY . .
6 | RUN yarn install
7 | RUN yarn build
8 | RUN yarn generate
9 | ENV HOST 0.0.0.0
10 | EXPOSE 3000
11 | CMD [ "yarn", "start" ]
12 |
--------------------------------------------------------------------------------
/backend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.8
2 | ENV PYTHONUNBUFFERED 1
3 | ENV PYTHONDONTWRITEBYTECODE 1
4 | WORKDIR /app
5 | COPY backend/ ./
6 | RUN pip install setuptools==40
7 | RUN pip install -r /app/requirements.txt
8 | RUN apt-get update && apt-get install systemd wkhtmltopdf -y
--------------------------------------------------------------------------------
/admin/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18 as build
2 | WORKDIR /app
3 | ENV PATH /app/node_modules/.bin:$PATH
4 | COPY . .
5 | RUN yarn install
6 | RUN yarn build
7 |
8 | FROM nginx:alpine
9 | COPY deploy/default.conf /etc/nginx/conf.d/default.conf
10 | COPY --from=build /app/dist /usr/share/nginx/html
11 | CMD ["nginx", "-g", "daemon off;"]
12 |
--------------------------------------------------------------------------------
/admin/default.conf:
--------------------------------------------------------------------------------
1 | server {
2 | set_real_ip_from 172.0.0.1/8;
3 | #real_ip_header X-Forwarded-For;
4 | real_ip_header CF-Connecting-IP;
5 | listen 80;
6 | server_name _;
7 | root /usr/share/nginx/html;
8 | index index.html;
9 |
10 | location / {
11 | }
12 |
13 | location /ADMIN_BASE_URL {
14 | alias /usr/share/nginx/html;
15 | try_files $uri $uri/ /index.html;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/frontend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18 as build
2 | ARG localconfig
3 | WORKDIR /app
4 | ENV PATH /app/node_modules/.bin:$PATH
5 | COPY . .
6 | RUN yarn install
7 | RUN yarn build
8 |
9 | FROM nginx:alpine
10 | COPY deploy/default.conf /etc/nginx/conf.d/default.conf
11 | COPY deploy/nginx.conf /etc/nginx/nginx.conf
12 | COPY --from=build /app/dist /usr/share/nginx/html
13 | CMD ["nginx", "-g", "daemon off;"]
14 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | =========================================================================
2 | == NOTICE file for use with the Apache License, Version 2.0, ==
3 | =========================================================================
4 |
5 | OpenCEX cryptocurrency platform
6 | Copyright 2023 Polygant (Webmart LLC, Stan Chernukhin).
7 |
8 | This product includes software developed at Polygant (https://polygant.net/).
9 |
--------------------------------------------------------------------------------
/nuxt/.env.template:
--------------------------------------------------------------------------------
1 | ###########################################################################
2 | # OpenCEX Main configuration file. More info
3 | # https://polygant.notion.site/Settings-3f9e0aae880e433a9d23e76f62a4a456
4 | ###########################################################################
5 |
6 |
7 | API_URL="https://${DOMAIN}/"
8 | BROWSER_BASE_URL="https://${DOMAIN}"
9 | project_title="${PROJECT_NAME}"
10 | telegram="${TELEGRAM}"
11 | facebook="${FACEBOOK}"
12 | twitter="${TWITTER}"
13 | linkedin="${LINKEDIN}"
14 | logo="${LOGO}"
--------------------------------------------------------------------------------
/frontend/nginx.conf:
--------------------------------------------------------------------------------
1 | user nginx;
2 |
3 | worker_processes auto;
4 | worker_rlimit_nofile 100000;
5 |
6 | events {
7 | multi_accept on;
8 | worker_connections 100000;
9 | }
10 |
11 | error_log stderr warn;
12 | pid /var/run/nginx.pid;
13 |
14 | http {
15 | sendfile on;
16 | tcp_nopush on;
17 |
18 | keepalive_timeout 30;
19 | keepalive_requests 256;
20 |
21 | proxy_connect_timeout 30;
22 | proxy_send_timeout 3600;
23 | proxy_read_timeout 3600;
24 |
25 | fastcgi_keep_conn on;
26 | fastcgi_connect_timeout 120;
27 | fastcgi_send_timeout 3600;
28 | fastcgi_read_timeout 3600;
29 |
30 | client_max_body_size 1536m;
31 | client_body_buffer_size 10m;
32 | proxy_buffers 512 16k;
33 | proxy_buffer_size 16k;
34 | fastcgi_buffers 256 16k;
35 | fastcgi_temp_file_write_size 256k;
36 | proxy_max_temp_file_size 0;
37 |
38 | server_tokens off;
39 |
40 | include mime.types;
41 | types {
42 | text/plain log;
43 | }
44 | default_type application/octet-stream;
45 |
46 | charset utf-8;
47 |
48 | # Cloudflare
49 | #real_ip_header CF-Connecting-IP;
50 | #set_real_ip_from 0.0.0.0/0;
51 |
52 |
53 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
54 | '$status $body_bytes_sent "$http_referer" '
55 | '"$http_user_agent" "$http_x_forwarded_for"';
56 |
57 | access_log /dev/stdout main;
58 | #access_log /var/log/acces.log ;
59 | #error_log /var/log/error.log ;
60 | include /etc/nginx/conf.d/*.conf;
61 |
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/frontend/default.conf:
--------------------------------------------------------------------------------
1 | map $remote_addr $cond {
2 | "default" "0";
3 | "0.0.0.0" "1";
4 | }
5 |
6 | server {
7 | set_real_ip_from 172.0.0.1/8;
8 | #real_ip_header CF-Connecting-IP;
9 | real_ip_header X-Forwarded-For;
10 | add_header Content-Security-Policy "frame-ancestors *";
11 | add_header X-Frame-Options "ALLOW-FROM opencex";
12 |
13 | proxy_connect_timeout 600;
14 | proxy_send_timeout 600;
15 | proxy_read_timeout 600;
16 | send_timeout 600;
17 |
18 | fastcgi_connect_timeout 600s;
19 | fastcgi_send_timeout 600s;
20 | fastcgi_read_timeout 600s;
21 |
22 |
23 | #set $maintenance on;
24 | #set $cond "${cond}0";
25 |
26 |
27 | location = /account/wizard {
28 | return 404;
29 | }
30 | location = /account/wizard/ {
31 | return 404;
32 | }
33 |
34 |
35 |
36 |
37 | if ($cond = 00) {
38 | return 403;
39 | }
40 | error_page 503 @maintenance;
41 | error_page 403 @maintenance;
42 |
43 | listen 80 default_server;
44 |
45 | server_name DOMAIN;
46 | root /usr/share/nginx/html;
47 |
48 |
49 |
50 | location /media {
51 | alias /app/media/ ;
52 | }
53 |
54 |
55 | location /account {
56 | root /usr/share/nginx/html;
57 | index index.html index.htm;
58 | try_files $uri $uri/ /index.html =404;
59 | }
60 |
61 | location /public {
62 | root /usr/share/nginx/html;
63 | index index.html index.htm;
64 | try_files $uri $uri/ =404;
65 | }
66 |
67 | location /assets {
68 | root /usr/share/nginx/html;
69 | index index.html index.htm;
70 | try_files $uri $uri/ /index.html =404;
71 |
72 | }
73 |
74 |
75 |
76 | location /wsapi {
77 | proxy_pass http://opencex-wss:8000;
78 | proxy_http_version 1.1;
79 | proxy_set_header Upgrade $http_upgrade;
80 | proxy_set_header Connection "upgrade";
81 |
82 | proxy_redirect off;
83 | proxy_set_header Host $host;
84 | proxy_set_header X-Real-IP $remote_addr;
85 | proxy_set_header X-Forwarded-Proto https;
86 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
87 | proxy_set_header X-Forwarded-Host $server_name;
88 | }
89 |
90 |
91 | location /ADMIN_BASE_URL {
92 |
93 | proxy_pass http://admin:80;
94 | proxy_http_version 1.1;
95 | proxy_set_header Upgrade $http_upgrade;
96 | proxy_set_header Connection "upgrade";
97 |
98 | proxy_redirect off;
99 | proxy_set_header Host $host;
100 | proxy_set_header X-Real-IP $remote_addr;
101 | proxy_set_header X-Forwarded-Proto https;
102 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
103 | proxy_set_header X-Forwarded-Host $server_name;
104 |
105 | }
106 |
107 |
108 | location / {
109 |
110 | proxy_pass http://nuxt:3000;
111 | proxy_http_version 1.1;
112 | proxy_set_header Upgrade $http_upgrade;
113 | proxy_set_header Connection "upgrade";
114 | proxy_redirect off;
115 | proxy_set_header Host $host;
116 | proxy_set_header X-Real-IP $remote_addr;
117 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
118 | proxy_set_header X-Forwarded-Proto https;
119 | proxy_set_header X-Forwarded-Host $server_name;
120 |
121 | }
122 |
123 |
124 | location /upload { alias /app/media/; }
125 |
126 | location /robots.txt { alias /usr/share/nginx/html/static/robots.txt; }
127 |
128 | location /staticfiles/ {
129 | root /app/;
130 | try_files $uri =404;
131 | }
132 |
133 |
134 | location /apiadmin {
135 | proxy_pass http://opencex:8080;
136 | proxy_http_version 1.1;
137 | proxy_set_header Upgrade $http_upgrade;
138 | proxy_set_header Connection "upgrade";
139 |
140 | proxy_redirect off;
141 | proxy_set_header Host $host;
142 | proxy_set_header X-Real-IP $remote_addr;
143 | proxy_set_header X-Forwarded-Proto https;
144 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
145 | proxy_set_header X-Forwarded-Host $server_name;
146 | }
147 |
148 | location /api {
149 | proxy_pass http://opencex:8080;
150 | proxy_http_version 1.1;
151 | proxy_set_header Upgrade $http_upgrade;
152 | proxy_set_header Connection "upgrade";
153 |
154 | proxy_redirect off;
155 | proxy_set_header Host $host;
156 | proxy_set_header X-Real-IP $remote_addr;
157 | proxy_set_header X-Forwarded-Proto https;
158 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
159 | proxy_set_header X-Forwarded-Host $server_name;
160 | }
161 |
162 |
163 |
164 |
165 |
166 |
167 | location @proxy {
168 |
169 |
170 | proxy_pass http://opencex:8080;
171 | proxy_http_version 1.1;
172 | proxy_set_header Upgrade $http_upgrade;
173 | proxy_set_header Connection "upgrade";
174 |
175 | proxy_redirect off;
176 | proxy_set_header Host $host;
177 | proxy_set_header X-Real-IP $remote_addr;
178 | proxy_set_header X-Forwarded-Proto https;
179 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
180 | proxy_set_header X-Forwarded-Host $server_name;
181 |
182 |
183 |
184 |
185 |
186 |
187 | if (-f $document_root/maintenance) {
188 | set $cond "${cond}0";
189 | }
190 |
191 |
192 |
193 | }
194 | location @maintenance {
195 | root /usr/share/nginx/html/public;
196 | rewrite ^(.*)$ /dump.html break;
197 | }
198 |
199 |
200 |
201 | }
202 |
203 |
204 |
205 |
206 |
207 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | OpenCEX is a free and open source cryptocurrency exchange platform.
9 | Developed by Polygant.
10 |
11 |
12 | Live demo | OpenCEX documentation | Telegram chat
13 |
14 |
15 | ## Main features.
16 |
17 | - Custodial wallet supporting BTC, ETH, BNB, TRX, USDT (ERC-20, BEP-20, TRC-20). Deposit and withdrawal.
18 | - Order matching engine. Trading pairs BTC-USDT, ETH-USDT, BNB-USDT, TRX-USDT.
19 | - Professional exchange interface for placing orders.
20 | - Simplified interface for quick swap.
21 | - KYT transaction verification (requires Scorechain keys).
22 | - KYC verification of users (requires Sumsub keys).
23 | - SMS 2fa for users (requires Twilio keys).
24 |
25 | ## System requirements.
26 |
27 |
37 |
38 | ## The software used.
39 |
40 |
41 | | Docker | latest | OS-level virtualization |
42 | | NGINX | 1.22.0 | Web server |
43 | | Caddy | 2.6.2 | Router |
44 | | Postgres | 14.5 | RDBMS |
45 | | Redis server | 7.0.4 | RDBMS |
46 | | RabbitMQ | 3.10.7 | Message-broker software |
47 | | Python | 3.8 | Programming language |
48 | | Django | 3.2.7 | Python framework |
49 | | VUE.JS | 3.2.25 | JS framework |
50 | | NUXT.JS | 2.15.7 | JS framework |
51 | | Bitcoin Core | latest | Bitcoin node |
52 |
53 |
54 | ## Before installing:
55 |
56 | - Watch the installation video [https://youtu.be/c-WnQkvBwf0](https://youtu.be/c-WnQkvBwf0)
57 | - Order a virtual or physical server, not below the minimum requirements. You will need full access to this server (root). Shared hosting will not work.
58 | - Bind the IPv4 address you received when purchasing the server to your domain. If you don't have a domain yet, you can use [https://nip.io/](https://nip.io/) or [https://sslip.io/](https://sslip.io/).
59 | - Sign up for a Google account and get reCAPTCHA V2 keys (invisible). [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/)
60 | - Get the SMTP server credentials for sending emails (any will do, i.e. [https://www.mailgun.com/](https://www.mailgun.com/)).
61 | - Register an Infura account ([https://infura.io/](https://infura.io/)) and create an API key + secret.
62 | - Register an Etherscan account ([https://etherscan.io/](https://etherscan.io/)) and create an API key.
63 | - You will need BTC, ETH addresses and BNB, TRX addresses(optional) to collect cryptocurrency deposits (cold addresses). If you don't have it yet, you can use any multi-currency wallet like Trust Wallet and generate BTC, ETH, BNB, TRX addresses.
64 | - OPTIONAL. For BNB и BEP-20 support you will need Bscscan credentials (https://bscscan.com/)
65 | - OPTIONAL. For TRX and TRC-20 support you will need Trondrid credentials (https://www.trongrid.io/)
66 | - OPTIONAL. For SMS verification you will need Twilio credentials ([https://twilio.com](https://twilio.com))
67 | - OPTIONAL. For KYT you need Scorechain credentials ([https://www.scorechain.com/](https://www.scorechain.com/))
68 | - OPTIONAL. For KYC you will need Sumsub credentials ([https://sumsub.com/](https://sumsub.com/))
69 |
70 |
71 | ## Installation
72 |
73 | You need to SSH into your server as root and run the following command:
74 |
75 | mkdir /app ;
76 | cd /app/ || exit ;
77 | git clone https://github.com/Polygant/OpenCEX.git ./deploy ;
78 | cd deploy ;
79 | chmod +x opencex.sh ;
80 | ./opencex.sh 2>&1 | tee /tmp/install.txt
81 |
82 | Installation time ~ 5 minutes.
83 |
84 | If something goes wrong you can clean the installation and try again
85 |
86 | cd /app/opencex && docker compose down ;
87 | rm -rf /app ;
88 | docker system prune -a
89 |
90 | 🥳 Congratulations, the exchange has been successfully installed!
91 | You can open it by your domain name.
92 |
93 | **After installation, you need to download the file /app/openex/backend/save_to_self_and_delete.txt and delete it from the server.**
94 |
95 | **Mind that BTC node will take up to 30 hours to fully sync. BTC transactions sent to user addresses in this period will be collected and credited only after a full sync.**
96 |
97 | ## Documentation
98 | - [OpenCEX Help Center](https://www.notion.so/polygant/OpenCEX-Help-Center-8cf8c842bde947c3818a615a88ceef9c)
99 | - [Admin panel Guide](https://docs.google.com/document/d/1VoBFEjzmGXzNHQYfvu8BYHvoSv9Sg73AV9wWGvsRJ04/edit#)
100 |
101 | ## Partners & Sponsors ❤️
102 | Become a partner: [hello@polygant.net](mailto:hello@polygant.net)
103 |
104 | ## Donate 💰
105 | You like our product and want to support the team? Nothing could be easier :)
106 |
107 |
108 |
109 | | Bitcoin (BTC) |
110 | USDT (TRC20) |
111 | ETH, USDT, USDC (ERC20) |
112 |
113 |
114 |  |
115 |  |
116 |  |
117 |
118 |
119 |
120 | BTC:
121 | **bc1qgdnah2uh49wgnlvpmpnf7jkwz6dm8teuf66ynt**
122 |
123 | USDT (TRC-20):
124 | **TShx7cEsDancuqU5PmVPCQ3bUMtZyiqQq2**
125 |
126 | ETH, USDT, USDC (ERC-20):
127 | **0x938209344aD987EFB91D7dc1F3957Ce3DD39b95**
128 |
129 | ## Community
130 | Ask questions at the official community Telegram chat.
131 |
132 | ## Contributing
133 | Thanks for all your wonderful PRs, issues and ideas.
134 | You’re always welcome to join: check out our contribution guides, open issues and the Telegram chat.
135 |
136 | ## Can I hire you guys?
137 |
138 | OpenCEX was created and backed by Polygant, and is supported through all the years. You can request a consultation or order web and mobile development services by Polygant, just visit our site. 😎
139 |
140 | Say hi: [hello@polygant.net](mailto:hello@polygant.net) . We will be happy to work with you!
141 |
142 | ## License
143 | Apache License, Version 2.0
144 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/opencex.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ $(dpkg-query -W -f='${Status}' docker-ce 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
4 | echo "Docker not found, install docker..."
5 | sudo apt-get update > /dev/null 2>&1
6 | sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release > /dev/null 2>&1
7 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor --yes -o /usr/share/keyrings/docker-archive-keyring.gpg
8 | echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
9 | sudo apt-get update > /dev/null 2>&1
10 | sudo apt-get install -y docker-ce docker-ce-cli containerd.io git docker-compose-plugin > /dev/null 2>&1
11 | sudo systemctl enable docker > /dev/null 2>&1
12 | sudo systemctl start docker > /dev/null 2>&1
13 | echo "Docker has been successfully installed."
14 | else
15 | echo "Docker already installed."
16 | fi
17 |
18 |
19 | mkdir /app/opencex -p
20 | cd /app/opencex || exit
21 | git clone https://github.com/Polygant/OpenCEX-backend.git ./backend
22 | git clone https://github.com/Polygant/OpenCEX-frontend.git ./frontend
23 | git clone https://github.com/Polygant/OpenCEX-static.git ./nuxt
24 | git clone https://github.com/Polygant/OpenCEX-JS-admin.git ./admin
25 |
26 | echo "`cat < /app/opencex/backend/.env
652 |
653 | fi
654 |
655 | source /app/opencex/backend/.env
656 | set -a
657 | cd /app/opencex/frontend || exit
658 | FILE=/app/opencex/frontend/src/local_config
659 |
660 | if test ! -f "$FILE"; then
661 | envsubst < /app/opencex/frontend/src/example.local_config.js > /app/opencex/frontend/src/local_config
662 | ### save to env
663 |
664 | cat << EOF >> /app/opencex/backend/.env
665 |
666 |
667 | #opencex frontend values
668 | RECAPTCHA=$RECAPTCHA
669 | TELEGRAM=$TELEGRAM
670 | TG_NEWS=$TG_NEWS
671 | SUPPORT_EMAIL=$SUPPORT_EMAIL
672 | FACEBOOK=$FACEBOOK
673 | TWITTER=$TWITTER
674 | LINKEDIN=$LINKEDIN
675 | EOF
676 |
677 | fi
678 |
679 | ##################
680 | # START BUILDING!
681 | ##################
682 |
683 |
684 | # build front
685 | mkdir -p /app/opencex/frontend/deploy/
686 | cp /app/deploy/frontend/Dockerfile /app/opencex/frontend/deploy/Dockerfile
687 | cp /app/deploy/frontend/default.conf /app/opencex/frontend/deploy/default.conf
688 | cp /app/deploy/frontend/nginx.conf /app/opencex/frontend/deploy/nginx.conf
689 | sed -i "s/ADMIN_BASE_URL/$ADMIN_BASE_URL/g" /app/opencex/frontend/deploy/default.conf
690 | sed -i "s/DOMAIN/$DOMAIN/g" /app/opencex/frontend/deploy/default.conf
691 | docker build -t frontend -f deploy/Dockerfile .
692 |
693 | # build nuxt
694 | mkdir -p /app/opencex/nuxt/deploy/
695 | cd /app/opencex/nuxt || exit
696 | cp /app/deploy/nuxt/.env.template /app/opencex/nuxt/
697 | cp /app/deploy/nuxt/Dockerfile /app/opencex/nuxt/deploy/Dockerfile
698 | envsubst < /app/opencex/nuxt/.env.template > /app/opencex/nuxt/.env
699 | docker build -t nuxt -f deploy/Dockerfile .
700 |
701 | # build admin
702 | mkdir -p /app/opencex/admin/deploy/
703 | cd /app/opencex/admin || exit
704 | cp /app/deploy/admin/Dockerfile /app/opencex/admin/deploy/Dockerfile
705 | cp /app/deploy/admin/default.conf /app/opencex/admin/deploy/default.conf
706 | cp /app/deploy/admin/.env.template /app/opencex/admin/
707 | sed -i "s/ADMIN_BASE_URL/$ADMIN_BASE_URL/g" /app/opencex/admin/deploy/default.conf
708 | envsubst < /app/opencex/admin/.env.template > /app/opencex/admin/src/local_config.js
709 | docker build -t admin -f deploy/Dockerfile .
710 |
711 |
712 | # build backend
713 | cd /app/opencex/backend/ || exit
714 | chmod +x /app/opencex/backend/manage.py
715 | docker build -t opencex .
716 |
717 |
718 | ### install Caddy
719 |
720 | mkdir /app/opencex -p
721 | cd /app/opencex || exit
722 | mkdir caddy_data postgresql_data redis_data rabbitmq_data rabbitmq_logs bitcoind_data -p
723 | chmod 777 caddy_data postgresql_data redis_data rabbitmq_data rabbitmq_logs bitcoind_data
724 | docker network create caddy
725 |
726 | cat << EOF > docker-compose.yml
727 | version: "3.7"
728 | networks:
729 | caddy:
730 | external: true
731 | services:
732 | opencex:
733 | container_name: opencex
734 | image: opencex:latest
735 | command: gunicorn exchange.wsgi:application -b 0.0.0.0:8080 -w 2 --access-logfile - --error-logfile -
736 | # entrypoint: tail -f /dev/null
737 | restart: always
738 | volumes:
739 | - /app/opencex/backend:/app
740 | networks:
741 | - caddy
742 | depends_on:
743 | - postgresql
744 | - redis
745 | - rabbitmq
746 | - frontend
747 | - nuxt
748 | - caddy
749 | - bitcoind
750 |
751 | opencex-wss:
752 | container_name: opencex-wss
753 | image: opencex:latest
754 | command: daphne -b 0.0.0.0 exchange.asgi:application --ping-interval 600 --ping-timeout 600
755 | restart: always
756 | volumes:
757 | - /app/opencex/backend:/app
758 | networks:
759 | - caddy
760 | depends_on:
761 | - postgresql
762 | - redis
763 | - rabbitmq
764 | - frontend
765 | - nuxt
766 | - caddy
767 | - bitcoind
768 | - opencex
769 |
770 | opencex-cel:
771 | container_name: opencex-cel
772 | image: opencex:latest
773 | command: celery -A exchange worker -l info -n general -B -s /tmp/cebeat.db -X btc,eth_new_blocks,eth_deposits,eth_payouts,eth_check_balances,eth_accumulations,eth_tokens_accumulations,eth_send_gas,bnb_new_blocks,bnb_deposits,bnb_payouts,bnb_check_balances,bnb_accumulations,bnb_tokens_accumulations,bnb_send_gas,trx_new_blocks,trx_deposits,trx_payouts,trx_check_balances,trx_accumulations,trx_tokens_accumulations,matic_new_blocks,matic_deposits,matic_payouts,matic_check_balances,matic_accumulations,matic_tokens_accumulations
774 | restart: always
775 | volumes:
776 | - /app/opencex/backend:/app
777 | networks:
778 | - caddy
779 | depends_on:
780 | - postgresql
781 | - redis
782 | - rabbitmq
783 | - frontend
784 | - nuxt
785 | - caddy
786 | - bitcoind
787 | - opencex
788 |
789 | opencex-stack:
790 | container_name: opencex-stack
791 | image: opencex:latest
792 | command: python bin/stack.py
793 | restart: always
794 | volumes:
795 | - /app/opencex/backend:/app
796 | networks:
797 | - caddy
798 | depends_on:
799 | - postgresql
800 | - redis
801 | - rabbitmq
802 | - frontend
803 | - nuxt
804 | - caddy
805 | - bitcoind
806 | - opencex
807 |
808 | opencex-btc:
809 | container_name: opencex-btc
810 | image: opencex:latest
811 | command: /app/manage.py btcworker
812 | restart: always
813 | volumes:
814 | - /app/opencex/backend:/app
815 | networks:
816 | - caddy
817 | depends_on:
818 | - postgresql
819 | - redis
820 | - rabbitmq
821 | - frontend
822 | - nuxt
823 | - caddy
824 | - bitcoind
825 | - opencex
826 |
827 | opencex-eth-blocks:
828 | container_name: opencex-eth-blocks
829 | image: opencex:latest
830 | command: bash -c "celery -A exchange worker -l info -n eth_new_blocks -Q eth_new_blocks -c 1 "
831 | restart: always
832 | volumes:
833 | - /app/opencex/backend:/app
834 | networks:
835 | - caddy
836 | depends_on:
837 | - postgresql
838 | - redis
839 | - rabbitmq
840 | - frontend
841 | - nuxt
842 | - caddy
843 | - bitcoind
844 | - opencex
845 |
846 | opencex-bnb-blocks:
847 | container_name: opencex-bnb-blocks
848 | image: opencex:latest
849 | command: bash -c "celery -A exchange worker -l info -n bnb_new_blocks -Q bnb_new_blocks -c 1 "
850 | restart: always
851 | volumes:
852 | - /app/opencex/backend:/app
853 | networks:
854 | - caddy
855 | depends_on:
856 | - postgresql
857 | - redis
858 | - rabbitmq
859 | - frontend
860 | - nuxt
861 | - caddy
862 | - bitcoind
863 | - opencex
864 |
865 | opencex-trx-blocks:
866 | container_name: opencex-trx-blocks
867 | image: opencex:latest
868 | command: bash -c "celery -A exchange worker -l info -n trx_new_blocks -Q trx_new_blocks -c 1 "
869 | restart: always
870 | volumes:
871 | - /app/opencex/backend:/app
872 | networks:
873 | - caddy
874 | depends_on:
875 | - postgresql
876 | - redis
877 | - rabbitmq
878 | - frontend
879 | - nuxt
880 | - caddy
881 | - bitcoind
882 | - opencex
883 |
884 | opencex-matic-blocks:
885 | container_name: opencex-matic-blocks
886 | image: opencex:latest
887 | command: bash -c "celery -A exchange worker -l info -n matic_new_blocks -Q matic_new_blocks -c 1 "
888 | restart: always
889 | volumes:
890 | - /app/opencex/backend:/app
891 | networks:
892 | - caddy
893 | depends_on:
894 | - postgresql
895 | - redis
896 | - rabbitmq
897 | - frontend
898 | - nuxt
899 | - caddy
900 | - bitcoind
901 | - opencex
902 |
903 | opencex-deposits:
904 | container_name: opencex-deposits
905 | image: opencex:latest
906 | command: bash -c "celery -A exchange worker -l info -n deposits -Q trx_deposits,bnb_deposits,eth_deposits,matic_deposits -c 1 "
907 | restart: always
908 | volumes:
909 | - /app/opencex/backend:/app
910 | networks:
911 | - caddy
912 | depends_on:
913 | - postgresql
914 | - redis
915 | - rabbitmq
916 | - frontend
917 | - nuxt
918 | - caddy
919 | - bitcoind
920 | - opencex
921 |
922 | opencex-payouts:
923 | container_name: opencex-payouts
924 | image: opencex:latest
925 | command: bash -c "celery -A exchange worker -l info -n payouts -Q trx_payouts,eth_payouts,bnb_payouts,matic_payouts -c 1 "
926 | restart: always
927 | volumes:
928 | - /app/opencex/backend:/app
929 | networks:
930 | - caddy
931 | depends_on:
932 | - postgresql
933 | - redis
934 | - rabbitmq
935 | - frontend
936 | - nuxt
937 | - caddy
938 | - bitcoind
939 | - opencex
940 |
941 | opencex-balances:
942 | container_name: opencex-balances
943 | image: opencex:latest
944 | command: bash -c "celery -A exchange worker -l info -n check_balances -Q trx_check_balances,bnb_check_balances,eth_check_balances,matic_check_balances -c 1 "
945 | restart: always
946 | volumes:
947 | - /app/opencex/backend:/app
948 | networks:
949 | - caddy
950 | depends_on:
951 | - postgresql
952 | - redis
953 | - rabbitmq
954 | - frontend
955 | - nuxt
956 | - caddy
957 | - bitcoind
958 | - opencex
959 |
960 | opencex-coin-accumulations:
961 | container_name: opencex-coin-accumulations
962 | image: opencex:latest
963 | command: bash -c "celery -A exchange worker -l info -n coin_accumulations -Q trx_accumulations,bnb_accumulations,eth_accumulations,matic_accumulations -c 1 "
964 | restart: always
965 | volumes:
966 | - /app/opencex/backend:/app
967 | networks:
968 | - caddy
969 | depends_on:
970 | - postgresql
971 | - redis
972 | - rabbitmq
973 | - frontend
974 | - nuxt
975 | - caddy
976 | - bitcoind
977 | - opencex
978 |
979 | opencex-token-accumulations:
980 | container_name: opencex-token-accumulations
981 | image: opencex:latest
982 | command: bash -c "celery -A exchange worker -l info -n tokens_accumulations -Q trx_tokens_accumulations,bnb_tokens_accumulations,eth_tokens_accumulations,matic_tokens_accumulations -c 1 "
983 | restart: always
984 | volumes:
985 | - /app/opencex/backend:/app
986 | networks:
987 | - caddy
988 | depends_on:
989 | - postgresql
990 | - redis
991 | - rabbitmq
992 | - frontend
993 | - nuxt
994 | - caddy
995 | - bitcoind
996 | - opencex
997 |
998 | opencex-gas:
999 | container_name: opencex-gas
1000 | image: opencex:latest
1001 | command: bash -c "celery -A exchange worker -l info -n send_gas -Q trx_send_gas,bnb_send_gas,eth_send_gas,matic_send_gas -c 1 "
1002 | restart: always
1003 | volumes:
1004 | - /app/opencex/backend:/app
1005 | networks:
1006 | - caddy
1007 | depends_on:
1008 | - postgresql
1009 | - redis
1010 | - rabbitmq
1011 | - frontend
1012 | - nuxt
1013 | - caddy
1014 | - bitcoind
1015 | - opencex
1016 |
1017 | frontend:
1018 | image: frontend:latest
1019 | container_name: frontend
1020 | restart: always
1021 | volumes:
1022 | - /app/opencex/backend:/app
1023 | networks:
1024 | - caddy
1025 | labels:
1026 | caddy: $DOMAIN
1027 | caddy.reverse_proxy: "{{upstreams 80}}"
1028 | nuxt:
1029 | image: nuxt:latest
1030 | container_name: nuxt
1031 | restart: always
1032 | networks:
1033 | - caddy
1034 | admin:
1035 | image: admin:latest
1036 | container_name: admin
1037 | restart: always
1038 | networks:
1039 | - caddy
1040 | caddy:
1041 | image: lucaslorentz/caddy-docker-proxy:latest
1042 | restart: always
1043 | ports:
1044 | - 80:80
1045 | - 443:443
1046 | environment:
1047 | - CADDY_INGRESS_NETWORKS=caddy
1048 | networks:
1049 | - caddy
1050 | volumes:
1051 | - /var/run/docker.sock:/var/run/docker.sock
1052 | - ./caddy_data:/data
1053 |
1054 | postgresql:
1055 | container_name: postgresql
1056 | hostname: postgresql
1057 | restart: always
1058 | image: postgres:latest
1059 | shm_size: 1g
1060 | volumes:
1061 | - ./postgresql_data:/var/lib/postgresql/data
1062 | environment:
1063 | POSTGRES_USER: "$DB_USER"
1064 | POSTGRES_PASSWORD: "$DB_PASS"
1065 | POSTGRES_DB: "$DB_NAME"
1066 | networks:
1067 | - caddy
1068 |
1069 | redis:
1070 | container_name: redis
1071 | restart: always
1072 | image: redis:latest
1073 | volumes:
1074 | - ./redis_data:/data
1075 | entrypoint: redis-server
1076 | networks:
1077 | - caddy
1078 | rabbitmq:
1079 | hostname: rabbitmq
1080 | container_name: rabbitmq
1081 | restart: always
1082 | image: rabbitmq:3.9.22-management
1083 | volumes:
1084 | - ./rabbitmq_data/:/var/lib/rabbitmq/
1085 | - ./rabbitmq_logs/:/var/log/rabbitmq/
1086 | environment:
1087 | RABBITMQ_DEFAULT_USER: $AMQP_USER
1088 | RABBITMQ_DEFAULT_PASS: $AMQP_PASS
1089 | RABBITMQ_DEFAULT_VHOST: /
1090 | networks:
1091 | - caddy
1092 | labels:
1093 | caddy: $RMQDOMAIN
1094 | caddy.reverse_proxy: "{{upstreams http 15672}}"
1095 | bitcoind:
1096 | container_name: bitcoind
1097 | restart: always
1098 | image: lncm/bitcoind:v24.0.1
1099 | volumes:
1100 | - ./bitcoind_data/:/data/.bitcoin/
1101 | networks:
1102 | - caddy
1103 | EOF
1104 |
1105 | # build hummingbot
1106 | if [ "$IS_HUMMINGBOT_ENABLED" = "True" ]; then
1107 | cd /app/opencex || exit
1108 | git clone https://github.com/Polygant/hummingbot.git ./hmbot
1109 | cd ./hmbot
1110 | docker build -t hummingbot:latest -f Dockerfile --target=release .
1111 | cat << EOF >> /app/opencex/docker-compose.yml
1112 | hummingbot:
1113 | container_name: hummingbot
1114 | hostname: hummingbot
1115 | restart: always
1116 | image: hummingbot:latest
1117 | volumes:
1118 | - /app/opencex/hmbot/conf:/home/hummingbot/conf
1119 | - /app/opencex/hmbot/conf/connectors:/home/hummingbot/conf/connectors
1120 | - /app/opencex/hmbot/conf/strategies:/home/hummingbot/conf/strategies
1121 | - /app/opencex/hmbot/logs:/home/hummingbot/logs
1122 | - /app/opencex/hmbot/data:/home/hummingbot/data
1123 | - /app/opencex/hmbot/scripts:/home/hummingbot/scripts
1124 | networks:
1125 | - caddy
1126 | tty: true
1127 | stdin_open: true
1128 | EOF
1129 | fi
1130 | cd /app/opencex
1131 | docker compose up -d
1132 |
1133 | docker stop opencex-cel opencex-wss
1134 | sleep 5;
1135 | docker exec -it opencex python ./manage.py migrate
1136 | docker exec -it opencex python ./manage.py collectstatic
1137 | docker compose up -d
1138 |
1139 |
1140 |
1141 | cd /app/opencex || exit
1142 | docker compose stop
1143 | cat << EOF > /app/opencex/bitcoind_data/bitcoin.conf
1144 | rpcuser=$BTC_NODE_USER
1145 | rpcpassword=$BTC_NODE_PASS
1146 | rpcallowip=0.0.0.0/0
1147 | rpcbind=0.0.0.0
1148 | rpcport=$BTC_NODE_PORT
1149 | prune=20000
1150 | wallet=/data/.bitcoin/opencex
1151 |
1152 | EOF
1153 | docker compose up -d
1154 | sleep 30;
1155 | docker exec -it bitcoind bitcoin-cli -named createwallet wallet_name="opencex" descriptors=false
1156 | docker restart bitcoind
1157 | sleep 30;
1158 | docker exec -it opencex python wizard.py
1159 | cd /app/opencex || exit
1160 | docker compose stop
1161 | docker compose up -d
1162 |
1163 | ### Registration of the installation OpenCEX
1164 | curl --location 'http://alertbot.plgdev.com/registration' \
1165 | --header 'Content-Type: application/json' \
1166 | --data "{\"domain\": \"${DOMAIN}\"}"
1167 |
1168 |
1169 | # cleanup
1170 | # cd /app/opencex && docker compose down
1171 | # rm -rf /app
1172 | # docker system prune -a
1173 |
--------------------------------------------------------------------------------