Overview
Connection Details
GRVT's services are hosted in AWS Tokyo (ap-northeast-1
).
For close partners with high trading volumes, we offer AWS PrivateLink.
Authentication
GRVT supports API Authentication via session cookies, and API keys.
You may follow the below steps to authenticate your requests.
This section is conveniently inlined at every authenticated endpoint for your convenience.
Authentication
In order to authenticate, you must first provision a valid API key. API keys can be provisioned via the GRVT UI.
# These are the variables you will need to set manually
GRVT_API_KEY="<insert_key_here>"
GRVT_SUB_ACCOUNT_ID="<insert_sub_account_id_here>"
Then, choose the environment you want to authenticate against.
# dev
GRVT_AUTH_ENDPOINT="https://edge.dev.gravitymarkets.io/auth/api_key/login"
# stg
GRVT_AUTH_ENDPOINT="https://edge.stg.gravitymarkets.io/auth/api_key/login"
# testnet
GRVT_AUTH_ENDPOINT="https://edge.testnet.grvt.io/auth/api_key/login"
# prod
GRVT_AUTH_ENDPOINT="https://edge.grvt.io/auth/api_key/login"
Now, let's create a cookie that will be used to authenticate with our API Services.
echo $GRVT_API_KEY
echo $GRVT_SUB_ACCOUNT_ID
echo $GRVT_AUTH_ENDPOINT
GRVT_COOKIE=$(
curl $GRVT_AUTH_ENDPOINT \
-H 'Content-Type: application/json' \
-H 'Cookie: rm=true;' \
-d "{ \"api_key\": \"$GRVT_API_KEY\" }" \
-s -i \
| grep -i 'set-cookie:' \
| grep -o 'gravity=[^;]*'
);
echo $GRVT_COOKIE
Order Creation
Python SDK
We have a Python SDK available for usage. (link)
pip install grvt-pysdk
Step-by-Step Guide
For specific information on how to sign and create an order, here's a step-by-step guide, using our Python SDK:
- Step 8-1: Fetch All Instruments
- Step 8-2: Use Instrument Map in Order Signing
- Step 8-3: Create An Order
- Step 8-4: Sign Order
- Step 8-5: Submit The Order
Chain IDs
Network | Ethereum L1 Chain ID | GRVT L2 Chain ID |
---|---|---|
Sepolia (Dev) | 11155111 | 327 |
Sepolia (Stg) | 11155111 | 327 |
Sepolia (Testnet) | 11155111 | 326 |
Mainnet | 1 | 325 |
Encoding (Full vs Lite)
For more versatile usage, all our APIs and Websockets are offered in full
and lite
variants.
These variants are identical except for the JSON field_name
used:
- `full` uses the full field name, e.g. `order_id`
- `lite` uses the shortened field name, e.g. `oi`
This is allows for users to trade off between simplicity and performance.
WebSocket Subscription
Request
Websocket subscriptions are initiated by sending a JSON RPC Request to the server.
They have the following structure:
- stream: The stream to subscribe to
- feed: The list of feeds to subscribe to
- method: The JSONRPC method. This is always `"subscribe"`
- is_full: Whether to subscribe to the `full` or `lite` feed.
{
"stream":"v1.book.s",
"feed":["BTC_USDT_Perp@500-100-10"],
"method":"subscribe",
"is_full":true
}
Response
Upon subscribing, the server will respond with an initial JSON RPC Response.
In the successful case, the following response will be returned:
- stream: The stream that was subscribed to
- subs: The list of subscriptions that were successfully subscribed to
- unsubs: The list of subscriptions that were unsubscribed from
{
"stream":"v1.book.s",
"subs":["BTC_USDT_Perp@500-100-10"],
"unsubs":[]
}
In the case of an error, the following response will be returned:
- code: The error code
- message: The error message
- status: The HTTP status code
{
"code":3001,
"message":"Stream handler not found",
"status":400
}
Feed Structure
For each WebSocket stream, users may subscribe to multiple feeds. Each stream defines its own feed structure, which is documented on the relevant page. However, they all share the same underlying structure.
Firstly, feeds are broken down into primary@secondary
selector pairs.
- `primary` is used to determine the type of streaming data received.
- `secondary` is used to determine the format/subtype of the streaming data received.
When subscribing to the same primary
selector again, the previous secondary
selector will be replaced.
eg. If previously subcribing to "BTC_USDT_Perp@500-100-10"
and then subscribing to "BTC_USDT_Perp@500-1-10"
, the subscribe response will return.
{
"stream":"v1.book.s",
"subs":["BTC_USDT_Perp@500-1-10"],
"unsubs":["BTC_USDT_Perp@500-100-10"]
}
Within each primary
or secondary
selector, fields are separated by -
, and ordered by the schema definition.
Feed Data Stream
The feed data stream will return a continuous stream of JSON objects. It has the following structure:
- stream: The stream that the data is from
- selector: The selector that the data is from
- sequence_number: This increases by one for each feed object published in the `stream`/`selector` pair. If the number `jumps`, it indicates data loss.
- feed: The feed data object. Different for each stream.
{
"stream": "v1.book.s",
"selector": "BTC_USDT_Perp@500-100-10",
"sequence_number": "872634876",
"feed": {}
}
Event Time
All feed data is published with an event_time
timestamp (in unix nanoseconds).
This timestamp is stamped by our core cluster, and is guaranteed to be consistent across all services and nodes.
For All Streams, other than MiniTicker
raw streams, event time is a globally consistent unique identifier for a message.
ie. All connections via WebSocket/REST can agree that a message is the same via its event_time
.
Sequence Number
Sequence Numbers are stamped at the gateway level. Which means that it only has relevance within a single websocket connection, and nothing more.
It helps you to guarantee that you received the right number of snapshot
updates, and did not miss any delta
updates.
- All snapshot payloads will have a sequence number of `0`. All delta payloads will have a sequence number of `1+`. So its easy to distinguish between snapshots, and deltas
- Num snapshots returned in JSON RPC Response (per stream): You can ensure that you received the right number of snapshots
- First sequence number returned in JSON RPC Response (per stream): You can ensure that you received the first stream, without gaps from snapshots
- Sequence numbers should always monotonically increase by `1`. If it decreases, or increases by more than `1`. Please reconnect
- Duplicate sequence numbers are possible due to network retries. If you receive a duplicate, please ignore it, or idempotently re-update it.