General
These docs describe the v3 API for the dYdX decentralized perpetual contracts exchange. The exchange runs on an L2 (layer-2) blockchain system, and operates independently of previous dYdX protocols and systems, including the v1 and v2 APIs.
Like the previous iteration of dYdX perpetuals, the exchange uses a centralized order book, but remains non-custodial, and settles trades and liquidations in a trustless manner.
Layer 2: ZK-Rollups
Trades are settled in an L2 (layer-2) system, which publishes ZK (zero-knowledge) proofs periodically to an Ethereum smart contract in order to prove that state transitions within L2 are valid. Funds must be deposited to the Ethereum smart contract before they can be used to trade on dYdX.
By settling trades on L2, the exchange is able to offer much higher trade throughput and lower minimum order sizes, compared with systems settling trades directly on Ethereum (i.e. L1). This is achieved while maintaining decentralization, and the exchange is fully non-custodial.
The L2 system was developed with, and is operated jointly with, Starkware. More information about the L2 design can be found in Starkware's documentation. (Note: Some of the details described there may be specific to Starkware's previous StarkEx system and may not apply to the dYdX system.)
Data Centers
Our data centers are located in the Amazon us-east-1 region (Northern Virginia).
Number Formats
All amounts and prices in the clients and API are represented in “human readable,” natural units. For example, an amount of 1.25 ETH is represented as 1.25
, and a price of $31,000.50 per BTC is represented as 31000.5
.
This differs from the dYdX v1 and v2 APIs which represented amounts and prices in terms of base token units.
Base URLs
Base URLs for API endpoints are as follows:
- Production:
https://api.dydx.exchange
- Staging (Ropsten):
https://api.stage.dydx.exchange
Perpetual Contracts
The dYdX Perpetual is a non-custodial, decentralized margin product that offers synthetic exposure to a variety of assets.
Margin
Collateral is held as USDC, and the quote asset for all perpetual markets is USDC. Cross-margining is used by default, meaning an account can open multiple positions that share the same collateral. Isolated margin can be achieved by creating separate accounts (sub-accounts) under the same user.
Each market has two risk parameters, the initial margin fraction and the maintenance margin fraction, which determine the max leverage available within that market. These are used to calculate the value that must be held by an account in order to open or increase positions (in the case of initial margin) or avoid liquidation (in the case of maintenance margin).
Portfolio Margining
There is no distinction between realized and unrealized PnL for the purposes of margin calculations. Gains from one position will offset losses from another position within the same account, regardless of whether the profitable position is closed.
Margin Calculation
The margin requirement for a single position is calculated as follows:
Initial Margin Requirement = abs(S × P × I) Maintenance Margin Requirement = abs(S × P × M)
Where:
S
is the size of the position (positive if long, negative if short)P
is the oracle price for the marketI
is the initial margin fraction for the marketM
is the maintenance margin fraction for the market
The margin requirement for the account as a whole is the sum of the margin requirement over each market i
in which the account holds a position:
Total Initial Margin Requirement = Σ abs(Si × Pi × Ii) Total Maintenance Margin Requirement = Σ abs(Si × Pi × Mi)
The total margin requirement is compared against the total value of the account, which incorporates the quote asset (USDC) balance of the account as well as the value of the positions held by the account:
Total Account Value = Q + Σ (Si × Pi)
The Total Account Value is also referred to as equity.
Where:
Q
is the account's USDC balance (note thatQ
may be negative)S
andP
are as defined above (note thatS
may be negative)
An account cannot open new positions or increase the size of existing positions if it would lead the total account value of the account to drop below the total initial margin requirement. If the total account value ever falls below the total maintenance margin requirement, the account may be liquidated.
Free collateral is calculated as:
Free collateral = Total Account Value - Total Initial Margin Requirement
Equity and free collateral can be tracked over time using the latest oracle price (obtained from the markets websocket).
Liquidations
Accounts whose total value falls below the maintenance margin requirement (described above) may have their positions automatically closed by the liquidation engine. Positions are closed at the liquidation price described below. Profits or losses from liquidations are taken on by the insurance fund.
Liquidation Price
The liquidation price of a position is calculated as follows, depending on whether it is a short or long position:
Liquidation Price (short) = P × (1 + M × V) Liquidation Price (long) = P × (1 − M × V)
Where:
P
is the oracle price for the marketM
is the maintenance margin fraction for the marketV
is the total account value, as defined above
This formula is chosen such that the ratio Total Account Value / Total Maintenance Margin Requirement
is unchanged as individual positions are liquidated.
Funding
Funding payments are exchanged between long and short traders to encourage the price of a perpetual contract to trade close to the price of the underlying. If the perpetual trades at a premium relative to the index, long traders will typically make payments to short traders, whereas if the perpetual trades at a discount relative to the index, short traders will typically make payments to long traders.
The payments are credited or debited at the start of each hour, and are included in the realized PnL for the position.
Funding payments can be found by calling Get /v3/funding and the predicted funding rate can be found by calling Get v3/markets.
Funding Rate Units
Since funding payments are exchanged every hour, the dYdX funding rate is usually represented as a 1-hour rate, which represents the return a position may expect to earn or pay every hour.
When calculating the funding rate, the premium is scaled to have a realization period of 8 hours. That means, for example, that if a certain perpetual market trades consistently at a 0.1% premium relative to the underlying, long traders may expect to pay ~0.1% every 8 hours, and short traders may expect to earn a ~0.1% return every 8 hours (not accounting for the interest rate component).
Funding Payment Calculation
At the start of each hour, an account receives USDC (if F
is positive) or pays USDC (if F
is negative) in an amount equal to:
F = (-1) × S × P × R
Where:
S
is the size of the position (positive if long, negative if short)P
is the oracle price for the marketR
is the funding rate (as a 1-hour rate)
Funding Rate Calculation
The main component of the funding rate is a premium that takes into account market activity for the perpetual. It is calculated for each market, every minute (at a random point within the minute) using the formula:
Premium = (Max(0, Impact Bid Price - Index Price) - Max(0, Index Price - Impact Ask Price)) / Index Price
Where the impact bid and impact ask prices are defined as:
Impact Bid Price = Average execution price for a market sell of the impact notional value Impact Ask Price = Average execution price for a market buy of the impact notional value
And the impact notional amount for a market is:
Impact Notional Amount = 500 USDC / Initial Margin Fraction
For example, for a market with a 10% initial margin fraction, the impact notional value is 5,000 USDC.
At the end of each hour, the premium component is calculated as the simple average (i.e. TWAP) of the 60 premiums calculated over the course of the last hour. In addition to the premium component, each market has a fixed interest rate component that aims to account for the difference in interest rates of the base and quote currencies. The funding rate is then:
Funding Rate = (Premium Component / 8) + Interest Rate Component
Currently, the interest rate component for all dYdX markets is 0.0000125%
(equivalent to 0.0001%
per 8 hours).
Contract Loss Mechanisms
During periods of high volatility in the markets underlying the perpetual contracts, the value of some accounts may drop below zero before they can be liquidated.
The insurance fund is the first backstop to maintain the solvency of the system when an account has a negative balance. The account will be liquidated, and the insurance fund will take on the loss.
In the event that the insurance fund is depleted, positions with the most profit and leverage may be used to offset negative-balance accounts, in order to maintain the stability of the system.
Clients
Python and TypeScript clients are available, allowing programmatic usage of dYdX.
Python Client
Installation
Install dydx-v3-python
from PyPI using pip
:
pip install dydx-v3-python
API
See dydxprotocol/dydx-v3-python.
TypeScript Client
Installation
Install @dydxprotocol/v3-client
from NPM:
npm i -s @dydxprotocol/v3-client
API
Client Initialization
Initialize
client = Client(
host='https://api.dydx.exchange',
web3=Web3('...'),
stark_private_key='01234abcd...',
)
const client: DydxClient = new Client(
'host',
{
apiTimeout: 3000,
starkPrivateKey: '01234abcd...',
},
);
The client is organized into modules, based on the type of authentication needed for different requests. The configuration options passed into the client determine which modules are available. See Authentication for more information.
Module | Description |
---|---|
public | Public API endpoints. Does not require authentication. |
onboarding | Endpoint to create a new user, authenticated via Ethereum key. |
api_keys | Endpoints for managing API keys, authenticated via Ethereum key. |
private | All other private endpoints, authenticated via API key. |
eth | Calling and querying L1 Ethereum smart contracts. |
The following configuration options are available:
Parameter | Description |
---|---|
host | The HTTP API host. |
api_timeout | Timeout for HTTP requests, in milliseconds. |
default_ethereum_address | (Optional) The default account for Ethereum key auth and sending Ethereum transactions. |
eth_private_key | (Optional) May be used for Ethereum key auth. |
eth_send_options | (Optional) Options for Ethereum transactions, see sendTransaction . |
network_id | (Optional) Chain ID for Ethereum key auth and smart contract addresses. Defaults to web3.net.version if available, or 1 (mainnet). |
stark_private_key | (Optional) STARK private key, used to sign orders and withdrawals. |
web3 | (Optional) Web3 object used for Ethereum key auth and/or smart contract interactions. |
web3_account | (Optional) May be used for Ethereum key auth. |
web3_provider | (Optional) Web3 provider object, same usage as web3 . |
api_key_credentials | (Optional) Dictionary containing the key, secret and passphrase required for the private module to sign requests. |
crypto_c_exports_path | (Optional) For python only, will use faster C++ code to run hashing, signing and verifying. It's expected to be compiled from the crypto_c_exports target from Starkware's repository. See section on this below for more information. |
C++ Methods for Faster STARK Signing
The C++ wrapper methods in the client expect an absolute path to a Shared Object. This has to be compiled from Starkware's crypto C++ library.
Private HTTP API
Authentication
There are three levels of authentication to be considered when using dYdX. All signing can be handled directly by the client libraries.
Ethereum Key Authentication
The highest level of authentication is via an account's Ethereum private key. The Ethereum key remains in control of an account's funds while they are within the L2 system. This includes the ability to forcibly close an account's positions and exit the system, in the event that the L2 operators (dYdX and Starkware) were to unexpectedly go offline or otherwise censor requests.
Ethereum key authentication is required for the following operations:
- Register a new user or STARK key
- Create or revoke API keys
- Request a forced withdrawal or forced trade
STARK Key Authentication
Within the L2 system, authentication is handled by a separate key pair, known as the account's STARK key pair.
STARK key authentication is required for the following operations:
- Place an order
- Withdraw funds
API Key Authentication
The third level of authentication consists of the API key, secret and passphrase which are used solely to authenticate API requests made to dYdX. This includes operations such as canceling orders or retrieving an account's fills, which do not affect the L2 system.
When a user onboards via POST v3/onboarding
, the server will use the signature as a seed to determinstically generate default API key credentials. An API key includes three fields:
key
: UUID identifying the credentials.secret
: Secret string used to generate HMACs, not sent with requests.passphrase
: Secret string sent with each request, used to encrypt/decrypt the secret in our DB, and never stored in our DB.
API keys can be added and managed via the /v3/api-keys
endpoints.
All requests which are not signed by an Ethereum key and which are made to private endpoints require an API key signature.
STARK Key Cryptography
The STARK and API keys are ECDSA key pairs on the STARK curve. More info on the cryptography used on L2 is available in Starkware's documentation.
Creating and Signing Requests
Within the private HTTP API, there are three groups of endpoints which each require different headers and authentication.
(Separately, and in addition to the above, STARK signatures are required for orders and withdrawals. For details, please refer to the Python and TypeScript reference implementations.)
Onboarding Endpoint: POST v3/onboarding
Request Headers
Header | Required? | Description |
---|---|---|
DYDX-SIGNATURE | yes | Ethereum key authentication |
DYDX-ETHEREUM-ADDRESS | yes | Ethereum address of the user |
Signing
The header DYDX-SIGNATURE
is an EIP-712 Ethereum signature on a static message containing the fields:
action
: The stringDYDX-ONBOARDING
.onlySignOn
: The stringhttps://trade.dydx.exchange
.
See reference implementations: [Python] [TypeScript]
Ethereum Key Private Endpoints
This group includes the POST
and DELETE
v3/api-keys
endpoints for managing API keys. Like the onboarding endpoint, requests to these endpoints require signatures by the user's Ethereum key.
Request Headers
Header | Required? | Description |
---|---|---|
DYDX-SIGNATURE | yes | Ethereum key authentication |
DYDX-ETHEREUM-ADDRESS | yes | Ethereum address of the user |
DYDX-TIMESTAMP | yes | ISO timestamp of when the request was signed. Must be within 30 seconds of the server time. |
Signing
The header DYDX-SIGNATURE
is an EIP-712-compliant Ethereum signature on a message containing the fields:
method
: The name of the HTTP method used, uppercase (e.g.GET
).requestPath
: The API endpoint path, beginning with/v3/
.body
: The HTTP request body (normally empty forGET
andDELETE
).timestamp
: Equal to the headerDYDX-TIMESTAMP
.
See reference implementations: [Python] [TypeScript]
API Key Private Endpoints
All private endpoints not listed above fall in this category, and must be authenticated via an API key.
Request Headers
Header | Required? | Description |
---|---|---|
DYDX-SIGNATURE | yes | HMAC of the request |
DYDX-ETHEREUM-ADDRESS | yes | Ethereum address of the user |
DYDX-TIMESTAMP | yes | ISO timestamp of when the request was signed. Must be within 30 seconds of the server time. |
DYDX-PASSPHRASE | yes | The passphrase field of the API key. |
DYDX-ACCOUNT-NUMBER | no | Account number used to scope the request. Defaults to zero. |
Signing
The DYDX-SIGNATURE
is a SHA-256 HMAC produced as described below, and encoded as a Base64
string.
A SHA-256 HMAC is created using the API key secret
and the message timestamp + method + requestPath + body
defined as follows:
timestamp
: TheDYDX-TIMESTAMP
header, which must be within 30 seconds of the server time.method
: The name of the HTTP method used, uppercase (e.g.GET
).requestPath
: The API endpoint path, beginning with/v3/
.body
: The HTTP request body (normally empty forGET
andDELETE
).
The HMAC should be encoded as a Base64 string and sent as the DYDX-SIGNATURE
header.
See reference implementations: [Python] [TypeScript]
Rate Limits
If more than 100 requests are made in 10 seconds, requests will be blocked for one minute. Please make use of the WebSockets API if you need real-time data.
Onboarding
Overview
A few steps are required of all accounts before they can begin trading:
- Create a user, providing a STARK public key to be associated with the main account.
- Request registration signature from dYdX.
- Send registration request to the L1 smart contract.
- Approve collateral token allowance on the L1 smart contract.
- Deposit collateral token to the L1 smart contract.
All of these steps are supported by the Python and TypeScript clients. See the Python integration tests for an example of onboarding and usage of various endpoints.
Create User
onboarding_information = client.onboarding.create_user(
# Optional if stark_private_key was provided.
stark_public_key='012340bcd...',
stark_public_key_y_coordinate='01234abcd...',
# Optional if eth_private_key or web3.eth.defaultAccount was provided.
ethereum_address='ethereumAddress',
)
const onboardingInformation: {
apiKey: ApiKeyCredentials,
user: UserResponseObject,
account: AccountResponseObject,
} = await client.onboarding.createUser(
{
starkKey: '71234abcd...',
starkKeyYCoordinate: '01234abcd...',
},
ethereumAddress: 'ethereumAddress',
);
{
"apiKey": {
"key": "290decd9-548b-62a8-d603-45a988386fc8",
"passphrase": "S6a8lUhACPY2L5MWDvPl",
"secret": "KQ3s2VSLYqjWA0WpiDhvyEumvJVIQAj2Ni-TFg7z"
},
"user": {
"ethereumAddress": "0x0913017c740260fea4b2c62828a4008ca8b0d6e4",
"isRegistered": true,
"email": "[email protected]",
"username": "supersam15o",
"referredByAffiliateLink": null,
"makerFeeRate": "0.01",
"takerFeeRate": "0.01",
"makerVolume30D": "1000.00",
"takerVolume30D": "1000.00",
"fees30D": "00.50",
"userData": {}
},
"account": {
"starkKey": "180913017c740260fea4b2c62828a4008ca8b0d6e4",
"positionId": "1812",
"equity": "10000",
"freeCollateral": "10000",
"quoteBalance": "10000",
"pendingDeposits": "0",
"pendingWithdrawals": "0",
"openPositions": {
"BTC-USD": {
"market": "BTC-USD",
"status": "OPEN",
"side": "LONG",
"size": "1000",
"maxSize": "1050",
"entryPrice": "100",
"exitPrice": null,
"unrealizedPnl": "50",
"realizedPnl": "100",
"createdAt": "2021-01-04T23:44:59.690Z",
"closedAt": null,
"netFunding": "500"
}
},
"accountNumber": "5",
"id": "id"
}
}
HTTP Request
POST v3/onboarding
Description: Onboard a user so they can begin using dYdX V3 API. This will generate a user, account and derive a key, passphrase and secret from the signature.
Request
Parameter | Description |
---|---|
starkKey | Public starkKey associated with the key-pair you created. |
starkKeyYCoordinate | Public starkKey Y-Coordinate associated with the key-pair you created. |
ethereumAddress | Ethereum address associated with the user being created. |
referredByAffiliateLink | (Optional) Link to affiliate the user was referred by. |
Response
Parameter | Description |
---|---|
apiKey | See ApiKeyCredentials. |
user | See User. |
account | See Account. |
Derive StarkKey
Derive StarkKey
key_pair_with_y_coordinate = client.onboarding.derive_stark_key(
# Optional if eth_private_key or web3.eth.defaultAccount was provided.
ethereum_address='ethereumAddress',
)
const keyPairWithYCoordinate: KeyPairWithYCoordinate = await client.onboarding.deriveStarkKey(
'ethereumAddress',
);
Request
Parameter | Description |
---|---|
ethereumAddress | Ethereum address associated with the user being created. |
Response
Parameter | Description |
---|---|
keyPairWithYCoordinate | KeyPairWithYCoordinate. |
KeyPairWithYCoordinate
field | type | description |
---|---|---|
publicKey | string | The x-coordinate of the publicKey. |
publicKeyYCoordinate | string | The y-coordinate of the publicKey. |
privateKey | string | The privateKey for the key pair. |
Recover Default API Credentials
Recover Default API Credentials
api_credentials = client.onboarding.recover_default_api_key_credentials(
# Optional if eth_private_key or web3.eth.defaultAccount was provided.
ethereum_address='ethereumAddress',
)
const apiCredentials: ApiKeyCredentials = await client.onboarding.recoverDefaultApiCredentials(
'ethereumAddress',
);
Request
Parameter | Description |
---|---|
ethereumAddress | Ethereum address associated with the user being created. |
Response
Parameter | Description |
---|---|
apiCredentials | ApiKeyCredentials. |
ApiKeyCredentials
field | type | description |
---|---|---|
key | string | UUID identifying the credentials. |
secret | string | Secret string used to generate HMACs. |
passphrase | string | Secret string sent with each request. |
Get Registration
Get Registration
signature = client.private.get_registration()
const signature: { signature: string } = await client.private.getRegistration();
{
"signature": "foo"
}
HTTP Request
GET v3/registration
Description: Gets the dYdX provided Ethereum signature required to send a registration transaction to the Starkware smart contract.
Response
Parameter | Description |
---|---|
signature | Ethereum signature authorizing the user's Ethereum address to register for the corresponding position id. |
Register API Key
Register API Key
api_key_response = client.api_keys.create_api_key(
# Optional if eth_private_key or web3.eth.defaultAccount was provided.
ethereum_address='0x0123...',
)
const apiKey: { apiKey: ApiKeyCredentials } = await client.apiKeys.createApiKey(
'0x0123...',
);
{
"apiKey": {
"key": "290decd9-548b-62a8-d603-45a988386fc8",
"passphrase": "S6a8lUhACPY2L5MWDvPl",
"secret": "KQ3s2VSLYqjWA0WpiDhvyEumvJVIQAj2Ni-TFg7z"
}
}
HTTP Request
POST v3/api-keys
Description: Create new API key credentials for a user.
Response
Parameter | Description |
---|---|
apiKey | ApiKeyCredentials. |
Get API Keys
Get API Keys
api_keys = client.private.get_api_keys()
const apiKeys: { keys: string[] } = await client.private.getApiKeys();
{
"apiKeys": [
"290decd9-548b-62a8-d603-45a988386fc8",
"390decd9-548b-62a8-d603-45a988386fc8",
...
]
}
HTTP Request
GET v3/api-keys
Description: Get all api keys associated with an Ethereum address.
Response
Parameter | Description |
---|---|
apiKeys | Array of apiKey strings corresponding to the ethereumAddress in the request. |
Delete API Key
Delete API Key
client.api_keys.delete_api_key(
api_public_key='290decd9-548b-...',
# Optional if eth_private_key or web3.eth.defaultAccount was provided.
ethereum_address='0x0123...',
)
await client.apiKeys.delete_api_key(
'290decd9-548b-...', // API key
'0x0123...', // Ethereum address
);
{
"apiKey": "foo"
}
HTTP Request
DELETE v3/api-keys
Description: Delete an api key by key and Ethereum address.
Request
Parameter | Description |
---|---|
apiKey | Public api key being deleted. |
ethereumAdddress | Ethereum address the api key is associated with. |
Response
Returns a 200 on success.
Get User
Get User
user = client.private.get_user()
const user: { user: UserResponseObject } = await client.private.getUser();
{
"user": {
"ethereumAddress": "0x0913017c740260fea4b2c62828a4008ca8b0d6e4",
"isRegistered": true,
"email": "[email protected]",
"username": "supersam15o",
"referredByAffiliateLink": null,
"makerFeeRate": "0.01",
"takerFeeRate": "0.01",
"makerVolume30D": "1000.00",
"takerVolume30D": "1000.00",
"fees30D": "00.50",
"userData": {}
}
}
HTTP Request
GET v3/users
Description: return the user and user information.
Response
Parameter | Description |
---|---|
ethereumAddress | The 20-byte Ethereum address. |
isRegistered | True if the user is registered on the starkware smart contract. This is false otherwise. |
Email address. | |
username | User defined username. |
referredByAffiliateLink | The affiliate link that referred this user, or null if the user was not referred. |
makerFeeRate | The fee rate the user would be willing to take as the maker. Note, 1% would be represented as 0.01. |
takerFeeRate | The fee rate the user would be willing to take as the taker. Note, 1% would be represented as 0.01. |
makerVolume30D | The user's thirty day maker volume. Note, this is in USD (eg $12.34 -> 12.34). |
takerVolume30D | The user's thirty day maker volume. Note, this is in USD (eg $12.34 -> 12.34). |
fees30D | The user's thirty day fees. Note, this is in USD (eg $12.34 -> 12.34). |
userData | The user's unstructured user data. |
Update User
Update user
user = client.private.update_user(
user_data={},
email='[email protected]',
username='username',
)
const user: { user: UserResponseObject } = await client.private.updateUser({
email: '[email protected]',
username: 'username',
userData: {},
});
{
"user": {
"ethereumAddress": "0x0913017c740260fea4b2c62828a4008ca8b0d6e4",
"isRegistered": true,
"email": "[email protected]",
"username": "supersam15o",
"referredByAffiliateLink": null,
"makerFeeRate": "0.01",
"takerFeeRate": "0.01",
"makerVolume30D": "1000.00",
"takerVolume30D": "1000.00",
"fees30D": "00.50",
"userData": {}
}
}
HTTP Request
PUT v3/users
Description: Update user information and return the updated user.
Parameter | Description |
---|---|
userData | User metadata in a JSON blob. |
(Optional) Email to be used with the user. | |
username | (Optional) Username to be used for the user. |
Response
Parameter | Description |
---|---|
user | See User. |
Create An Account
Create Account
client.private.create_account(
stark_public_key='701234abcd...',
stark_public_key_y_coordinate='1234abcd...',
)
const account: { account: AccountResponseObject } = await client.private.createAccount(
'701234abcd...', // starkKey
'1234abcd...', // starkKeyYCoordinate
);
{
"account": {
"starkKey": "180913017c740260fea4b2c62828a4008ca8b0d6e4",
"positionId": "1812",
"equity": "10000",
"freeCollateral": "10000",
"quoteBalance": "10000",
"pendingDeposits": "0",
"pendingWithdrawals": "0",
"openPositions": {
"BTC-USD": {
"market": "BTC-USD",
"status": "OPEN",
"side": "LONG",
"size": "1000",
"maxSize": "1050",
"entryPrice": "100",
"exitPrice": null,
"unrealizedPnl": "50",
"realizedPnl": "100",
"createdAt": "2021-01-04T23:44:59.690Z",
"closedAt": null,
"netFunding": "500"
}
},
"accountNumber": "5",
"id": "id"
}
}
HTTP Request
POST v3/accounts
Description: Create an account with a given starkKey.
Request
Parameter | Description |
---|---|
starkKey | Public starkKey associated with the key-pair you created. |
starkKeyYCoordinate | Public starkKey Y-Coordinate associated with the key-pair you created. |
Response
Parameter | Description |
---|---|
account | See Account. |
Get Account
Get Account
account = client.private.get_account(
# Optional if eth_private_key or web3.eth.defaultAccount was provided.
ethereum_address='0x0123...',
)
const account: { account: AccountResponseObject } = await client.private.getAccount(
'0x0123...',
);
{
"account": {
"starkKey": "180913017c740260fea4b2c62828a4008ca8b0d6e4",
"positionId": "1812",
"equity": "10000",
"freeCollateral": "10000",
"quoteBalance": "10000",
"pendingDeposits": "0",
"pendingWithdrawals": "0",
"openPositions": {
"BTC-USD": {
"market": "BTC-USD",
"status": "OPEN",
"side": "LONG",
"size": "1000",
"maxSize": "1050",
"entryPrice": "100",
"exitPrice": null,
"unrealizedPnl": "50",
"realizedPnl": "100",
"createdAt": "2021-01-04T23:44:59.690Z",
"closedAt": null,
"netFunding": "500"
}
},
"accountNumber": "5",
"id": "id"
}
}
HTTP Request
GET v3/accounts/:id
Description: Get an account for a user by id. Using the client, the id will be generated with client information and an Ethereum address.
Request
Parameter | Description |
---|---|
ethereumAddress | Ethereum address associated with an account. |
Response
Parameter | Description |
---|---|
starkKey | Public StarkKey associated with an account. |
positionId | Starkware-specific positionId. |
equity | The amount of equity (value) in the account. Uses balances and index prices to calculate. |
freeCollateral | The amount of collateral that is withdrawable from the account. |
quoteBalance | Human readable quote token balance. Can be negative. |
pendingDeposits | The sum amount of all pending deposits. |
pendingWithdrawals | The sum amount of all pending withdrawal requests. |
openPositions | See Positions. Note, markets where the user has no position are not returned in the map. |
accountNumber | Unique accountNumber for the account. |
id | Unique id of the account hashed from the userId and the accountNumber. |
Get Accounts
Get Account
accounts = client.private.get_accounts()
const accounts: { accounts: AccountResponseObject[] } = await client.private.getAccounts();
{ "accounts": [{
"starkKey": "180913017c740260fea4b2c62828a4008ca8b0d6e4",
"positionId": "1812",
"equity": "10000",
"freeCollateral": "10000",
"quoteBalance": "10000",
"pendingDeposits": "0",
"pendingWithdrawals": "0",
"openPositions": {
"BTC-USD": {
"market": "BTC-USD",
"status": "OPEN",
"side": "LONG",
"size": "1000",
"maxSize": "1050",
"entryPrice": "100",
"exitPrice": null,
"unrealizedPnl": "50",
"realizedPnl": "100",
"createdAt": "2021-01-04T23:44:59.690Z",
"closedAt": null,
"netFunding": "500"
}
},
"accountNumber": "5",
"id": "id"
}]
}
HTTP Request
GET v3/accounts
Description: Get all accounts for a user.
Response
Parameter | Description |
---|---|
accounts | See Account. Returns an array of Accounts. |
Get Positions
Get Positions
from dydx3.constants import MARKET_BTC_USD
from dydx3.constants import POSITION_STATUS_OPEN
all_positions = client.private.get_positions(
market=MARKET_BTC_USD,
status=POSITION_STATUS_OPEN,
)
const positions: { positions: PositionResponseObject[] } = await client.private.getPositions(
{
market: Market.BTC_USD,
status: PositionStatus.OPEN,
},
);
{
"market": "BTC-USD",
"status": "OPEN",
"side": "LONG",
"size": "1000",
"maxSize": "1050",
"entryPrice": "100",
"exitPrice": null,
"unrealizedPnl": "50",
"realizedPnl": "100",
"createdAt": "2021-01-04T23:44:59.690Z",
"closedAt": null,
"netFunding": "500"
}
HTTP Request
GET v3/positions
Description: Get all current positions for a user by specified query parameters.
Request
Parameter | Description |
---|---|
market | (Optional) Market of the position. |
status | (Optional) Status of the position. Can be OPEN , CLOSED or LIQUIDATED . |
limit | (Optional) The maximum number of positions that can be fetched via this request. Note, this cannot be greater than 100. |
createdBeforeOrAt | (Optional) Set a date by which the positions had to be created. |
Response
Parameter | Description |
---|---|
market | The market of the position. |
status | The status of the position. |
side | The side of the position. LONG or SHORT . |
size | The current size of the position. Positive if long, negative if short, 0 if closed. |
maxSize | The maximum (absolute value) size of the position. Positive if long, negative if short. |
entryPrice | Average price paid to enter the position. |
exitPrice | Average price paid to exit the position. |
unrealizedPnl | The unrealized pnl of the position in quote currency. |
realizedPnl | The realized pnl of the position in quote currency. |
createdAt | Timestamp of when the position was opened. |
closedAt | Timestamp of when the position was closed. |
netFunding | Sum of all funding payments for this position. |
Get Transfers
Get Transfers
from dydx3.constants import ACCOUNT_ACTION_DEPOSIT
transfers = client.private.get_transfers(
transfer_type=ACCOUNT_ACTION_DEPOSIT,
limit=50,
)
const transfers: { transfers: TransferResponseObject[] } = await client.private.getTransfers(
{
type: AccountAction.DEPOSIT,
limit: 50,
},
);
{
"transfers": [{
"id": "foo",
"type": "DEPOSIT",
"debitAsset": "USDC",
"creditAsset": "USDT",
"debitAmount": "3000",
"creditAmount": "2800",
"transactionHash": "hash",
"status": "PENDING",
"createdAt": "2021-01-04T23:44:59.690Z",
"confirmedAt": null,
"clientId": "foo",
"fromAddress": "0x0913017c740260fea4b2c62828a4008ca8b0d6e4",
"toAddress": null
}]
}
HTTP Request
GET v3/transfers
Description: Get transfers for a user, limited by query parameters.
Request
Parameter | Description |
---|---|
transferType | (Optional) Type of the transfer. Can be DEPOSIT , WITHDRAWAL or FAST_WITHDRAWAL . |
limit | (Optional) The maximum number of transfers that can be fetched via this request. Note, this cannot be greater than 100. |
createdBeforeOrAt | Latest that the transfers could have been created. |
Response
Parameter | Description |
---|---|
id | Unique id assigned by dYdX. |
type | Type of the transfer. Will be DEPOSIT , WITHDRAWAL or FAST_WITHDRAWAL . |
debitAsset | Asset that was debited (USDC, USDT, USD, etc). |
creditAsset | Asset that was credited (USDC, USDT, USD, etc). |
debitAmount | Amount that was sent in for the deposit in debitAsset. |
creditAmount | Amount that was credited to the account in creditAsset. |
transactionHash | Ethereum transaction hash of the transfer. |
status | Status of the transfer. Will be PENDING or CONFIRMED . |
createdAt | Timestamp when created. |
confirmedAt | Timestamp when confirmed. |
clientId | ClientId of transfer. |
fromAddress | The Ethereum address the transfer is from. |
toAddress | The Ethereum address the transfer is for. |
Fast vs. Slow Withdrawal
The normal process for withdrawing from L2 to L1 requires waiting for a block of L2 transactions to be collected, and the zero-knowledge proof for the bock to be constructed and verified on-chain.
Using the fast withdrawal process, users can get their funds on L1 much faster by essentially trading their L2 funds to an “LP” account operated by dYdX, in order to receive immediate liquidity on L1. Since the LP must then recycle these funds from L2 to L1 via the regular withdrawal process, dYdX is only able to process a certain volume of fast withdrawals within a given period of time.
Create Withdrawal
Create Withdrawal
from dydx3.constants import ASSET_USDC
withdrawal = client.private.create_withdrawal(
position_id=1,
amount='100',
asset=ASSET_USDC,
expiration_epoch_seconds=1613988637,
)
const withdrawal: { withdrawal: TransferResponseObject } = await client.private.createWithdrawal(
{
amount: '100',
asset: Asset.USDC,
expiration: '2020-12-28T22:49:31.588Z',
},
'1',
);
{
"withdrawal": {
"id": "foo",
"type": "WITHDRAWAL",
"debitAsset": "USDC",
"creditAsset": "USDC",
"debitAmount": "3000",
"creditAmount": "2800",
"transactionHash": "hash",
"status": "PENDING",
"createdAt": "2021-01-04T23:44:59.690Z",
"confirmedAt": null,
"clientId": "foo",
"fromAddress": "0x0913017c740260fea4b2c62828a4008ca8b0d6e4",
"toAddress": null
}
}
HTTP Request
POST v3/withdrawals
Description: Create a withdrawal from an account.
Request
Parameter | Description |
---|---|
positionId | The unique id of the position the withdrawal is associated with. |
amount | Amount to be withdrawn. |
asset | Asset being withdrawn. Can currently only be USDC . |
expiration | Datetime at which the withdrawal expires if it has not been completed. |
clientId | (Optional) Unique id of the client associated with the withdrawal. |
signature | (Optional) The starkware signature for the withdrawal. If not included, will be done by the client. |
Response
Parameter | Description |
---|---|
withdrawal | See Transfers. |
Create Fast Withdrawal
Create Fast Withdrawal
from dydx3.constants import ASSET_USDC
fast_withdrawal = client.private.create_fast_withdrawal(
credit_asset=ASSET_USDC,
credit_amount='100',
debit_amount='110',
to_address='0x98ab...',
lp_position_id='2',
expiration_epoch_seconds=1613988637,
signature='0abc12...', # Optional if stark_private_key was provided to client.
)
const fastWithdrawal: { withdrawal: TransferResponseObject } = await client.private.createFastWithdrawal(
{
creditAsset: Asset.USDC,
creditAmount: '100',
debitAmount: '110',
toAddress: '0x98ab...',
lpPositionId: '2',
clientId: 'client',
signature: '0abc12...', // Optional if starkPrivateKey was provided to client.
},
);
{
"withdrawal": {
"id": "foo",
"type": "FAST_WITHDRAWAL",
"debitAsset": "USDC",
"creditAsset": "USDC",
"debitAmount": "3000",
"creditAmount": "2800",
"transactionHash": "hash",
"status": "PENDING",
"createdAt": "2021-01-04T23:44:59.690Z",
"confirmedAt": null,
"clientId": "foo",
"fromAddress": "0x0913017c740260fea4b2c62828a4008ca8b0d6e4",
"toAddress": null
}
}
HTTP Request
POST v3/fast-withdrawals
Description: Create a fast-wthdrawal.
Request
Parameter | Description |
---|---|
creditAsset | Asset being withdrawn. Can currently only be USDC . |
creditAmount | Amount that is expected. |
debitAmount | Amount offered in USDC for the credit amount. |
toAddress | Address to be credited |
lpPositionId | LP Position Id of the debit account. |
expiration | Datetime at which the withdrawal expires if it has not been completed. |
signature | Starkware signature for the fast withdrawal. Currently can be anything. |
clientId | (Optional) Unique id of the client associated with the withdrawal. |
Response
Parameter | Description |
---|---|
withdrawal | See Transfers. |
Order Types
Type | Description |
---|---|
LIMIT | Limit order. |
STOP | Stop limit order. |
TRAILING_STOP | Trailing stop limit order. |
TAKE_PROFIT | Trailing stop limit order. |
LIQUIDATED | Indicates the account was liquidated (fills only). |
LIQUIDATION | Indicates the account took over a liquidated account (fills only). |
Create A New Order
Create Order
from dydx3.constants import MARKET_BTC_USD
from dydx3.constants import ORDER_SIDE_SELL
from dydx3.constants import ORDER_TYPE_LIMIT
from dydx3.constants import TIME_IN_FORCE_GTT
placed_order = client.private.create_order(
position_id=1,
market=MARKET_BTC_USD,
side=ORDER_SIDE_SELL,
order_type=ORDER_TYPE_LIMIT,
post_only=False,
size='100',
price='18000',
limit_fee='0.015',
expiration_epoch_seconds=1613988637,
time_in_force=TIME_IN_FORCE_GTT,
)
const order: { order: OrderResponseObject } = await client.private.createOrder(
{
side: OrderSide.SELL,
type: OrderType.LIMIT,
timeInForce: TimeInForce.GTT,
postOnly: false,
size: '100',
price: '18000',
limitFee: '0.015',
expiration: '2022-12-21T21:30:20.200Z',
},
'1',
);
{
"order": {
"id": "foo",
"clientId": "foo",
"accountId": "afoo",
"market": "BTC-USD",
"side": "SELL",
"price": "18000",
"triggerPrice": null,
"trailingPercent": null,
"size": "100",
"remainingSize": "100",
"type": "LIMIT",
"createdAt": "2021-01-04T23:44:59.690Z",
"unfillableAt": null,
"expiresAt": "2022-12-21T21:30:20.200Z",
"status": "PENDING",
"timeInForce": "GTT",
"postOnly": false,
"cancelReason": null
}
}
HTTP Request
POST v3/orders
Description: Create a new order.
Request
Parameter | Description |
---|---|
positionId | StarkWare-specific positionId. This is required for signing and can be fetched from the account endpoints. |
market | Market of the order. |
side | Either BUY or SELL. |
type | The type of order. This can be LIMIT , STOP , TRAILING_STOP or TAKE_PROFIT . |
postOnly | Whether the order should be canceled if it would fill immediately on reaching the matching-engine. |
size | Size of the order, in base currency (i.e. an ETH-USD position of size 1 represents 1 ETH). |
price | Worst accepted price of the base asset in USD. |
limitFee | Is the highest accepted fee for the trade. See below for more information. |
expiration | Time at which the order will expire if not filled. |
timeInForce | (Optional) One of GTT (Good til time), FOK (Fill or kill) or IOC (Immediate or cancel). This will default to GTT . |
cancelId | (Optional) The id of the order that is being replaced by this one. |
triggerPrice | (Optional) The triggerPrice at which this order will go to the matching-engine. |
trailingPercent | (Optional) The percent that the triggerPrice trails the indexPrice of the market. |
clientId | (Optional) Unique id assigned by the client. |
signature | (Optional) Signature for the order, signed with the account's STARK private key. |
Response
Parameter | Description |
---|---|
order | See order. |
Order LimitFee
The limitFee
is the highest fee a user would be willing to accept on an order. This should be in decimal form (i.e. 0.1 is 10%). To see current fees, call GET /v3/users and the maker/taker fee rates show what fees will be. If the order is postOnly
dYdX will validate against makerFeeRate
only. The opposite is true if the order is FOK
or IOC
- dYdX will only validate against takerFeeRate
. Otherwise, dYdX assesses against the maximum of maker and taker fee rate.
Tick Size and Minimum Size
Tick Size
Each market has a specified tickSize
. Order price
must be a multiple of the tickSize. THe same applies to triggerPrice
and trailingPercent
if either of these are not null.
Minimum Size
Each market has a specified minOrderSize
. Order size
must be not be less than the minOrderSize.
Order Deletion
Canceled orders older than one month are deleted from the dYdX database.
Cancel An Order
Cancel an order
client.private.cancel_order(order_id='0x0000')
await client.private.cancelOrder('0x0000');
{}
HTTP Request
DELETE v3/orders/:id
Description: Cancel an order by its unique id.
Request
Parameter | Description |
---|---|
orderId | Unique id of the order to be canceled. |
Response
Parameter | Description |
---|---|
cancelOrder | See order. |
Cancel Orders
Cancel orders
from dydx3.constants import MARKET_BTC_USD
client.private.cancel_all_orders(market=MARKET_BTC_USD)
await client.private.cancelAllOrders(Market.BTC_USD);
{}
HTTP Request
DELETE v3/orders
Description: Either bulk cancel all orders or just all orders for a specific market.
Request
Parameter | Description |
---|---|
market | (Optional) Market of the orders being canceled. |
Response
Parameter | Description |
---|---|
cancelOrders | Returns an array of orders to be canceled. See order. |
Get Orders
Get Orders
from dydx3.constants import MARKET_BTC_USD
from dydx3.constants import ORDER_SIDE_SELL
from dydx3.constants import ORDER_TYPE_LIMIT
from dydx3.constants import ORDER_STATUS_OPEN
all_orders = client.private.get_orders(
market=MARKET_BTC_USD,
status=ORDER_STATUS_OPEN,
side=ORDER_SIDE_SELL,
type=ORDER_TYPE_LIMIT,
limit=50,
)
const allOrders: { orders: OrderResponseObject[] } = await client.private.getOrders(
{
market: Market.BTC_USD,
status: OrderStatus.OPEN,
side: OrderSide.SELL,
type: OrderType.LIMIT,
limit: 50,
},
);
{
"orders": [
{
"id": "id",
"clientId": "foo",
"accountId": "afoo",
"market": "BTC-USD",
"side": "SELL",
"price": "29000",
"triggerPrice": null,
"trailingPercent": null,
"size": "0.500",
"remainingSize": "0.500",
"type": "LIMIT",
"createdAt": "2021-01-04T23:44:59.690Z",
"unfillableAt": null,
"expiresAt": "2021-02-04T23:44:59.690Z",
"status": "OPEN",
"timeInForce": "GTT",
"postOnly": false,
"cancelReason": null
},
...
]
}
HTTP Request
GET v3/orders
Description: Get all orders for a user by specified parameters.
Request
Parameter | Description |
---|---|
market | (Optional) Market of the order. |
status | (Optional) The status of all orders being gotten. This can be PENDING , OPEN , FILLED , CANCELED or UNTRIGGERED . |
side | (Optional) Either BUY or SELL. |
type | (Optional) The expected type of the order. This can be LIMIT , STOP , TRAILING_STOP or TAKE_PROFIT . |
limit | (Optional) The maximum number of orders that can be fetched via this request. Note, this cannot be greater than 100. |
createdBeforeOrAt | (Optional) Set a date by which the orders had to be created. |
Response
Parameter | Description |
---|---|
orders | An array of orders. See order below. |
Order
Parameter | Description |
---|---|
id | The unique id assigned by dYdX. |
clientId | The unique id assigned by the client. |
accountId | The id of the account. |
market | Market of the fill. |
side | Either BUY or SELL. |
price | The price of the order. Must adhere to the market's tick size. |
triggerPrice | The trigger price of the order. Must adhere to the market's tick size. |
trailingPercent | Used for trailing stops. Percent drop from maximum price that will trigger the order. |
size | Total size (base currency) of the order |
remainingSize | Size of order not yet filled. |
type | The type of the fill. |
createdAt | Timestamp when the fill was created. |
unfillableAt | Time order was either filled or canceled. |
expiresAt | Time order will expire. |
status | See order statuses below. |
timeInForce | (Optional) One of GTT (Good til time), FOK (Fill or kill) or IOC (Immediate or cancel). This will default to GTT . |
postOnly | If the order will cancel if it would take the position of TAKER . |
cancelReason | See cancel reasons below. |
Order Statuses
Status | Description |
---|---|
PENDING | Order has yet to be processed by the matching engine. |
OPEN | Order is active and on the orderbook. Could be partially filled. |
FILLED | Fully filled. |
CANCELED | Canceled, for one of the cancel reasons. Could be partially filled. |
UNTRIGGERED | Triggerable order that has not yet been triggered. |
Cancel Reasons
Reason | Description |
---|---|
UNDERCOLLATERALIZED | Order would have led to an undercollateralized state for the user. |
EXPIRED | Order expired. |
USER_CANCELED | Order was canceled by the user. |
SELF_TRADE | Order would have resulted in a self trade for the user. |
FAILED | An internal issue caused the order to be canceled. |
COULD_NOT_FILL | A FOK or IOC order could not be fully filled. |
POST_ONLY_WOULD_CROSS | A post-only order would cross the orderbook. |
Get Order By Id
Get Order By Id
order = client.private.get_order_by_id('foo')
const allOrders: { order: OrderResponseObject } = await client.private.getOrderById('foo');
{
"order": {
"id": "foo",
"clientId": "foo",
"accountId": "afoo",
"market": "BTC-USD",
"side": "SELL",
"price": "29000",
"triggerPrice": null,
"trailingPercent": null,
"size": "0.500",
"remainingSize": "0.500",
"type": "LIMIT",
"createdAt": "2021-01-04T23:44:59.690Z",
"unfillableAt": null,
"expiresAt": "2021-02-04T23:44:59.690Z",
"status": "OPEN",
"timeInForce": "GTT",
"postOnly": false,
"cancelReason": null
}
}
HTTP Request
GET v3/orders/:id
Description: Get an order by id
from the active orderbook and order history.
Request
Parameter | Description |
---|---|
id | Unique id of the order |
Response
Parameter | Description |
---|---|
order | See order. |
Get Order by ClientId
Get Order By ClientId
order = client.private.get_order_by_client_id('clientId')
const allOrders: { order: OrderResponseObject } = await client.private.getOrderByClientId('clientId');
{
"order": {
"id": "foo",
"clientId": "foo",
"accountId": "afoo",
"market": "BTC-USD",
"side": "SELL",
"price": "29000",
"triggerPrice": null,
"trailingPercent": null,
"size": "0.500",
"remainingSize": "0.500",
"type": "LIMIT",
"createdAt": "2021-01-04T23:44:59.690Z",
"unfillableAt": null,
"expiresAt": "2021-02-04T23:44:59.690Z",
"status": "OPEN",
"timeInForce": "GTT",
"postOnly": false,
"cancelReason": null
}
}
HTTP Request
GET v3/orders/client/:id
Description: Get an order by clientId
from the active orderbook and order history.
Request
Parameter | Description |
---|---|
id | Unique clientId of the order |
Response
Parameter | Description |
---|---|
order | See order. |
Get Fills
Get Fills
from dydx3.constants import MARKET_BTC_USD
all_fills = client.private.get_fills(
market=MARKET_BTC_USD,
)
const allFills: { fills: FillResponseObject[] } = await client.private.getFills(
{
market: Market.BTC_USD,
},
);
{
"fills": [
{
"id": "foo",
"side": "BUY",
"liquidity": "TAKER",
"type": "LIMIT",
"market": "BTC-USD",
"orderId": "id",
"price": "29000",
"size": "0.001",
"fee": "100",
"createdAt": "2021-01-05T16:33:43.163Z"
},
...
]
}
HTTP Request
GET v3/fills
Description: Get Fills for a user by specified parameters.
Request
Parameter | Description |
---|---|
market | (Optional) Market of the fills. |
orderId | (Optional) Unique order id. Will only fetch a single order. |
limit | (Optional) The maximum number of fills that can be fetched via this request. Note, this cannot be greater than 100. |
createdBeforeOrAt | (Optional) Set a date by which the fills had to be created. |
Response
Parameter | Description |
---|---|
fills | Array of fills. See below for an individual example. |
Fill
Parameter | Description |
---|---|
id | The unique id assigned by dYdX. |
side | Either BUY or SELL. |
liquidity | Either MAKER or TAKER. |
type | The type of the fill. |
market | Market of the fill. |
orderId | Id of the order which caused this fill. null if type is LIQUIDATED or LIQUIDATION` . |
price | The price the fill occurred at (in quote / base currency). |
size | Size that was filled (in base currency). |
fee | Fee that was charged (in quote currency). |
createdAt | Timestamp when the fill was created. |
Get Funding Payments
Get Funding Payments
from dydx3.constants import MARKET_BTC_USD
funding_payments = client.private.get_funding_payments(
market=MARKET_BTC_USD,
limit=75,
)
const fundingPayments: { fundingPayments: FundingResponseObject } = await client.private.getFundingPayments(
{
market: Market.BTC_USD,
limit: 75,
},
);
{
"fundingPayments": [{
"market": "BTC-USD",
"payment": "10000",
"rate": "0.0000125000",
"positionSize": "500",
"price": "90",
"effectiveAt": "2021-01-04T23:44:59.690Z"
}]
}
HTTP Request
GET v3/funding
Description: Get Funding Payments made to an account.
Request
Parameter | Description |
---|---|
market | (Optional) Market of the funding payments. |
limit | (Optional) The maximum number of funding payments that can be fetched via this request. Note, this cannot be greater than 100. |
effectiveBeforeOrAt | (Optional) Set a date by which the funding payments had to be created. |
Response
Parameter | Description |
---|---|
market | Market corresponding to the funding payment. |
payment | Amount of the payment, negative if user received funding and positive if user paid funding. |
rate | Funding rate at the time of this payment (as a 1-hour rate). |
positionSize | User's position size at the time of this funding payment. positive if long, negative if short. |
price | Oracle price used to calculate this funding payment. |
effectiveAt | Time of this funding payment. |
Get Historical PNL Ticks
Get Historical PNL Ticks
funding_payments = client.private.get_historical_pnl(
account='49979004...',
created_before_or_at='2021-04-09T22:02:46+0000',
)
const historicalPnlTicks: {
historicalPnl: HistoricalPnlResponseObject[],
} = await client.private.getHistoricalPnl(
{
account: '49979004...',
createdBeforeOrAt: '2021-04-09T22:02:46+0000',
},
);
{
"historicalPnl": [{
"equity": "0.0000",
"totalPnl": "0.0000",
"createdAt": "2021-04-09T21:08:34.984Z",
"netTransfers": "0.0000",
"accountId": "49979004..."
}]
}
HTTP Request
GET v3/historical-pnl
Description: Get Historical PNL for an account during an interval.
Request
Parameter | Description |
---|---|
account | Account PNL will be for. |
effectiveBeforeOrAt | (Optional) Used for setting a ending bounds on the ticks. |
effectiveAtOrAfter | (Optional) Used for setting a starting bounds on the ticks. |
Response
Parameter | Description |
---|---|
historicalPnl | Array of HistoricalAggregatedPnl. See "HistoricalAggregatedPnl" below. |
HistoricalAggregatedPnl
Parameter | Description |
---|---|
equity | The total account equity. |
totalPnl | The total PNL for the account since inception. |
createdAt | When the tick was recorded. |
netTransfers | The value into or out of the account of transfers since the last interval. |
accountId | Account the tick is for. |
Public HTTP API
Get Markets
Get Markets
markets = client.public.get_markets()
const markets: { markets: MarketsResponseObject } = await client.public.getMarkets();
{
"markets": {
"LINK-USD": {
"market": "LINK-USD",
"status": "ONLINE",
"baseAsset": "LINK",
"quoteAsset": "USD",
"stepSize": "0.1",
"tickSize": "0.01",
"indexPrice": "12",
"oraclePrice": "101",
"priceChange24H": "0",
"nextFundingRate": "0.0000125000",
"nextFundingAt": "2021-03-01T18:00:00.000Z",
"minOrderSize": "1",
"type": "PERPETUAL",
"initialMarginFraction": "0.10",
"maintenanceMarginFraction": "0.05",
"baselinePositionSize": "1000",
"incrementalPositionSize": "1000",
"incrementalInitialMarginFraction": "0.2",
"volume24H": "0",
"trades24H": "0",
"openInterest": "0",
"maxPositionSize": "10000",
"allTimeLiquidationQuoteVolume": "1000",
"dailyLiquidationQuoteVolume": "0"
},
...
}
HTTP Request
GET v3/markets
Description: Get one or all markets as well as metadata about each retrieved market.
Request
Parameter | Description |
---|---|
market | (Optional): Specific market to be fetched. |
Response
Market
Parameter | Description |
---|---|
markets | Map of market objects. See below for individual market. |
Parameter | Description |
---|---|
market | Symbol of the market. |
status | Status of the market. Can be one of ONLINE , OFFLINE , POST_ONLY or CANCEL_ONLY . |
baseAsset | Symbol of the base asset. e.g. "BTC". |
quoteAsset | Symbol of the quote asset. e.g. "BTC". |
stepSize | The minimum step size (in base currency) of trade sizes for the market. |
tickSize | The Tick size of the market. |
indexPrice | The current index price of the market. |
oraclePrice | The current oracle price of the market. |
priceChange24H | The absolute price change of the index price over the past 24 hours. |
nextFundingRate | The predicted next funding rate (as a 1-hour rate). |
nextFundingAt | The timestamp of the next funding update. |
minOrderSize | Minimum order size for the market. |
type | Type of the market. This will always be PERPETUAL for now. |
initialMarginFraction | The margin fraction needed to open a position. |
maintenanceMarginFraction | The margin fraction required to prevent liquidation. |
baselinePositionSize | The max position size (in base token) before increasing the initial-margin-fraction. |
incrementalPositionSize | The step size (in base token) for increasing the initialMarginFraction by (incrementalInitialMarginFraction per step) |
incrementalInitialMarginFraction | The increase of initialMarginFraction for each incrementalPositionSize above the baselinePositionSize the position is. |
maxPositionSize | The max position size for this market in base token. |
volume24H | The USD volume of the market in the previous 24 hours. |
trades24H | The number of trades in the market in the previous 24 hours. |
openInterest | The open interest in base token. |
allTimeLiquidationQuoteVolume | The all time liquidation quote volume. |
dailyLiquidationQuoteVolume | The liquidation quote volume for the past 24 hours. |
Get Orderbook
Get Trades
from dydx3.constants import MARKET_BTC_USD
orderbook = client.public.get_orderbook(
market=MARKET_BTC_USD,
)
const orderbook: OrderbookResponseObject = await client.public.getOrderbook(
Market.BTC_USD,
);
{
"bids": [
{
"price": "29000",
"size": "1"
},
...
],
"asks": [
{
"price": "29500",
"size": "0.499"
},
...
]
}
HTTP Request
GET v3/orderbook/:market
Description: Returns the active orderbook for a market. All bids and asks that are fillable are returned.
Request
Parameter | Description |
---|---|
market | Market of the Orderbook. |
Response
Parameter | Description |
---|---|
bids | See Orderbook Order below. Sorted by price in descending order. |
asks | See Orderbook Order below. Sorted by price in ascending order. |
Orderbook Order
Parameter | Description |
---|---|
price | The price of the order (in quote / base currency). |
size | The size of the order (in base currency). |
Get Trades
Get Trades
from dydx3.constants import MARKET_BTC_USD
all_trades = client.public.get_trades(
market=MARKET_BTC_USD,
)
const trades: { trades: Trade[] } = await client.public.getTrades({
market: Market.BTC_USD,
});
{
"trades": [
{
"side": "BUY",
"size": "0.001",
"price": "29000",
"createdAt": "2021-01-05T16:33:43.163Z"
},
...
]
}
HTTP Request
GET v3/trades/:market
Description: Get Trades by specified parameters.
Request
Parameter | Description |
---|---|
market | Market of the trades. |
startingBeforeOrAt | (Optional): Set a date by which the trades had to be created. |
Response
Parameter | Description |
---|---|
trades | An array of trades. See trade below |
Trade
Parameter | Description |
---|---|
side | Either BUY or SELL. |
size | The size of the trade. |
price | The price of the trade. |
createdAt | The time of the trade. |
Get Fast Withdrawal Liquidity
Get Fast Withdrawal
fast_withdrawals_info = client.public.get_fast_withdrawal()
const availableFundsMap: {
liquidityProviders: {
[positionId: string]: {
availableFunds: string,
starkKey: string,
quote: {
creditAsset: string,
creditAmount: string,
debitAmount: string,
} | null,
}
}
} = await client.public.getFastWithdrawalAvailableFunds();
{
"liquidityProviders": {
"1812": {
"availableFunds": "1000",
"starkKey": "180913017c740260fea4b2c62828a4008ca8b0d6e4",
"quote": null,
},
}
}
HTTP Request
GET v3/fast-withdrawals
Description: Returns a map of all LP provider accounts that have available funds for fast withdrawals. Given a debitAmount
and asset the user wants sent to L1, this endpoint also returns the predicted amount of the desired asset the user will be credited on L1. Given a creditAmount
and asset the user wants sent to L1, this endpoint also returns the predicted amount the user will be debited on L2.
Request
Parameter | Description |
---|---|
creditAsset | (Optional): The asset that would be sent to the user. Required if creditAmount or debitAmount are set. |
creditAmount | (Optional): Set this value if the user wants a quote based on the creditAmount. |
debitAmount | (Optional): Set this value if the user wants a quote based on the debitAmount. |
Response
Parameter | Description |
---|---|
liquidityProviders | Map of LP position IDs to Liquidity Provider. |
Liquidity Provider
Field | Description |
---|---|
availableFunds | The funds available for the LP. |
starkKey | The public stark key for the LP. |
quote | The Liquidity Provider Quote given the user's request. Null if no request from the user or the request is unfillable by this LP. |
Liquidity Provider Quote
Field | Description |
---|---|
creditAsset | The asset that would be sent to the user on L1. |
creditAmount | The amount of creditAsset that would be sent to the user (human readable). |
debitAmount | The amount of USD that would be deducted from the users L2 account (human readable). |
Get Market Stats
Get Market Stats
from dydx3.constants import MARKET_BTC_USD
market_statistics = client.public.get_stats(
market=MARKET_BTC_USD,
days=MARKET_STATISTIC_DAY_SEVEN,
)
const marketStatistics = await client.public.getStats({
market: Market.BTC_USD,
days: MarketStatisticDay.SEVEN,
});
{
"markets": {
"ETH-USD": {
"market": "ETH-USD",
"open": "1100",
"close": "1100",
"high": "1100",
"low": "1095",
"baseVolume": "10000",
"quoteVolume": "100000",
"type": "PERPETUAL"
}
}
}
HTTP Request
GET v3/stats/:market
Description: Get an individual market's statistics over a set period of time or all available periods of time.
Request
Parameter | Description |
---|---|
market | Market whose statistics are being fetched. |
days | (Optional): Specified day range for the statistics to have been compiled over. Can be one of 1 , 7 , 30 . |
Response
Parameter | Description |
---|---|
market | The symbol of the market, e.g. ETH-USD. |
open | The open price of the market. |
high | The high price of the market. |
low | The low price of the market. |
close | The close price of the market. |
baseVolume | The total amount of base asset traded. |
quoteVolume | The total amount of quote asset traded. |
type | Type of the market. This will always be PERPETUAL for now. |
Get Historical Funding
Get Historical Funding
from dydx3.constants import MARKET_BTC_USD
historical_funding = client.public.get_historical_funding(
market=MARKET_BTC_USD,
)
const historicalFunding = await client.public.getHistoricalFunding({
market: Market.BTC_USD,
});
{
"historicalFunding": [
{
"market": "BTC-USD",
"rate": "0.0000125000",
"price": "31297.5000008009374142",
"effectiveAt": "2021-01-05T09:10:49.000Z"
},
...
]
}
HTTP Request
GET v3/historical-funding/:market
Description: Get the historical funding rates for a market.
Request
Parameter | Description |
---|---|
market | Market whose historical funding rates are being fetched. |
effectiveBeforeOrAt | (Optional): Set a date by which the historical funding rates had to be created. |
Response
Parameter | Description |
---|---|
historicalFunding | Array of HistoricalFunding. See below for individual example. |
Historical Funding
Parameter | Description |
---|---|
market | Market for which to query historical funding. |
rate | The funding rate (as a 1-hour rate). |
price | Oracle price used to calculate the funding rate. |
effectiveAt | Time at which funding payments were exchanged at this rate. |
Get Candles for Market
Get Candles for Market
from dydx3.constants import MARKET_BTC_USD
candles = client.public.get_candles(
market=MARKET_BTC_USD,
resolution='1DAY',
)
const candles: {
candles: CandleResponseObject,
} = await client.public.getCandles({
market: Market.BTC_USD,
resolution: CandleResolution.1DAY,
})
"candles": [
{
"startedAt": "2021-01-05T00:00:00.000Z",
"market": "BTC-USD",
"resolution": "1DAY",
"low": "40000",
"high": "45000",
"open": "45000",
"close": "40000",
"baseTokenVolume": "1.002",
"trades": "3",
"usdVolume": "45085",
"startingOpenInterest": "28"
},
...
]
HTTP Request
GET v3/candles/:market
Description: Get the candle statistics for a market.
Request
Parameter | Description |
---|---|
market | Market whose candles are being fetched. |
resolution | (Optional): Specific candle resolution being fetched. Can be one of 1DAY , 1HOUR . |
fromISO | (Optional): Starting point for the candles. |
toISO | (Optional): Ending point for the candles. |
limit | (Optional): The number of candles to fetch. (Max 100.) |
Response
Parameter | Description |
---|---|
startedAt | When the candle started, time of first trade in candle. |
market | Market the candle is for. |
resolution | Time-period of candle (currently 1HOUR or 1DAY). |
low | Low trade price of the candle. |
high | High trade price of the candle. |
open | Open trade price of the candle. |
close | Close trade price of the candle. |
baseTokenVolume | Volume of trade in baseToken currency for the candle. |
trades | Count of trades during the candle. |
usdVolume | Volume of trade in USD for the candle. |
startingOpenInterest | The open interest in baseToken at the start of the candle. |
Check If User Exists
Check If User Exists
user_exists = client.public.check_if_user_exists(
ethereum_address='foo',
)
const userExists: { exists: boolean } = await client.public.doesUserExistWithAddress(
'foo',
);
{
"exists": true
}
HTTP Request
GET v3/users/exists
Description: Check if a user exists for a given Ethereum address.
Request
Parameter | Description |
---|---|
ethereumAddress | Ethereum address that the user would be associated with. |
Response
Parameter | Description |
---|---|
exists | If a user exists for the given Ethereum address. |
Check If Username Exists
Check If User Exists
username_exists = client.public.check_if_username_exists(
username='username',
)
const usernameExists: { exists: boolean } = await client.public.doesUserExistWithUsername(
'username',
);
{
"exists": true
}
HTTP Request
GET v3/usernames
Description: Check if a username has been taken by a user.
Request
Parameter | Description |
---|---|
username | Unique username being checked. |
Response
Parameter | Description |
---|---|
exists | If a username has been taken by any user. |
Get API Server Time
Get Time
time_object = client.public.get_time()
const time: { time: { iso: string, epoch: number } } = await client.public.getTime();
{
"iso": "2021-02-02T18:35:45Z",
"epoch": "1611965998.515",
}
HTTP Request
GET v3/time
Description: Get the current time of the API server.
Response
Parameter | Description |
---|---|
iso | ISO time of the server in UTC. |
epoch | Epoch time in seconds with milliseconds. |
V3 Websocket API
dYdX offers a WebSocket API for streaming v3 updates.
You can connect to the v3 WebSockets at:
- Production:
wss://api.dydx.exchange/v3/ws
- Staging (Ropsten):
wss://api.stage.dydx.exchange/v3/ws
The server will send pings every 30s and expects a pong within 10s. The server does not expect pings, but will respond with a pong if sent one.
Accounts channel
This channel provides realtime information about orders, fills, funding updates and positions for a user. To subscribe, you will need to be authenticated.
To subscribe:
field | type | description |
---|---|---|
type | string | Set to subscribe |
channel | string | Set to v3_accounts |
accountNumber | string | The account number to subscribe to |
apiKey | string | The apiKey for the user |
signature | string | validation signature. See below |
timestamp | string | timestamp used for the signature |
passphrase | string | The passphrase field of the API key |
Authentication
The authentication in the accounts channel is identical to private endpoint authentication with one key difference. The requestPath
is /ws/accounts
.
Initial Response:
The initial response will contain the information about the account, open positions, recent transfers, and open orders, i.e. everything from GET /v3/accounts/:id
, GET /v3/transfers
, GET /v3/funding
and GET /v3/orders
(with accountId
in the header).
Note that the freeCollateral
and equity
(also called total account value
) for an account are only sent in the initial response. To track these over time, refer to this section.
Example initial response
{
"type": "subscribed",
"channel": "v3_accounts",
"connection_id": "e2a6c717-6f77-4c1c-ac22-72ce2b7ed77d",
"id": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"message_id": 1,
"contents": {
"orders": [
{
"id": "797fc129eeb7c54163f3947f1f250594",
"clientId": "2",
"market": "BTC-USD",
"accountId": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"side": "BUY",
"size": "112",
"remainingSize": "0",
"price": "34",
"limitFee": "0.0005",
"type": "LIMIT",
"status": "OPEN",
"signature": "0x456...",
"timeInForce": "FOK",
"postOnly": "false",
"expiresAt": "2021-09-22T20:22:26.399Z",
"createdAt": "2020-09-22T20:22:26.399Z"
}
],
"account": {
"id": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"positionId": "9356",
"userId": "fe71e7df-c633-4ba1-870e-61f36580cfc5",
"accountNumber": "0",
"starkKey": "041c2ae647ee91807eed6471488983ab4addc2a602d4ceeb04dfda470e33f148",
"quoteBalance": "300",
"pendingDeposits": "0",
"pendingWithdrawals": "0",
"lastTransactionId": "14",
"equity": "1879.090000",
"freeCollateral": "1879.090000",
"openPositions": {
"LINK-USD": {
"id": "677dad3b-d848-5e7c-84bf-18760f3414f6",
"accountId": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"market": "LINK-USD",
"side": "LONG",
"status": "OPEN",
"size": "200",
"maxSize": "300",
"entryPrice": "36",
"exitPrice": "38",
"realizedPnl": "50",
"createdAt": "2020-09-22T20:25:26.399Z",
"openTransactionId": "2",
"lastTransactionId": "14"
}
}
}
},
"transfers": [
{
"id": "8d303634-da14-56bb-99f5-122e34b1ce34",
"type": "FAST_WITHDRAWAL",
"debitAsset": "USDC",
"creditAsset": "USDC",
"debitAmount": "500",
"creditAmount": "500",
"transactionHash": "0xb86e98d05098de6249d7c10616ffefa0b001976238083dc34a8e747fd7960029",
"status": "CONFIRMED",
"createdAt": "2021-02-05T00:37:43.009Z",
"confirmedAt": null,
"clientId": "9407156494718159",
"fromAddress": "0x3ebe6781be6d436cb7999cfce8b52e40819721cb",
"toAddress": "0x14c2a496e5b7a52d54748cba0bd9f4b24ed27fdd"
}
],
"fundingPayments": [],
}
Channel Data
Subsequent responses will contain any updates to open orders, or changes to account balance, or the open positions, or transfers, in a single message.
A fill occurs, and a position is closed, and the account balance modified
{
"type": "channel_data",
"channel": "v3_accounts",
"connection_id": "e2a6c717-6f77-4c1c-ac22-72ce2b7ed77d",
"id": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"message_id": 2,
"contents": {
"fills": [{
"id": "677dad3b-d848-5e7c-84bf-18760f3414f6",
"accountId": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"side": "BUY",
"liquidity": "TAKER",
"market": "LINK-USD",
"orderId": "797fc129eeb7c54163f3947f1f250594",
"size": "112",
"price": "35",
"fee": "10",
"transactionId": "1",
"orderClientId": "31391968951033844",
"createdAt": "2020-09-22T20:25:26.399Z",
}],
"orders": [{
"id": "797fc129eeb7c54163f3947f1f250594",
"clientId": "2",
"market": "BTC-USD",
"accountId": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"side": "BUY",
"size": "112",
"remainingSize": "0",
"price": "34",
"limitFee": "0.0005",
"type": "LIMIT",
"status": "ENTIRELY_FILLED",
"signature": "0x456...",
"timeInForce": "FOK",
"postOnly": "false",
"expiresAt": "2021-09-22T20:22:26.399Z",
"createdAt": "2020-09-22T20:22:26.399Z"
}],
"positions": [{
"id": "677dad3b-d848-5e7c-84bf-18760f3414f6",
"accountId": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"market": "LINK-USD",
"side": "LONG",
"status": "CLOSED",
"size": "200",
"maxSize": "300",
"entryPrice": "36",
"exitPrice": "38",
"realizedPnl": "50",
"createdAt": "2020-09-22T20:25:26.399Z",
"openTransactionId": "2",
"closeTransactionId": "23",
"lastTransactionId": "23",
"closedAt": "2020-14-22T20:25:26.399Z"
}],
"accounts": [{
"id": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"positionId": "b2759094-12af-4b59-8071-661e99148a14",
"userId": "fe71e7df-c633-4ba1-870e-61f36580cfc5",
"accountNumber": "0",
"starkKey": "0x456...",
"quoteBalance": "700",
"pendingDeposits": "400",
"pendingWithdrawals": "0",
"lastTransactionId": "14"
}]
}
}
a deposit occurs
{
"type": "channel_data",
"channel": "v3_accounts",
"connection_id": "e2a6c717-6f77-4c1c-ac22-72ce2b7ed77d",
"id": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"message_id": 2,
"contents": {
"fills": [],
"orders": [],
"positions": [],
"accounts": [{
"id": "e33a8007-57ca-52ab-887d-d162d1666f3b",
"positionId": "b2759094-12af-4b59-8071-661e99148a14",
"userId": "fe71e7df-c633-4ba1-870e-61f36580cfc5",
"accountNumber": "0",
"starkKey": "0x456...",
"quoteBalance": "7000",
"pendingDeposits": "200",
"pendingWithdrawals": "0",
"lastTransactionId": "14"
}],
"transfers": [{
"id" : "35bb84a8-d8b5-5f8e-a49e-8ad979fb7567",
"accountId" : "e33a8007-57ca-52ab-887d-d162d1666f3b",
"type" : "DEPOSIT",
"debitAsset" : "USDC",
"creditAsset" : "USDC",
"debitAmount" : "10000",
"creditAmount" : "10000",
"transactionHash" : "0xec2bd16e73e4bb54c1ee25415233ded15f6e8c4edb8480ce9774a28c7846d4f0",
"status" : "PENDING",
"clientId" : "18",
"updatedAt" : "2021-01-17 22:24:54.661+00",
"createdAt" : "2021-01-17 22:24:54.560426+00",
}]
}
}
Orderbook
To subscribe:
field | type | description |
---|---|---|
type | string | Set to subscribe |
channel | string | Set to v3_orderbook |
id | string | The market to subscribe to e.g. BTC-USD, LINK-USD |
includeOffsets (optional) | boolean | If specified, this will return an initial response with per-price level offsets |
Initial Response:
The initial response will contain the state of the orderbook and will be the same structure as GET /v3/orderbook/:market
. If includeOffsets
is sent and set to true in the subscription message, there will be an offset included for each price level. (See the example included)
field | description |
---|---|
type | will be subscribed |
channel | the channel name, i.e. v3_orderbook |
id | the market subscribed to e.g. BTC-USD |
contents | the message contents |
The contents is structured as:
field | type | description |
---|---|---|
offset | string | A number used for ordering. See offset below. |
bids | array |
See PublicOrder below. Sorted by price in descending order |
asks | array |
See PublicOrder below. Sorted by price in ascending order |
PublicOrder:
field | type | description |
---|---|---|
price | string | human readable price of the order (in quote / base currency) |
size | string | human readable size of the order (in base currency) |
offset | string | (if includeOffsets is set to true) the offset for the specific price |
Offset:
The price updates are not guaranteed to be sent in order. So it is possible to receive an older price update later. For this reason, the offset is included in the message, to help order. The offset increases monotonically, and increasing values of offsets indicate more recent values.
Example messages:
Example initial response:
{
"type": "subscribed",
"connection_id": "87b25218-0170-4111-bfbf-d9f0a506fcab",
"message_id": 1,
"channel": "v3_orderbook",
"id": "ETH-USD",
"contents": {
"bids": [
{
"price": "1779",
"size": "11.24"
},
{
"price": "1778.5",
"size": "18"
}
],
"asks": [
{
"price": "1782.8",
"size": "10"
},
{
"price": "1784",
"size": "2.81"
}
]
}
}
Example initial response if
includeOffsets
is set to true:
Request:
{
"type": "subscribe",
"channel": "v3_orderbook",
"id": "ETH-USD",
"includeOffsets": "true"
}
Response:
{
"type": "subscribed",
"connection_id": "14f7c481-1e1f-4f5c-8c5c-7b114209d8ce",
"message_id": 1,
"channel": "v3_orderbook",
"id": "ETH-USD",
"contents": {
"bids": [
{
"price": "1778.8",
"offset": "36850163",
"size": "11"
},
{
"price": "1776.7",
"offset": "36849225",
"size": "5.9"
}
],
"asks": [
{
"price": "1783",
"offset": "36848764",
"size": "13"
},
{
"price": "1784",
"offset": "36848433",
"size": "4.3"
}
]
}
}
Channel Data
Subsequent responses will contain the new order sizes for any price levels that have changed since the previous update:
e.g:
Subsequent messages
{
"type": "channel_data",
"id": "BTC-USD",
"connection_id": "e2a6c717-6f77-4c1c-ac22-72ce2b7ed77d",
"channel": "v3_orderbook",
"message_id": 2,
"contents": {
"offset": "178",
"bids": [["102", "12"]],
"asks": [["104", "0" ]]
}
}
E.g: if some orders at "102" price, get filled, then the update would be ["102", "12"], where "12" is the new size. If there are no more asks at "104", then the ask update would be ["104", "0"].
Trades
To subscribe:
field | type | description |
---|---|---|
type | string | Set to subscribe |
channel | string | Set to v3_trades |
id | string | The market to subscribe to e.g. BTC-USD, LINK-USD |
Initial Response:
The initial response will contain the historical trades and will be the same structure as GET /v3/trades/:market
.
field | description |
---|---|
type | will be subscribed |
channel | the channel name, i.e. v3_trades |
id | the market subscribed to e.g. BTC-USD |
contents | the message contents |
The contents is structured as:
field | type | description |
---|---|---|
trades | array |
See PublicTrade below. |
PublicTrade:
field | type | description |
---|---|---|
side | string | BUY or SELL |
size | string | size of the trade |
price | string | price of the trade |
createdAt | ISO time of the trade | time of the trade |
Example messages:
Example initial response:
{
"type": "subscribed",
"id": "BTC-USD",
"connection_id": "e2a6c717-6f77-4c1c-ac22-72ce2b7ed77d",
"channel": "v3_trades",
"message_id": 1,
"contents": {
"trades": [
{
"side": "BUY",
"size": "100",
"price": "4000",
"createdAt": "2020-10-29T00:26:30.759Z"
},
{
"side": "BUY",
"size": "100",
"price": "4000",
"createdAt": "2020-11-02T19:45:42.886Z"
},
{
"side": "BUY",
"size": "100",
"price": "4000",
"createdAt": "2020-10-29T00:26:57.382Z"
}
]
}
}
Channel Data
Subsequent responses will contain the recently created trades. e.g:
Subsequent responses
{
"type": "channel_data",
"id": "BTC-USD",
"connection_id": "e2a6c717-6f77-4c1c-ac22-72ce2b7ed77d",
"channel": "v3_trades",
"message_id": 2,
"contents": {
"trades": [
{
"side": "BUY",
"size": "100",
"price": "4000",
"createdAt": "2020-11-29T00:26:30.759Z"
},
{
"side": "SELL",
"size": "100",
"price": "4000",
"createdAt": "2020-11-29T14:00:03.382Z"
}
]
}
}
Markets
To subscribe:
field | type | description |
---|---|---|
type | string | Set to subscribe |
channel | string | Set to v3_markets |
Initial Response:
Same as GET /v3/markets
Channel Data
Subsequent responses will contain an update for one or more markets. Updates will be sent any time a field(s) changes on a market(s). Updates will only contain the field(s) that have changed:
Subsequent responses
{
"type": "channel_data",
"connection_id": "e2a6c717-6f77-4c1c-ac22-72ce2b7ed77d",
"channel": "v3_markets",
"message_id": 2,
"contents": {
"ETH-USD": {
"oraclePrice": "100.23"
},
"BTC-USD": {
"indexPrice": "100.23",
"priceChange24H": "0.12",
"initialMarginFraction": "1.23"
}
}
}
Security
Independent Audits
The Starkware Perpetual smart contracts were audited independently by PeckShield.
Vulnerability Disclosure Policy
The disclosure of security vulnerabilities helps us ensure the security of our users.
How to report a security vulnerability?
If you believe you’ve found a security vulnerability in one of our contracts or platforms, send it to us by emailing [email protected]. Please include the following details with your report:
A description of the location and potential impact of the vulnerability.
A detailed description of the steps required to reproduce the vulnerability.
Scope
Any vulnerability not previously disclosed by us or our independent auditors in their reports.
Guidelines
We require that all reporters:
Make every effort to avoid privacy violations, degradation of user experience, disruption to production systems, and destruction of data during security testing.
Use the identified communication channels to report vulnerability information to us.
Keep information about any vulnerabilities you’ve discovered confidential between yourself and dYdX until we’ve had 30 days to resolve the issue.
If you follow these guidelines when reporting an issue to us, we commit to:
Not pursue or support any legal action related to your findings.
Work with you to understand and resolve the issue quickly (including an initial confirmation of your report within 72 hours of submission).
Grant a monetary reward based on the OWASP risk assessment methodology.