Introduction
In this guide, we will cover how to authenticate using JWT tokens and how to send a login request via WebSockets. This knowledge is easily transferable to many other API documentations across the web.
Quick Development Setup
For Windows users, we recommend either using Windows Subsystem for Linux (WSL) and setting up VScode on the Windows side, using a Linux virtual machine or downloading cmder to run the code.
For the rest of the blog, we assume you will be using MacOS, Linux or cmder on Windows.
- Create a new directory for the project, navigate into it and create a new Python file called
login.pyand akeys.pyfile to store your private keys and key IDs:
mkdir thalex_api
cd thalex_api
touch login.py
touch keys.py
- Set up a Python venv environment in the new directory, activate it, and install the required libraries
MacOS/Linux:
python -m venv .venv
source .venv/bin/activate
pip install websockets pyjwt time json asyncio
Windows (via cmder):
python -m venv .venv
.venv\Scripts\activate
pip install websockets pyjwt time json asyncio
Login Endpoint
From the public/login endpoint in the API docs, we see that the following are required/requested to login via WebSockets:
- A
methodparameter, and - The
paramsparameter containing a token. Specifically a JWT token (look at the payload request example to the right of the docs)
Let's see how to create this JWT token.
Authentication
If you search for JWT using ctrl+f in the API docs, we find the Authentication section which describes the parameters needed for the JWT token:
- An encryption
algorithmofRS512or any of the other choices listed, - A key id
kidheader containing your key ID, - An
iat(issued at) containing the current time as a unix timestamp, and - The token signed with your private key.
Private Key and Key ID
First we add the following template code in our keys.py file:
private_keys = {
'TESTNET': """-----BEGIN RSA PRIVATE KEY-----
...replace_with_your_testnet_private_key...
-----END RSA PRIVATE KEY-----
""",
'PROD': """-----BEGIN RSA PRIVATE KEY-----
...replace_with_your_prod_private_key...
-----END RSA PRIVATE KEY-----
""",
}
key_ids = {'TESTNET': "K123456789", 'PROD': "K123456789"}
Then we get the private key and key ID from our testnet or production account by creating an API key with trading permissions.
Replace these values in the keys.py file accordingly.
Creating the JWT Token
Recall that the JWT token requires:
- An encryption
algorithmofRS512, - A key id
kidheader containing your key ID, - An
iat(issued at) containing the current time as a unix timestamp, and - The token signed with your private key
We've already replaced the private key and key ID in the keys.py file but now we need to import this file, the jwt and time libraries and define our key_id and private_key variables in the login.py file:
import keys
import jwt
import time
key_id = keys.key_ids['TESTNET'] # or 'PROD' for production
private_key = keys.private_keys['TESTNET'] # or 'PROD' for production
Then to create the token:
token = jwt.encode(
{"iat": time.time()},
private_key,
algorithm="RS512",
headers={"kid": key_id}
)
Connecting
WebSockets Connection
Now that we've created the JWT token variable, we can connect to the WebSockets API as a client and send the login request to Thalex.
The WebSockets API requires a connection to wss://<api_endpoint>.thalex.com/ws/api/v2. For testnet, we use wss://testnet.thalex.com/ws/api/v2 and for production, we use wss://thalex.com/ws/api/v2.
So let's create a variable for testnet and production (or just one of them if you prefer):
Network = {
"TEST": "wss://testnet.thalex.com/ws/api/v2",
"PROD": "wss://thalex.com/ws/api/v2",
}
We can now send the login request with our JWT token. We import the libraries: websockets, json to handle the json response and asyncio to handle the asynchronous connections.
import websockets
import json
import asyncio
async with websockets.connect(Network["TEST"]) as ws:
await ws.send(
json.dumps(
{
"method": "public/login",
"params": {"token": token}
}
)
)
print(await ws.recv())
Main Function
Now we put it all together inside a function called main since we want to run it easily with one function call:
async def main():
token = jwt.encode(
{"iat": time.time()},
private_key,
algorithm="RS512",
headers={"kid": key_id}
)
async with websockets.connect(Network["TEST"]) as ws:
await ws.send(
json.dumps(
{
"method": "public/login",
"params": {"token": token}
}
)
)
print(await ws.recv())
asyncio.run(main())
The End Result
To put everything together, here is the complete code to login via websockets using JWT authentication.
import asyncio
import json
import time
import jwt
import websockets
import keys
Network = {
"TEST": "wss://testnet.thalex.com/ws/api/v2",
"PROD": "wss://thalex.com/ws/api/v2",
}
key_id = keys.key_ids["TEST"]
private_key = keys.private_keys["TEST"]
async def main():
token = jwt.encode(
{"iat": time.time()},
private_key,
algorithm="RS512",
headers={"kid": key_id}
)
async with websockets.connect(Network["TEST"]) as ws:
await ws.send(
json.dumps(
{
"method": "public/login",
"params": {"token": token}
}
)
)
print(await ws.recv())
asyncio.run(main())
When you run this code, you should see a successful login response from the server in the form of:
"id":null,"result":{"account_number":"A123456789"}}
With this knowledge, you can now explore the other API endpoints in the API docs and start getting market data or building your own trading bots on Thalex!
Disclaimer
Thalex may provide you with certain educational and software tools that you may use for your benefit, at your own risk, and for your own account. Thalex disclaims any responsibility for the use, reliance or utilization of the software, and you agree without limitation to hold Thalex harmless and wholly indemnified of your conscious use of the software, for whatever purposes you may have, related or unrelated with the activities on Thalex or any other service provider that caters for the use of the software, or similar software. Use of the software presupposes acceptance of these conditionals.
