ResilientDB GraphQL Server
(If you're using this for the first time, the steps below would be useful)
Install Ubuntu 20.04 on your local machine.
Once installed, go to File Explorer -> Linux -> Ubuntu 20.04.
Clone this repository.
Install python3 (version - 3.9+) and ensure pip is installed using the command.
sudo apt-get install python3-pip
Also make sure to install the venv module which creates a virtual Python environment that helps encapsulate the project's dependencies and prevents possible conflicts with the global Python environment. The command is:
sudo apt-get install -y python3.10-venv
Create a virtual environment:
python3 -m venv venv
Start a virtual environment:
source venv/bin/activate
Go back from the virtual environment when you no longer need it:
deactivate
To use the SDK, you need to start a KV service first, which you can refer to the resilientdb repository and the blog.
Then you should start the crow http service, which may take a few minutes at the first time.
bazel build service/http_server:crow_service_main
bazel-bin/service/http_server/crow_service_main service/tools/config/interface/service.config service/http_server/server_config.config
After starting the crow service, you can optionally test it by using the curl command to send HTTP requests.
curl -X POST -d '{"id":"key1","value":"value1"}' 127.0.0.1:18000/v1/transactions/commit
curl 127.0.0.1:18000/v1/transactions/key1
The expected output of the two commands above are: id: key1
and {"id":"key1","value":"value1"}
, respectively.
Start your virtual environment.
source venv/bin/activate
Run the requirements.txt command to install the SDK related dependencies.
pip3 install -r requirements.txt
Try the test script.
python3 test_sdk.py
You have successfully run the script if you see the output: The retrieved txn is successfully validated
(Optional) If there is an error while running any command relating to NexRes, this command below may help:
sudo apt-get install python3.10-distutils
Note: If there is an error with the pip version, use the command:
curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10
Open a venv in the Ubuntu server and run the command:
source venv/bin/activate
sudo apt-get install cloud-init
Install the remaining dependencies in venv
python3 -m pip install strawberry-graphql
python3 -m pip install flask_cors
BUG FIX: in the case requirements.txt doesn't work, and the cloud-init
version is not found, edit the file to be:
aiohttp==3.8.3
aiohttp-cors==0.7.0
aiosignal==1.3.1
anyio==3.6.2
ariadne==0.17.0
async-timeout==4.0.2
attrs==22.2.0
base58==2.1.0
certifi==2022.12.7
cffi==1.15.1
charset-normalizer==2.1.1
click==8.1.3
commonmark==0.9.1
cryptoconditions==0.8.1
cryptography==3.4.7
Flask==2.2.2
Flask-Cors==3.0.10
frozenlist==1.3.3
graphql-core==3.2.3
h11==0.14.0
idna==3.4
importlib-metadata==5.2.0
itsdangerous==2.1.2
Jinja2==3.1.2
libcst==0.4.9
MarkupSafe==2.1.1
multidict==6.0.4
mypy-extensions==0.4.3
pyasn1==0.4.8
pycparser==2.21
Pygments==2.14.0
PyNaCl==1.4.0
pysha3==1.0.2
python-dateutil==2.8.2
python-multipart==0.0.5
python-rapidjson==1.8
PyYAML==6.0
requests==2.28.1
rich==13.0.1
six==1.16.0
sniffio==1.3.0
starlette==0.23.1
strawberry-graphql==0.152.0
typing-inspect==0.8.0
typing_extensions==4.4.0
urllib3==1.26.13
uvicorn==0.20.0
Werkzeug==2.2.2
yarl==1.8.2
zipp==3.11.0
- You may get an error that says
Running setup.py install for <dependency> did not run successfully.
- First, try
pip3 install wheel
orpip install wheel
- Next, install all missing dependencies manually
- NOTE as long as you still have dependencies to install, you will get an error message, but this is okay!
- From the stack trace, identify the module, then use
pip install <dependency>
- keep generating errors by running
python3 app.py
every time, and resolve each missing dependency
- Ex:
Traceback (most recent call last):
File "/home/user/repos/NexresGraphQL/app.py", line 1, in <module>
from resdb_driver import Resdb
File "/home/user/repos/NexresGraphQL/resdb_driver/__init__.py", line 1, in <module>
from .driver import Resdb
File "/home/user/repos/NexresGraphQL/resdb_driver/driver.py", line 4, in <module>
from .offchain import prepare_transaction, fulfill_transaction
File "/home/user/repos/NexresGraphQL/resdb_driver/offchain.py", line 8, in <module>
from .transaction import Input, Transaction, TransactionLink, _fulfillment_from_details
File "/home/user/repos/NexresGraphQL/resdb_driver/transaction.py", line 14, in <module>
import base58
ModuleNotFoundError: No module named 'base58'
- In the last line, you can run
pip install base58
- Keep running
python3 app.py
until you get to the broken dependency (ex: pysha3, sha3), then try runningsudo apt-get install python3.10-dev
- Hopefully, all your dependencies should be installed, and running
python3 app.py
will run the server!
Start the app using:
python3 app.py
This would be hosted on your local server to test the React App/Frontend. Also, this would give info on the console about the POST command, which are used to create an account. This consists of 3 stages: publicKey. AES encrypted private key and decrypted privateKey
Note: To run Ubuntu virtual instance, open Command Prompt, then type ubuntu2004
to open an instance
Install the Nginx web server package:
sudo apt-get install nginx -y
Once the Nginx is installed, start and enable the Nginx service using the following command:
systemctl start nginx
systemctl enable nginx
Activate your virtual environment and install Gunicorn and Flask:
source venv/bin/activate
pip install wheel
pip install gunicorn flask
Verify whether Gunicorn can serve the application correctly using the command below:
gunicorn --bind 0.0.0.0:5000 wsgi:app
If everything is fine, you should get the following output:
[2023-10-06 22:28:11 +0000] [24074] [INFO] Starting gunicorn 21.2.0
[2023-10-06 22:28:11 +0000] [24074] [INFO] Listening at: http://0.0.0.0:5000 (24074)
[2023-10-06 22:28:11 +0000] [24074] [INFO] Using worker: sync
[2023-10-06 22:28:11 +0000] [24075] [INFO] Booting worker with pid: 24075
Press CTRL+C to stop the application. And deactivate the virtual environment.
deactivate
Next, you will need to create a systemd unit file for the Flask application:
sudo vim /etc/systemd/system/flask.service
Add the following lines:
[Unit]
Description=Gunicorn instance to serve Flask
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=\{Your Absolute Path to this Folder\}
Environment="PATH=\{Your Absolute Path to this Folder\}/venv/bin"
ExecStart=\{Your Absolute Path to this Folder\}/venv/bin/gunicorn --bind 0.0.0.0:8000 wsgi:app
[Install]
WantedBy=multi-user.target
Next, reload the systemd daemon with the following command:
sudo systemctl daemon-reload
Next, start the flask service and enable it to start at system reboot:
sudo systemctl start flask
sudo systemctl enable flask
Next, verify the status of the flask with the following command:
sudo systemctl status flask
Output:
● flask.service - Gunicorn instance to serve Flask
Loaded: loaded (/etc/systemd/system/flask.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-10-06 22:20:00 UTC; 14min ago
Main PID: 23745 (gunicorn)
Tasks: 2 (limit: 38067)
Memory: 40.6M
CGroup: /system.slice/flask.service
├─23745 /home/ubuntu/ResilientDB-GraphQL/venv/bin/python3 /home/ubuntu/ResilientDB-GraphQL/venv/b>
└─23747 /home/ubuntu/ResilientDB-GraphQL/venv/bin/python3 /home/ubuntu/ResilientDB-GraphQL/venv/b>
Next, you will need to configure Nginx as a reverse proxy to serve the Flask application through port 80. To do so, create an Nginx virtual host configuration file:
sudo vim /etc/nginx/conf.d/flask.conf
Add the following lines:
server {
listen 80;
server_name {The public IP address of your machine};
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Save and close the file then verify the Nginx for any syntax error:
sudo nginx -t
You should see the following output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Finally, restart the Nginx service to apply the changes:
sudo systemctl restart nginx
Then, test with:
{The public IP address of your machine}/graphql