The aim of this repository is to interact with FTX APIs to book orders (spot,future etc) and get market price.
Currently, this repository is mainly used for below cloud functions:
- conversion_request_place_order_api
- UpdatePriceHistory
- purge_old_market_price
-
This function place future order in
BYBIT
exchange and for stable coin (eg:USDC
,USDT
) additionally books spot order inFTX
exchange. -
This function is triggered when user makes a conversion request from front end and a corresponding document is added by another backend cloud function
conversion_request
to firestore tableconvert_history\{uid}\history\{assetType}
-
When a document is inserted into above firestore table, this function is auto triggered and an order is placed in bybit( and ftx) using external apis.
-
On successful creation of order, a sub-document is inserted under sub-collection
order
with order details returned from bybit (and ftx). eg:convert_history\{uid}\history\{assetType}\order\{id}\<details of order>
-
On failure, a subdocument is inserted under sub-scollection
order
with error details returned from bybit (and ftx). eg:convert_history\{uid}\history\{assetType}\order\{id}\<error message>
-
After order book request is done, the final
status
of firestore document is updated frompending
tosent
orerror
. eg:convert_history\{uid}\history\{assetType}\<{status = 'sent' or 'error'}>
-
There is pub/sub function
conversion_batch
which is auto triggered by scheduler jobconvert_trigger
and is scheduled to run daily around 9.10 AM JST. The pub/sub function looks for all the documents of this table having statussent
and do the conversion fromXYZ
toUSDS
orUSDS
toXYZ
and finally marks the document status fromsent
todone
-
This function currently used
FTX
api exchange as its default. -
This cloud function is a pub/sub function which is auto triggered by schedule job
update_market_price_trigger
and is schedule to run after each minute. -
When this function is triggered, it gets the prices of all target markets configured in runtime enviornment variable
TARGET_MARKETS
(eg; BTC-PERP|ETH-PERP) usingFTX
api and save the price in a new document of tableprice_histories
. -
This pre save/added price is used by front end conversion form/window for a given currency pair (eg: BTC-USD).
-
This cloud function is a pub/sub function which is auto triggered by schedule job
purge_old_market_price_trigger
and is schedule to run once daily at 2 AM JST time. -
This function auto purges/deletes all the old documents (older than 3 days) from
price_histories
table to avoid any future performance issue because of big size of table.
-
All API specific secrets have been added/uploaded to secret manager.
-
Because above cloud functions run under default service account
App Engine default service account
, all secret keys must be created under same account, otherwise you will have to grantSecret Manager Secret Accessor
role to another account -
Below are the scret keys currently used:
BYBIT_IS_TESTNET
:True
for non-production,False
for production.BYBIT_API_KEY
BYBIT_API_SECRET
FTX_API_KEY
FTX_API_SECRET
FTX_SUB_ACCOUNT
-
Notes:
-
for
conversion_request_place_order_api
function, if you plan to change Bybit's API KEYS, you need to set static ip address used by cloud function in your api keys management. (refer below section for more details) -
UpdatePriceHistory
function always usesFTX
exchange. (No static ip address is required)
-
-
conversion_request_place_order_api
no enviornment variables: -
UpdatePriceHistory
andpurge_old_market_price_trigger
use below enviornment variables:TARGET_MARKET
: Current production setting isBTC-PERP|ETH-PERP
-
This setup/configuration is required only for
conversion_request_place_order_api
function. The reason is, this function uses Bybit exchange which allows requests only from explicitly specified IP addresses and should be configured in Bybit API Key(s) in their portal. For FTX, there is no static ip required. -
As cloud function is a stateless service and doesn't have a static ip address. The idea is, first to route egress traffic from cloud function to VPC (Virtual private network) through VPC connector to adhere all the rules set on this VPC network and then setup Cloud NAT gateway with static ip address to give access to the function to connect to internet.
-
More details and explained steps can be found here: https://cloud.google.com/functions/docs/networking/network-settings#associate-static-ip
-
Below are the steps to follow:
- Route function's egress through VPC network
- Setup a VPC network
- This step can be omitted as we will be using soteria's
default
VPC network.
- This step can be omitted as we will be using soteria's
- Set up a Serverless VPC Access connector
- In google cloud, go to
Serverless VPC access
- Enable
Serverless VPC Access API
(if not enabled before) - Click on
CREATE CONNECTOR
- Name =
soteria-connector
- Region =
us-central1
(or anything) - Network =
default
(choose VPC network of that region, let it be default) - Subnet = Select
Custom IP range
and in IP range enter10.8.0.0
- Name =
- Let other values to be defaulted one and click on
CREATE
- In google cloud, go to
- Set up Cloud NAT and specify a static IP address
- In google cloud, go to
Cloud NAT
- Click on
CREATE NAT GATEWAY
- Name =
soteria-gateway
- VPC network=
default
- Region =
us-central1
(use same selected at the time of connector creation) - Cloud router = create a new router with name
soteria-router
- NAT Mapping/Source Internal = let
Primary and secondary ranges for all subnets
as default - NAT Mapping/NAT IP Address =
Manual
(Click on IP address, it will allow you to create a new static IP address, give the nameapi-static-ip
) - Finally click on
CREATE
- In google cloud, go to
- Setup a VPC network
- Route function's egress through VPC network
-
The static ip address created in last step has to be configured in Bybit API key. (Go to bybit portal and then
API
section and modify your key to add this ip address)
Make sure you have checked all steps mentioned in Configuration/Setup
section.
Set the project enviornment
gcloud auth login
gcloud config set project <project name of the environment you want to deploy to>
# Existing function
gcloud functions deploy conversion_request_place_order_api
# New function
gcloud functions deploy conversion_request_place_order_api --entry-point=place_order_api --runtime=python37 --trigger-event=providers/cloud.firestore/eventTypes/document.create --trigger-resource=projects/{project_id}/databases/(default)/documents/convert_history/{uid}/history/{assetType} --vpc-connector=soteria-connector --egress-settings=all
# Note:
## Replace {project_id} with stagging/production project id
## Make sure vpc-connector is created already.
# Existing function
gcloud functions deploy UpdatePriceHistory
# New function
gcloud functions deploy UpdatePriceHistory --entry-point=update_market_price --runtime=python37 --trigger-topic=update_market_price_topic --set-env-vars=TARGET_MARKETS="BTC-PERP|ETH-PERP"
# Note: Make sure topic and scheduler exists already
# Existing function
gcloud functions deploy purge_old_market_price
# New function
gcloud functions deploy purge_old_market_price --entry-point=purge_old_market_price --runtime=python37 --trigger-topic=purge_old_market_price_topic --set-env-vars=TARGET_MARKETS="BTC-PERP|ETH-PERP" --timeout=540s
# Note: Make sure topic and scheduler exists already