NAV

TypeScript Python HTTP

Introduction

What is dYdX?

dYdX is a decentralized trading platform that currently supports margin trading, spot trading, lending, and borrowing. dYdX runs on smart contracts on the Ethereum blockchain, and allows users to trade with no intermediaries.

dYdX Features

Trading on dYdX

Borrowing on dYdX

Lending on dYdX

API

Amounts

Amounts are represented as integers in the base unit of the token or currency. To convert an amount to the units used by dYdX, the amount should be shifted by a certain number of decimals depending on the asset:

Example: A USDC amount of 9605161500 represents a value of 9605.1615 USDC.

Rate Limits

If greater than 100 requests are made in 10 seconds, requests will be blocked for one minute.

Clients

dYdX offers clients in Typescript and in Python. These allow programmatic usage of dYdX.

To trade on dYdX, users must first deposit funds into their relevant account. On dYdX, you have your Spot account, Margin account, and then a separate account for each Perpetual. Offering portfolio margining across these products is something the team will be looking into in the future.

For Spot and Margin, traders will need to use the Solo API and for Perpetual, users will need to use the Perpetual API.

TypeScript Client

Solo TypeScript Client


GitHub NPM Package

TypeScript library for interacting with the dYdX Solo smart contracts and HTTP API.

Install

npm i -s @dydxprotocol/solo

API

Uses Solo Api.

Perpetual TypeScript Client


GitHub NPM Package

TypeScript library for interacting with the dYdX Perpetual smart contracts and HTTP API.

Install

npm i -s @dydxprotocol/perpetual

API

Uses Perpetual Api.

Python Client


GitHub PyPi

dYdX Python API for Limit Orders.

The library is currently tested against Python versions 2.7, 3.4, 3.5, and 3.6.

Installation

dydx-python is available on PyPI. Install with pip: pip install dydx-python

API

Uses Solo Api and Perpetual Api.

Client Initialization

Solo Initialize

Initialize

import { Solo, Networks } from '@dydxprotocol/solo';

// --- Initialize with Web3 provider ---
const solo = new Solo(
  provider,
  Networks.MAINNET,
  {
    defaultAccount: '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
    accounts: [
      {
        address: '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
        privateKey: '0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d',
      },
    ],
  }, // Optional
);

// --- OR Initialize with Ethereum node endpoint ---
const solo = new Solo(
  'https://mainnet.infura.io/v3/YOUR-PROJECT-ID',
  Networks.MAINNET,
  {
    defaultAccount: '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
    accounts: [
      {
        address: '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
        privateKey: '0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d',
      },
    ],
  }, // Optional
);
from dydx.client import Client
import dydx.constants as consts
import dydx.util as utils

# create a new Python client with a private key (string or bytearray)
# Only one Python client is needed for both Solo and Perpetual API
client = Client(
    private_key='0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d',
    node='https://mainnet.infura.io/v3/00000000000000000000000000000000'
)

You will need to initialize Solo using a Web3 provider / Ethereum node endpoint and an Ethereum network ID.

Parameter Description
provider web3 provider.
networkId An Ethereum network ID, recommended is Networks.MAINNET.
options.defaultAccount (Optional) Address of account to use by default for signing transactions.
options.accounts (Optional) List of accounts with address and privateKey for signing orders and transactions.

A full list of options can be found here.















Perpetual Initialize

Initialize

import { Perpetual, PerpetualMarket, Networks } from '@dydxprotocol/perpetual';
// --- Initialize with Web3 provider ---
const perpetual = new Perpetual(
  provider,
  PerpetualMarket.PBTC_USDC,
  Networks.MAINNET, // Optional
  {
    defaultAccount: '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
    accounts: [
      {
        address: '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
        privateKey: '0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d',
      },
    ],
  }, // Optional
);
from dydx.client import Client
import dydx.constants as consts
import dydx.util as utils

# create a new Python client with a private key (string or bytearray)
# Only one Python client is needed for both Solo and Perpetual API
client = Client(
    private_key='0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d',
    node='https://mainnet.infura.io/v3/00000000000000000000000000000000'
)

You will need to initialize Perpetual using a Web3 provider / Ethereum node endpoint. Additionally you must specifiy a perpetual market, e.g. PBTC-USDC or WETH-PUSD. You must create a new Perpetual object for each market you wish to trade.

Parameter Description
provider web3 provider.
market A perpetual market, e.g. PerpetualMarket.PBTC_USDC.
networkId (Optional) An Ethereum network ID, default is Networks.MAINNET.
options.accounts A list of accounts with address and privateKey used to sign orders and transactions.

A full list of options can be found here.

The following Perpetual markets are available:

Market pair Variable name
PBTC-USDC PerpetualMarket.PBTC_USDC
WETH-PUSD PerpetualMarket.WETH_PUSD

Account API

dYdX is a non-custodial exchange. This means that your funds are either in your own wallet, or in a "smart contract" which is a program that runs on the Ethereum Blockchain.

dYdX does not have any user accounts (and does not require any formal sign-up). Instead, you can instantly use dYdX by using your own Ethereum wallet to send transactions to the blockchain.

Interest Rates

Interest rates are "floating," which mean that they are dynamic and updated instantly depending on demand. This also means that rates are never "locked-in" at the time of opening a position and may change over the course of it being open.

There are separate rates for borrowing and lending per asset. The rates move based on utilization, which is the ratio of "amount borrowed" to "amount lent." As utilization increases, the interest rate will increase to incentivize more lenders. As utilization decreases, the interest rate decreases.

Pending Balances

When trades are in pending the sum of the change in balance for each asset that will occur when all trades are confirmed is shown as its pending balance. Pending balances are atomically removed and added to live account balances when trades confirm.

Account Initialization

Set Solo Allowance

Set Token Allowance

await solo.token.setMaximumSoloAllowance(
  '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359',
  '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5', // My Address
  { from: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5' }, // My Address
);
tx_hash = client.eth.solo.set_allowance(market=consts.MARKET_DAI) # must only be called once, ever
receipt = client.eth.get_receipt(tx_hash)

tx_hash = client.eth.solo.set_allowance(market=consts.MARKET_USDC) # must only be called once, ever
receipt = client.eth.get_receipt(tx_hash)

Setting an allowance authorizes the Smart Contract to transfer your tokens according to the ERC20 specification. This is necessary to begin depositing tokens.

Solo provides helper functions to help with interacting with ERC20 tokens. You can find them all here.

Example of setting DAI token allowance on Solo:

Parameter Description
tokenAddress Address of token contract.
ownerAddress Address of the token owner (not needed for Python).
options (Optional): SendOptions for the allowance.

Set Perpetual Allowance

Set Token Allowance

await perpetual.token.setMaximumPerpetualAllowance(
  '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359',
  '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5', // My Address
  { from: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5' }, // My Address
);
tx_hash = client.eth.perp.set_allowance(consts.PAIR_PBTC_USDC) # must only be called once, ever
receipt = client.eth.get_receipt(tx_hash)

Setting an allowance authorizes the Smart Contract to transfer your tokens according to the ERC20 specification. This is necessary to begin depositing tokens.

This does not have to be set before depositing ETH unless you are using WETH (The ERC20 "Wrapped Ether").

Perpetual provides helper functions to help with interacting with ERC20 tokens. You can find them all here.

Example of setting DAI token allowance on Solo:

Parameter Description
tokenAddress Address of token contract (currently not needed for Python).
ownerAddress Address of the token owner (not needed for Python).
options (Optional): SendOptions for the allowance.

Deposit / Withdraw to Spot Account

Deposit

Deposit

import { MarketId, BigNumber, AccountNumbers } from '@dydxprotocol/solo';

const result = await solo.standardActions.deposit({
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: AccountNumbers.SPOT,
  marketId: MarketId.DAI,
  amount: new BigNumber('1e18'),
});
# Client account_number had to be set to consts.ACCOUNT_NUMBERS_SPOT
# deposit 100 DAI
tx_hash = client.eth.solo.deposit(
  market=consts.MARKET_DAI,
  wei=utils.token_to_wei(100, consts.MARKET_DAI)
)
receipt = client.eth.get_receipt(tx_hash)

Deposit funds to dYdX

Parameter Description
accountOwner Your address.
marketId Specified token for some asset.
amount Base units of the token, so 1e18 = 1 ETH. USDC has 6 decimal places, so 1e6 = 1 USDC.
accountNumber (Optional): specific accountNumber for deposit, defaults to zero if not specified (Set in initialization for Python).
options (Optional): SendOptions for the deposit.

Withdraw

Withdraw

import { MarketId, BigNumber } from '@dydxprotocol/solo';

const result = await solo.standardActions.withdraw({
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: AccountNumbers.SPOT,
  marketId: MarketId.DAI,
  amount: new BigNumber('1e18'),
});
# Client account_number had to be set to consts.ACCOUNT_NUMBERS_SPOT
# withdraw 100 DAI
tx_hash = client.eth.solo.withdraw(
  amount=utils.token_to_wei(100, consts.MARKET_DAI)
)
receipt = client.eth.get_receipt(tx_hash)

Withdraw funds from dYdX.

Parameter Description
accountOwner Your address.
marketId Specified token for some asset.
amount Base units of the token, so 1e18 = 1 ETH. USDC has 6 decimal places, so 1e6 = 1 USDC.
accountNumber (Optional): specific accountNumber for deposit, defaults to zero if not specified (Set in initialization for Python).
options (Optional): SendOptions for the deposit.

Deposit / Withdraw to Margin Account

Deposit

Deposit

import { MarketId, BigNumber } from '@dydxprotocol/solo';

// accountNumber could have been set to AccountNumbers.MARGIN
const result = await solo.standardActions.deposit({
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  marketId: MarketId.ETH,
  amount: new BigNumber('1e18'),
});
# Client account_number had to be not set or set to consts.ACCOUNT_NUMBERS_MARGIN
# deposit 10 WETH ERC20 tokens without using the WETH payable proxy address
# requires set_allowance
tx_hash = client.eth.solo.deposit(
  market=consts.MARKET_WETH,
  wei=utils.token_to_wei(10, consts.MARKET_WETH),
  asEth=False
)
receipt = client.eth.get_receipt(tx_hash)

Deposit funds to dYdX

Parameter Description
accountOwner Your address.
marketId Specified token for some asset.
amount Base units of the token, so 1e18 = 1 ETH. USDC has 6 decimal places, so 1e6 = 1 USDC.
accountNumber (Optional): specific accountNumber for deposit, defaults to zero if not specified (Set in initialization for Python).
options (Optional): SendOptions for the deposit.

Withdraw

Withdraw

import { MarketId, BigNumber } from '@dydxprotocol/solo';

// accountNumber could have been set to AccountNumbers.MARGIN
const result = await solo.standardActions.withdraw({
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  marketId: MarketId.ETH,
  amount: new BigNumber('1e18'),
});
# Client account_number had to be not set or set to consts.ACCOUNT_NUMBERS_MARGIN
# withdraw 10 WETH ERC20 tokens without using the WETH payable proxy address
tx_hash = client.eth.solo.deposit(
  market=consts.MARKET_WETH,
  wei=utils.token_to_wei(10, consts.MARKET_WETH),
  asEth=False
)
receipt = client.eth.get_receipt(tx_hash)

Withdraw funds from dYdX.

Parameter Description
accountOwner Your address.
marketId Specified token for some asset.
amount Base units of the token, so 1e18 = 1 ETH. USDC has 6 decimal places, so 1e6 = 1 USDC.
accountNumber (Optional): specific accountNumber for deposit, defaults to zero if not specified (Set in initialization for Python).
options (Optional): SendOptions for the deposit.

Withdraw To Zero

Withdraw to Zero

import { MarketId, BigNumber } from '@dydxprotocol/solo';

const result = await solo.standardActions.withdrawToZero({
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  marketId: MarketId.ETH,
});
# withdraw all DAI (including interest)
tx_hash = client.eth.solo.withdraw_to_zero(market=consts.MARKET_DAI)
receipt = client.eth.get_receipt(tx_hash)

Withdraw all of your funds for some asset from dYdX.

Parameter Description
accountOwner Your address.
marketId Specified token for some asset.
accountNumber (Optional): specific accountNumber for deposit, defaults to zero if not specified.
options (Optional): SendOptions for the deposit.

Deposit / Withdraw to Perpetual Account

Deposit

Deposit

import { MarketId, BigNumber } from '@dydxprotocol/solo';

const result = await perpetual.margin.deposit({
  account: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  amount: new BigNumber('1e6'),
});
# deposit 100 USDC into the BTC-USD Perpetual
tx_hash = client.eth.perp.deposit(
  market=consts.PAIR_PBTC_USDC,
  amount=utils.token_to_wei(100, consts.MARKET_USDC)
)
receipt = client.eth.get_receipt(tx_hash)

Deposit funds to dYdX.

Parameter Description
account Your Perpetual address.
amount Base units of the token. USDC has 6 decimal places, so 1e6 = 1 USDC.
options (Optional): SendOptions for the deposit.

Withdraw

Withdraw

import { MarketId, BigNumber } from '@dydxprotocol/solo';

const result = await perpetual.margin.withdraw({
  account: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  destination: '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
  amount: new BigNumber('1e6'),
});
# withdraw 50 USDC from the BTC-USD Perpetual
tx_hash = client.eth.perp.withdraw(
  market=consts.PAIR_PBTC_USDC,
  amount=utils.token_to_wei(50, consts.MARKET_USDC)
)
receipt = client.eth.get_receipt(tx_hash)

Withdraw funds from dYdX.

Parameter Description
accountOwner Your Perpetual address.
destination Address to send withdrawal to.
amount Base units of the token. USDC has 6 decimal places, so 1e6 = 1 USDC.
options (Optional): SendOptions for the deposit.

Solo Get Account Balances

Get Account Balances

const account: ApiAccount = await solo.api.getAccountBalances({
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: new BigNumber(0),
});
my_balances = client.get_my_balances()
{
  "owner": "0x0913017c740260fea4b2c62828a4008ca8b0d6e4",
  "number": "0",
  "uuid": "72cd6a2a-17ff-4394-92d3-e951a96aa266",
  "balances": {
    "0": {
      "owner": "0x0913017c740260fea4b2c62828a4008ca8b0d6e4",
      "number": "0",
      "marketId": 0,
      "accountUuid": "72cd6a2a-17ff-4394-92d3-e951a96aa266",
      "wei": "10000184397123234.892111593021043502",
      "pendingWei": "20000184397123234.892111593021043502",
      "expiresAt": null,
      "par": "9994719126810778"
    },
    "1": {
      "par": 0,
      "wei": 0,
      "expiresAt": null
    },
    "2": {
      "par": 0,
      "wei": 0,
      "expiresAt": null
    }
  }
}

HTTP Request

GET https://api.dydx.exchange/v1/accounts/0x0913017c740260fea4b2c62828a4008ca8b0d6e4

Description:

Get Solo account balances for a particular account owner. This endpoint can also be used to get pending balances for an account corresponding to pending fills.

Note: To get any account's collateralization, simply take sumSupplyUsdValue / sumBorrowUsdValue. The minimum collateralization where liquidation occurs on the protocol using this formula is 1.15.

Request Fields

Parameter Description
accountOwner Your address.
accountNumber (Optional): specific accountNumber for deposit, defaults to zero if not specified.

Account Response Object

Field Name Description
owner The user's wallet address.
number The account number.
balances A map from marketIds to the balances for each market.
par The par for the account.
wei The wei for the account.
pendingWei The (pending) wei due to a fill that is still waiting to be confirmed.

Solo Get All Account Balances

Response

{
  "accounts": [
    {
      "owner": "0xc8e764dd559e3a6e0a433450a33dbbce83bc52d4",
      "number": "0",
      "uuid": "00006789-5921-4150-a392-4e6c5abc0043",
      "balances": {
        "0": {
          "marketId": 0,
          "par": "0",
          "wei": "0",
          "pendingWei": "0",
          "expiresAt": null,
          "orderNumber": null,
          "expiryAddress": null,
          "expiryOrderNumber": null
        },
        "1": {
          "marketId": 1,
          "par": "0",
          "wei": "0",
          "pendingWei": "0",
          "expiresAt": null,
          "orderNumber": null,
          "expiryAddress": null,
          "expiryOrderNumber": null
        },
        "2": {
          "marketId": 2,
          "par": "0",
          "wei": "0",
          "pendingWei": "0",
          "expiresAt": null,
          "orderNumber": null,
          "expiryAddress": null,
          "expiryOrderNumber": null
        },
        "3": {
          "marketId": 3,
          "par": "49696227095077403931903",
          "wei": "50862611748306230192199",
          "expiresAt": null,
          "expiryAddress": null
        }
      }
    }
  ]
}

HTTP Request:

GET https://api.dydx.exchange/v1/accounts

Description:

This endpoint returns balances for all the solo accounts.

Query Params:

parameter name description
isLiquidatable (Optional) returns all accounts that are at risk of under-collateralization.
isExpired (Optional) returns all accounts that have at least one balance that has expired and is negative.
isMigratable (Optional) returns all accounts that have SAI balance (positive or negative).

Accounts Response Object

Field Name Description
accounts An array of balances for each owner and account number.
owner The user's wallet address.
number The account number.
balances A map from marketIds to the balances for each market.
par The par for the account.
wei The wei for the account.
pendingWei The (pending) wei due to a fill that is still waiting to be confirmed.

Solo Get Balance Updates

Response

{
  "balanceUpdates": [
    {
      "uuid": "3920e9df-6260-4196-8d5d-ea3a65e05e16",
      "deltaWei": "139940891786496509",
      "newPar": "320499592695509982",
      "isLiquidate": false,
      "accountUuid": "fb8cb2a7-0910-406f-9ebd-41cb9b267a63",
      "actionUuid": null,
      "marketId": 0,
      "expiresAt": null,
      "orderNumber": "1011061200670003",
      "newWei": "320945032193181973.270328870120749488",
      "confirmedAt": "2020-05-21T17:34:22.000Z",
      "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
      "number": "0",
      "isPendingBlock": false,
      "createdAt": "2020-05-21T17:35:57.244Z",
      "updatedAt": "2020-05-21T17:35:57.244Z"
    },
    {
      "uuid": "9312921e-a53e-417f-b672-75a0d1943de8",
      "deltaWei": "-139940891786496509",
      "newPar": "0",
      "isLiquidate": false,
      "accountUuid": "836a4fdc-c994-450e-a07b-830ed37716ce",
      "actionUuid": null,
      "marketId": 0,
      "expiresAt": null,
      "orderNumber": "1011061200670003",
      "newWei": "0",
      "confirmedAt": "2020-05-21T17:34:22.000Z",
      "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
      "number": "72726098636314491067235956043692261150608981229613064856905296785781912974936",
      "isPendingBlock": false,
      "createdAt": "2020-05-21T17:35:57.243Z",
      "updatedAt": "2020-05-21T17:35:57.243Z"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/balance-updates?owner=0x77A035b677D5A0900E4848Ae885103cD49af9633&limit=2

Description:

This endpoint returns the last 100 balance updates for an address. Balance updates will come in as new transactions get posted and will show the (new par and new wei)[#wei-amp-par] for the accounts. The isPendingBlock indicates if the update is on a pending block or is confirmed.

Query Parameters

Field Description
owner the account address.
number (Optional) the account number.
orderNumberBefore (Optional) used for querying balance updates before a certain time. (orderNumber is used for ordering updates).
limit (Optional) the number of balance updates to return (max 100).

Balance Updates Response object

Field Description
balanceUpdates An array of the balance update objects.
uuid Unique identifier for a balance update.
deltaWei The change in wei in a balance update.
newPar The new par value due to the balance update.
newWei The new wei value due to the balance update.
orderNumber Used for ordering a balance update.
isPendingBlock Whether the balance update is still pending.
owner The account address.
number The account number.
marketId The id of the market for this balance update.
confirmedAt The ISO 8601 date and time this balance update was confirmed.
createdAt The ISO 8601 date and time this balance update was created.
updatedAt The ISO 8601 date and time this balance update was updated.

Perpetual Get Account Balances

Get Account Balances

const result = await perpetual.api.getAccountBalances({
  account: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
});
result = client.get_perpetual_balances(
  address='0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
)
{
  "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
  "balances": {
    "PBTC-USDC": {
      "cachedMargin": "40181034",
      "margin": "40169512",
      "position": "10000",
      "pendingMargin": "0",
      "pendingPosition": "0",
      "indexValue": "0.057858741951992068",
      "indexTimestamp": "1588271672"
    },
    "WETH-PUSD": {
      "cachedMargin": "40181034",
      "margin": "40169512",
      "position": "10000",
      "pendingMargin": "0",
      "pendingPosition": "0",
      "indexValue": "0.057858741951992068",
      "indexTimestamp": "1588271672"
    },
  }
}

HTTP Request:

GET https://api.dydx.exchange/v1/perpetual-accounts/0x77A035b677D5A0900E4848Ae885103cD49af9633

Description:

This endpoint takes in the user's walletAddress, and returns balances for the account.

Query Params:

Field Name Description
walletAddress The perpetual account to look up balances for.

Account Response Object

Field Name Description
owner The user's wallet address.
balances A mapping of the market to the balances for that market.
margin This is calculated as cachedMargin - (indexValue - globalIndexValue) * position.
position The balance in position token (e.g. PBTC).
cachedMargin This is the last stored margin value.
pendingMargin This is the (pending) component of the margin when a fill is still pending.
pendingPosition This is the (pending) component of the position when a fill is still pending.
indexValue The value of the global index from the last interaction with the account.
indexTimestamp The timestamp when the index value was set.

Perpetual Get All Account Balances

Response

{
  "accounts": [
    {
      "owner": "0x000f7f22bfc28d940d4b68e13213ab17cf107790",
      "market": "PBTC-USDC",
      "orderNumber": "1011196300330012",
      "cachedMargin": "36759577102",
      "margin": "36759577102",
      "position": "1201838526",
      "cachedIndexValue": "1.211642619304704688",
      "indexTimestamp": "1590100515"
    },
    {
      "owner": "0x003f480be5b68c5e863d2990d043f3b58f64473f",
      "market": "PBTC-USDC",
      "orderNumber": "1010984800560005",
      "cachedMargin": "368456014",
      "margin": "368468282",
      "position": "-3000000",
      "cachedIndexValue": "1.207553221962107213",
      "indexTimestamp": "1590072186"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/perpetual-accounts

Description:

This endpoint returns balances for all perpetual accounts.

Query Params:

Field Name Description
isLiquidatable (Optional) If set to true, returns accounts that are below the margin requirement.

Account Response Object

Field Name Description
owner The user's wallet address.
balances An object with the user's balances for each market.
margin This is calculated as cachedMargin - (indexValue - globalIndexValue) * position.
position The balance in position token (e.g. PBTC).
cachedMargin This is the last stored margin value.
pendingMargin This is the (pending) component of the margin when a fill is still pending.
pendingPosition This is the (pending) component of the position when a fill is still pending.
indexValue The value of the global index from the last interaction with the account.
indexTimestamp The timestamp when the index value was set.

Perpetual Get Balance Updates

Response

{
  "balanceUpdates": [
    {
      "uuid": "35f3d8cc-22a9-447e-b0b6-051f3e7272b7",
      "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
      "market": "PBTC-USDC",
      "deltaMargin": "89957950",
      "newMargin": "130127513",
      "deltaPosition": "-1000000",
      "newPosition": "-990000",
      "indexValue": "1.204924898727124293",
      "indexTimestamp": "1590089676",
      "isPendingBlock": false,
      "orderNumber": "1011116901510002",
      "createdAt": "2020-05-21T19:36:03.270Z",
      "updatedAt": "2020-05-21T19:36:03.270Z"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/perpetual-balance-updates?owner=0x77A035b677D5A0900E4848Ae885103cD49af9633&limit=1

Description:

Obtains the latest 100 perpetual balance updates. Balance updates will come in as new transactions get posted and will show the deltaMargin, newMargin, and deltaPosition for the accounts. These are the changes and the new values of the settlement and margin tokens of the balance. In the case of PBTC-USDC, PBTC is the position and USDC is the margin. The isPendingBlock indicates if the update is on a pending block or is confirmed.

Query Params:

Field Name Description
owner The wallet address of the user.
orderNumberBefore (Optional) Used to return balance updates before an orderNumber.
limit (Optional) The maximum number of balance updates to retrieve. (max is 100).

Perpetual Balance Update Response Object:

Field Name Description
balanceUpdates An array of the balance update objects.
uuid The unique ID for the balance update.
owner The wallet address of the user.
market The perpetual market, e.g. PBTC-USDC.
deltaMargin The change in settlement token (e.g. USDC).
newMargin The new balance of settlement token (e.g. USDC).
deltaPosition The change in position token (e.g. PBTC).
newPosition The amount in position token (e.g. PBTC).
indexValue The new index value of the account.
indexTimestamp The timestamp for when the index value was set.
orderNumber Number used for ordering the balance updates.
isPendingBlock Whether the specific balance update is pending or not.

Trading API

There are three trading offerings on dYdX: Spot, Margin and Perpetuals.

To trade on dYdX, users must first deposit funds into their relevant account. On dYdX, you have your Spot account, Margin account, and then a separate account for each Perpetual. Offering portfolio margining across these products is something the team will be looking into in the future.

Spot

dYdX offers three spot markets: ETH-DAI, ETH-USDC and DAI-USDC. Once on the Spot tab, you can trade freely using market, limit and stop orders.

Margin

dYdX offers margin trading on the same three spot markets with up to 5x leverage. Margin trading can be accessed on the Margin tab, where you choose either the 'Isolated' or 'Cross' mode on the trading sidebar. Here is a great place to start if you're getting started.

Perpetuals

dYdX offers Perpetual Contract Markets that allow up to 10x leverage on synthetic assets with no expiry. The first of which is a BTC-USDC market. All Perpetual markets are listed on the Perpetuals tab.

About the Orderbook

This orderbook is what's sometimes referred to as a "Matching Model" orderbook. This means that all orders are submitted to the blockchain by dYdX itself. You do not need to provide gas fees or send on-chain transactions yourself. This is especially useful for traders and market makers who wish to be able to quickly cancel their orders without waiting for a transaction to be mined.

Matching Specification

Order Matching (pseudocode)

const trades = [];

for (makerOrder in orderbook) {
  if (takerOrder.crosses(makerOrder)) {
    if (trades.length < 10) {
      trades.push(makeTrade(takerOrder, makerOrder));
    } else {
      // Find the smallest sized trade from trades
      smallestTrade = trades.findSmallestTrade();

      if (smallestTrade.size < makerOrder.remainingSize) {
        // If the smallest trade in trades is smaller than the current
        // maker order's remaining amount, replace it with makerOrder
        trades = trades.removeTrade(smallestTrade);
        trades.push(makeTrade(takerOrder, makerOrder));
      }
    }
  } else {
    sendFillTransaction(trades);
    return;
  }

  if (orderEntirelyFilled(takerOrder)) {
    sendFillTransaction(trades);
    return;
  }
}

All orders are routed through our central matching engine. Orders are matched first by price, then by time priority.

When orders are matched, our matching engine sends a fill transaction to the Ethereum blockchain. Once this transaction is mined, balances are updated reflecting the trades.

It is possible that fill transactions can revert, though this should be very rare. When fill transactions revert, trades are not executed and balances are not updated. On reverts, unless an order has specified the cancelAmountOnRevert flag, it will be re-placed onto the orderbook (which could cause another fill to be executed).

A maximum of 10 orders can be matched at a time (due to the Ethereum block gas limit). If a taker order is large enough such that the first 10 maker orders on the orderbook are not large enough to fully fill the taker order, and there exist worse-priced orders that would also match the taker order, orders are matched as described in the “Order Matching” algorithm.

Prices

A price is represented as a rate of conversion between the base units of each asset. Prices in dYdX must therefore be shifted by taking into account the decimals used by each asset.

For example, all PBTC-USDC prices are shifted by -2 decimals since the base currency has 8 decimals and the quote currency has 6 decimals. If the price of PBTC-USDC is externally represented as 9500.75 then it will be represented within the dYdX API and smart contracts as 95.0075.

See Amounts for all asset decimal specifications.

Linear and Inverse Perpetuals

Two different types of perpetual products are offered: linear and inverse. The primary difference is that in linear perpetuals, profit and loss are settled in the quote asset, whereas in inverse perpetuals, profit and loss are settled in the base asset. There are some secondary differences between the two in how prices and amounts are represented, which traders must be aware of.

These differences are outlined here:

  1. Order and fill amounts: The size of an order or fill is denominated in base currency for a linear perpetual and quote currency for an inverse perpetual.
  2. Margin and position: For a linear perpetual, margin balances refer to the quote currency and position balances refer to the base currency. For an inverse perpetual, margin balances refer to the base currency and position balances refer to the quote currency.
  3. Oracle price: The on-chain oracle price is represented in terms of margin units per unit of position. For an inverse perpetual, it is therefore inverted relative to other prices. This only affects the API with respect to prices explicitly designated as “oracle” prices, for example, as returned by the v1/perpetual-markets endpoint.

See this article for some discussion of the differences in trading linear and inverse perpetuals.

Initialization

Before using an asset, an account must set its allowance as a one-time setup. This is not necessary for ETH/WETH since, unlike, ERC-20 tokens, ETH is wrapped and deposited by a proxy contract.

Creating and Signing Orders

In order to submit an order, you (the maker) must first create a JSON object specifying the details of your order. You must then sign the order with your Ethereum private key, and put the result in the typedSignature field. Note that the typedSignature field is omitted before signing, and added only after signing the message.

When creating your order you must specify the takerAccountOwner as 0xf809e07870dca762B9536d61A4fBEF1a17178092 and the takerAccountNumber as 0, otherwise your order will be rejected.

After this is done, the order is ready to be submitted to the API.

Tick Size

Spot and Margin Tick Size

Perpetual Tick Size

Solo Place Order

Place Order(v2)

import { ApiSide, ApiMarketName, BigNumber } from '@dydxprotocol/solo';

// order has type ApiOrder
const { order } = await solo.api.placeCanonicalOrder({
  order: {
    side: ApiSide.BUY,
    market: ApiMarketName.WETH_DAI,
    amount: new BigNumber('1e18'),
    price: '230.1',
    makerAccountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
    expiration: new BigNumber('1000'),
    limitFee: '0.0015'
  }
  fillOrKill: false,
  postOnly: false,
  clientId: 'foo',
  cancelId: '0x2c45cdcd3bce2dd0f2b40502e6bea7975f6daa642d12d28620deb18736619fa2',
  cancelAmountOnRevert: false,
});
# Create order to BUY 10 ETH for 2504.90 DAI (a price of 250.49 DAI/ETH)
created_order = client.place_order(
    market=consts.PAIR_WETH_DAI,
    side=consts.SIDE_BUY,
    amount=utils.token_to_wei(10, consts.MARKET_WETH),
    price=Decimal('250.49'),
    fillOrKill=False,
    postOnly=False
)

# Create order to SELL 10 ETH for 1500.10 USDC (a price of 150.01 USDC/ETH)
# 'e-12' is in the price since USDC has 6 decimal places (ETH and DAI have 18)
created_order = client.place_order(
    market=consts.PAIR_WETH_USDC,
    side=consts.SIDE_SELL,
    amount=utils.token_to_wei(10, consts.MARKET_WETH),
    price=Decimal('150.01e-12'),
    fillOrKill=False,
    postOnly=False
)
// Request
{
  "fillOrKill": true,
  "cancelAmountOnRevert": true,
  "postOnly": false,
  "triggerPrice": "0",
  "clientId": "foo",
  "order": {
    "isBuy": true,
    "isDecreaseOnly": false,
    "baseMarket": "0",
    "quoteMarket": "3",
    "amount": "10000000000",
    "limitPrice": "20.3",
    "triggerPrice": "0",
    "limitFee": "0.0015",
    "makerAccountNumber": "0",
    "makerAccountOwner": "0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9",
    "expiration": "4294967295",
    "salt": "100",
    "typedSignature": "0xd9c006cf9066e89c2e75de72604751f63985f173ca3c69b195f1f5f445289a1f2229c0475949858522c821190c5f1ec387f31712bd21f6ac31e4510d5711c2681f00"
  }
}

// Response
{
  "order": {
    "uuid":"c8087842-b74c-4e29-8a3f-1c2207d4a758","id":"0x599bad2961e8daacf370d90f73e3545871c7b9095b5abb6a2ca7b1fe8889a6f6",
    "clientId":null,
    "status":"PENDING",
    "accountOwner":"0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9",
    "accountNumber":"0",
    "orderType":"CANONICAL_CROSS",
    "fillOrKill":false,
    "postOnly":false,
    "triggerPrice":null,
    "market":"WETH-DAI",
    "side":"BUY",
    "baseAmount":"1000000000000000000",
    "quoteAmount":"238610000",
    "filledAmount":"0",
    "price":"0.00000000023861",
    "cancelReason":null,
    "createdAt":"2020-07-06T19:41:55.109Z",
    "updatedAt":"2020-07-06T19:41:55.109Z",
    "expiresAt":"2020-08-03T19:56:53.000Z"
  }
}

// Error Response
{
  "errors":[
    {
      "accountOwner":"0x5f5a46a8471f60b1e9f2ed0b8fc21ba8b48887d8",
      "accountNumber":"0",
      "msg":"Order would put account under the collateralization threshold",
      "collateralization":"1.0371541260574773058718446738018714072784150319167023631923257642848763075472344","minCollateralization":"1.095"
    }
  ]
}

HTTP Request

POST https://api.dydx.exchange/v2/orders

Description: Post a new order to the orderbook.

Note:

Parameter Description
order.side Either BUY or SELL.
order.market Market to trade in.
order.amount An integer amount denominated in base units, e.g. 1 ETH = 1e18. Expressed in base currency for linear perpetuals and quote currency for inverse perpetuals.
order.price Denominated in quote per base in the appropriate price units.
order.address Your address. Account must be loaded onto Solo with private key for signing.
order.expiration (Optional): number of seconds until the order expires. 0 indicates no expiry. Defaults to 28 days.
order.limitFee (Optional): Maximum fee you are willing to accept.
fillOrKill (Optional): defaults to false.
postOnly (Optional): defaults to false.
clientId (Optional): defaults to undefined.
cancelId (Optional): Turns this order into a replace order with the cancelId being the replaced order.
cancelAmountOnRevert (Optional): defaults to false.

Perpetual Place Order

Place Order

import { ApiSide, ApiMarketName, BigNumber } from '@dydxprotocol/perpetual';
// order has type ApiOrder
const { order } = await perpetual.api.placePerpetualOrder({
  order: {
    side: ApiSide.BUY,
    amount: new BigNumber('1e8'),
    price: '72.00',
    maker: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
    taker: '0x7a94831b66a7ae1948b1a94a9555a7efa99cb426',
    expiration: new BigNumber('1000'),
    limitFee: '0.0075',
  }
  fillOrKill: false,
  postOnly: false,
  clientId: 'foo',
  cancelId: '0x2c45cdcd3bce2dd0f2b40502e6bea7975f6daa642d12d28620deb18736619fa2',
  cancelAmountOnRevert: false,
  market: ApiMarketName.PBTC_USDC,
});
# Create order to BUY 10 PBTC for 723,400.00 USDC (a price of 7234.00 PBTC/USDC)
created_order = client.place_order(
    market=consts.PAIR_PBTC_USDC,
    side=consts.SIDE_BUY,
    amount=utils.btc_to_sats(10),
    price=Decimal('72.34'),
    fillOrKill=False,
    postOnly=False
)
// Request
{
  "fillOrKill": true,
  "cancelAmountOnRevert": true,
  "postOnly": false,
  "triggerPrice": "0",
  "clientId": "foo",
  "market": "PBTC-USDC",
  "order": {
    "isBuy": true,
    "isDecreaseOnly": false,
    "amount": "10000000000",
    "limitPrice": "20.3",
    "triggerPrice": "0",
    "limitFee": "0.0015",
    "maker": "0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9",
    "taker": "0x7a94831b66a7ae1948b1a94a9555a7efa99cb426",
    "expiration": "4294967295",
    "salt": "100",
    "typedSignature": "0xd9c006cf9066e89c2e75de72604751f63985f173ca3c69b195f1f5f445289a1f2229c0475949858522c821190c5f1ec387f31712bd21f6ac31e4510d5711c2681f00"
  }
}

// Response
{
  "order":{
    "uuid":"56b3cf49-9e12-4585-97a4-f8cfe9efdbe8","id":"0x5870b74deb77bdd77574d8071495b0110734d938f1a963d2986756408df09afe",
    "clientId":null,
    "status":"PENDING",
    "accountOwner":"0x5f5a46a8471f60b1e9f2ed0b8fc21ba8b48887d8",
    "accountNumber":"0",
    "orderType":"PERPETUAL_CROSS",
    "fillOrKill":false,
    "postOnly":false,
    "triggerPrice":null,
    "market":"PBTC-USDC",
    "side":"BUY",
    "baseAmount":"100000000",
    "quoteAmount":"2000000",
    "filledAmount":"0",
    "price":"0.02",
    "cancelReason":null,
    "createdAt":"2020-07-06T19:37:30.996Z",
    "updatedAt":"2020-07-06T19:37:30.996Z",
    "expiresAt":"2020-08-03T19:52:29.000Z"
  }
}

HTTP Request

POST https://api.dydx.exchange/v2/orders

Perpetual provides an easy way to interact with dYdX http API endpoints. This is especially useful for placing & canceling orders.

Parameter Description
order.side Side your order is being placed on.
order.amount An integer amount denominated in base units, e.g. 1 BTC = 1e8.
order.price Denominated in quote per base in the appropriate price units.
order.maker Your address. Account must be loaded onto Perpetual with private key for signing.
order.taker Taker address. Account must be loaded onto Perpetual with private key for signing.
order.expiration (Optional): number of seconds until the order expires. 0 indicates no expiry. Defaults to 28 days.
order.limitFee (Optional): Maximum fee you are willing to accept.
fillOrKill (Optional): defaults to false.
postOnly (Optional): defaults to false.
clientId (Optional): defaults to undefined.
cancelId (Optional): Turns this order into a replace order with the cancelId being the replaced order.
cancelAmountOnRevert (Optional): defaults to false.
market Market to trade in.

Cancel Order

Cancel Order

// For margin/spot
const { id } = existingOrder;

// order has type ApiOrder
const { order } = await solo.api.cancelOrderV2({
  orderId: id,
  makerAccountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
});

// For perpetual
const { id } = existingOrder;

// order has type ApiOrder
const { order } = await perpetual.api.cancelOrderV2({
  orderId: id,
  makerAccountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
});
# For margin/spot
order_hash = created_order['order']['id']
canceled_order = client.cancel_order(
    hash=order_hash
)

# For perpetual
order_hash = created_order['order']['id']
canceled_order = client.cancel_perpetual_order(
    hash=order_hash
)
{
  "orders": [
    {
      "uuid": "ffb8f5e3-68aa-4dc9-89d2-1de6738b8c3f",
      "id": "0xd17ae8439b99c6c7637808be36d856c6f6f497ab132a7f394f611396b5594844",
      "createdAt": "2020-01-15T22:30:55.533Z",
      "status": "PENDING",
      "accountOwner": "0x998497ffc64240d6a70c38e544521d09dcd23293",
      "accountNumber": "0",
      "orderType": "PERPETUAL_CROSS",
      "fillOrKill": false,
      "postOnly": null,
      "market": "PBTC-USDC",
      "side": "BUY",
      "baseAmount": "50900000000000000000",
      "quoteAmount": "8386480372200000000000",
      "filledAmount": "0",
      "price": "231.763858",
      "cancelReason": null
    },
  ]
}

HTTP Request

DELETE https://api.dydx.exchange/v2/orders/0x998497ffc64240d6a70c38e544521d09dcd23293

Description: Cancels an open order by hash.

You will need to provide a valid cancelation signature in the Authorization header in order to cancel an order. The Authorization header signature should be hashed according to EIP-712 and include the original orderHash. See the Orders.ts Perpetual client module for reference implementations for signing perpetual order cancellations and the CanonicalOrders.ts Solo client module for reference implementations for signing margin/spot order cancellations.

The response will have a status of 200 as long as the order already existed and the signature is valid (even if the order is already unfillable for any reason). For example, if a user cancels an order twice, then 200 will be returned both times. As another example, canceling a fully-filled order will return 200 but will NOT update the status of the order from FILLED to CANCELED. Therefore, receiving a 200 status does not necessarily mean that the order was canceled.

Parameter Description
orderId Id of order to be canceled.
makerAccountOwner Your address.

A note about Order and Fill status

Both orders and fills returned from the API will provide a status field.

For orders this field represents the current status of the order.

Status Description
PENDING The order is not yet processed by our internal matching engine.
OPEN The order is open and can be filled.
FILLED The order has been completely filled.
PARTIALLY_FILLED The order has been partially filled.
CANCELED The order has been canceled and can no longer be filled.
FAILED The order failed to be processed due to an internal error.

If the order was canceled, additional information will be provided by the cancelReason field.

For fills the status field represents the status of the transaction on-chain.

Status Description
PENDING The fill has been sent to the blockchain but not yet mined.
REVERTED The fill was sent to the blockchain, but was reverted on-chain.
CONFIRMED The fill was sent to the blockchain and successfully mined.

To get pending balances related to fills in PENDING status, see Solo Get Account Balances.

Get Order

Get Order

// For margin/spot
const { id } = existingOrder;

const { order }: { order: ApiOrderV2 } = await solo.api.getOrderV2({ id });

// For perpetual
const { id } = existingOrder;

const { order }: { order: ApiOrderV2 } = await perpetual.api.getOrderV2({ id });
order = client.get_order(
  orderId,
)
{
  "order": {
    "uuid": "ffb8f5e3-68aa-4dc9-89d2-1de6738b8c3f",
    "id": "0xd17ae8439b99c6c7637808be36d856c6f6f497ab132a7f394f611396b5594844",
    "status": "OPEN",
    "clientId": null,
    "accountOwner": "0x998497ffc64240d6a70c38e544521d09dcd23293",
    "accountNumber": "0",
    "orderType": "CANONICAL_CROSS",
    "fillOrKill": false,
    "postOnly": false,
    "triggerPrice": null,
    "market": "WETH-DAI",
    "side": "BUY",
    "baseAmount": "50900000000000000000",
    "quoteAmount": "8386480372200000000000",
    "filledAmount": "0",
    "price": "164.763858",
    "cancelReason": null,
    "createdAt": "2020-06-15T22:30:55.533Z",
    "updatedAt": "2020-06-15T22:30:56.587Z",
    "expiresAt": "2020-06-15T23:30:57.000Z"
  }
}

HTTP Request

GET https://api.dydx.exchange/v2/orders/0xd17ae8439b99c6c7637808be36d856c6f6f497ab132a7f394f611396b5594844

Description: Get an order by id from the active orderbook and order history.

Parameter Description
id Id of order being fetched.

Get Orders

Get Orders

// For margin/spot
const { orders }: { orders: ApiOrderV2[] } = await solo.api.getOrdersV2({
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: '0',
  side: 'BUY',
  market: ['WETH-USDC', 'DAI-USDC'],
  status: ['OPEN', 'FILLED'],
  orderType: ['LIMIT', 'ISOLATED_MARKET'],
  limit: 40,
  startingBefore: new Date(),
});

// For perpetual
const { orders }: { orders: ApiOrderV2[] } = await perpetual.api.getOrdersV2({
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: '0',
  side: 'BUY',
  market: ['PBTC-USDC'],
  status: ['OPEN', 'FILLED'],
  orderType: ['PERPETUAL_CROSS', 'PERPETUAL_STOP_LIMIT'],
  limit: 40,
  startingBefore: new Date(),
});
# Get orders created by my account for both sides of the book
my_orders = client.get_my_orders(
    market=['WETH-DAI', 'DAI-WETH'],
    limit=None,
    startingBefore=None
)

# Get all orders for both sides of the book
ten_days_ago = datetime.datetime.now() - datetime.timedelta(days=10)
all_orders = client.get_orders(
    market=['WETH-DAI', 'DAI-WETH'],
    makerAccountOwner=None,  # optional
    makerAccountNumber=None,  # optional
    limit=2,  # optional
    startingBefore=ten_days_ago  # optional
)
{
  "orders": [
    {
      "uuid": "ffb8f5e3-68aa-4dc9-89d2-1de6738b8c3f",
      "id": "0xd17ae8439b99c6c7637808be36d856c6f6f497ab132a7f394f611396b5594844",
      "status": "OPEN",
      "clientId": null,
      "accountOwner": "0x998497ffc64240d6a70c38e544521d09dcd23293",
      "accountNumber": "0",
      "orderType": "CANONICAL_CROSS",
      "fillOrKill": false,
      "postOnly": false,
      "triggerPrice": null,
      "market": "WETH-DAI",
      "side": "BUY",
      "baseAmount": "50900000000000000000",
      "quoteAmount": "8386480372200000000000",
      "filledAmount": "0",
      "price": "164.763858",
      "cancelReason": null,
      "createdAt": "2020-06-15T22:30:55.533Z",
      "updatedAt": "2020-06-15T22:30:56.587Z",
      "expiresAt": "2020-06-15T23:30:57.000Z"
    },
    {
      "uuid": "da43af50-56dd-4884-a540-a7314a628b06",
      "id": "0xfb65cfa2ff31e5fbc6629da82cb0a2d7eefcf92ac8b00d94da4c541b60293e8f",
      "status": "OPEN",
      "clientId": null,
      "accountOwner": "0x998497ffc64240d6a70c38e544521d09dcd23293",
      "accountNumber": "0",
      "orderType": "CANONICAL_CROSS",
      "fillOrKill": false,
      "postOnly": false,
      "market": "WETH-DAI",
      "side": "BUY",
      "baseAmount": "50500000000000000000",
      "quoteAmount": "8323093314500000000000",
      "filledAmount": "0",
      "price": "164.813729",
      "cancelReason": null,
      "createdAt": "2020-06-17T22:30:55.498Z",
      "updatedAt": "2020-06-17T22:30:56.587Z",
      "expiresAt": "2020-06-17T23:30:57.000Z"

    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v2/orders

Description: Get orders from the active orderbook and order history.

Orders can be filtered on fields like market, status, and accepted order status, and are returned in descending order by createdAt. At most 100 orders are returned.

Parameter Description
accountOwner (Optional): wallet address of orders.
accountNumber (Optional): account number for the orders.
side (Optional): Either BUY or SELL.
market (Optional): Array of markets that the orders' markets must be.
status (Optional): Array of statuses that the orders' statuses must be.
orderType (Optional): Array of orderTypes that the orders must be.
limit (Optional): Number of orders requested.
startingBefore (Optional): Set a date by which the orders had to be created.

Order Statuses:

Status Explanation
PENDING The order has not yet been fully processed by the Matching-Engine.
OPEN The order is in an open position in the Matching-Engine and has not yet been filled at all.
FILLED The order has been fully filled.
PARTIALLY_FILLED The order has been partially filled.
CANCELED The order has been canceled. See Cancel Reasons below for explanations.
UNTRIGGERED Stop-Limit order has not been triggered yet.

Cancel Reasons:

Reason Explanation
EXPIRED The order reached the expiration date specified by the field expiresAt.
UNDERCOLLATERALIZED Either this order would put the position under collateralization or the position is currently undercollateralized.
CANCELED_ON_CHAIN The order was canceled on-chain.
USER_CANCELED The user cancled the order either through an API client or on https://trade.dydx.exchange/.
SELF_TRADE Execution of the order would have led the user to be both the maker and the taker.
FAILED Either before filling or on-chain, a failure occurred that prevented the order from being placed or filled.
COULD_NOT_FILL An order with fillOrKill: true could not be filled.
POST_ONLY_WOULD_CROSS An order with postOnly: true would cross the book.

Get Fills

Get Fills

// For margin/spot
const { id } = existingOrder;

const { fills }: { fills: ApiFillV2[] } = await solo.api.getFillsV2({
  orderId: id,
  side: 'BUY',
  transactionHash: '0xb6f6a4e9c513882353aeedd18b1843e6c451ed6bee2075487d5e013c6b0eeaba',
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: '0',
  startingBefore: new Date(),
  limit: 40,
});

// For perpetual
const { id } = existingOrder;

const { fills }: { fills: ApiFillV2[] } = await perpetual.api.getFillsV2({
  orderId: id,
  side: 'BUY',
  transactionHash: '0xb6f6a4e9c513882353aeedd18b1843e6c451ed6bee2075487d5e013c6b0eeaba',
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: '0',
  startingBefore: new Date(),
  limit: 40,
});
# Get fills created by my account for both sides of the orderbook
my_fills = client.get_my_fills(
    market=['WETH-DAI', 'DAI-WETH'],
    limit=None,  # optional
    startingBefore=None  # optional
)

# Get all fills from one side of the book
all_fills = client.get_fills(
    market=['WETH-DAI'], # 'DAI-WETH' side of the book is not included
    makerAccountOwner='0x5F5A46a8471F60b1E9F2eD0b8fc21Ba8b48887D8',  # optional
    makerAccountNumber=0,  # optional
    limit=2,  # optional
    startingBefore=None  # optional
)
{
  "fills": [
    {
      "uuid": "8994f3a0-f5a6-4aa8-a19f-075f076ad999",
      "createdAt": "2020-01-15T00:50:17.042Z",
      "transactionHash": "0x8350fae014702ce62c73762f9f38d29704d9dbf1909dd1fc02526c897207a35a",
      "status": "CONFIRMED",
      "market": "WETH-DAI",
      "side": "SELL",
      "accountOwner": "0x5f5a46a8471f60b1e9f2ed0b8fc21ba8b48887d8",
      "accountNumber": "0",
      "orderId": "0x773a0afd79bcc4c005c79d85ab7da21ff3e6bb11d73e5b3757b25fb1bc9c0f97",
      "orderClientId": null,
      "price": "169.98523710095444091",
      "amount": "100000000000000000",
      "feeAmount": "0",
      "liquidity": "MAKER"
    },
    {
      "uuid": "15a0d654-76d6-4bb4-ad1a-15c088def1b7",
      "createdAt": "2020-01-15T00:49:55.580Z",
      "transactionHash": "0x7419547186ee1c54785162fd6752f4c2e88ca09f0944d8b9c038a0e2cf169a8c",
      "status": "CONFIRMED",
      "market": "WETH-DAI",
      "side": "BUY",
      "accountOwner": "0x5f5a46a8471f60b1e9f2ed0b8fc21ba8b48887d8",
      "accountNumber": "0",
      "orderId": "0x4ef2ab5b3735c43c6ca6d91088884fe3ea43be9b03c3f16eab19aecf259420ab",
      "orderClientId": "d025f607-9827-4043-9445-aec9c4b2e9af",
      "price": "170.94678134323509863",
      "amount": "100000000000000000",
      "feeAmount": "0",
      "liquidity": "TAKER"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v2/fills

Description: Get all historical fills. This endpoint is most useful if you care about the outcome of the trade from the perspective of a particular accountOwner.

Parameter Description
orderId (Optional): Id of order the fills are for.
side (Optional): Either BUY or SELL.
market (Optional): Array of markets that the orders' markets must be.
transactionHash (Optional): The transaction hash associated with the fills.
accountOwner (Optional): The wallet address the fill was performed on.
accountNumber (Optional): The accountNumber associated with the fill.
startingBefore (Optional): Set a date by which the orders had to be created.
limit (Optional): Number of orders requested, the max limit is 100.
Fill Status Description
PENDING The fill is has not been fully processed on-chain.
REVERTED The fill was reverted on-chain.
CONFIRMED The fill was confirmed on-chain.

Get Trades

Get Trades

// For margin/spot
const { id } = existingOrder;

// order has type ApiTradeV2
const { trades }: { trades: ApiTradeV2[] } = await solo.api.getTradesV2({
  orderId: id,
  side: 'BUY',
  market: ['WETH-USDC', 'DAI-USDC'],
  transactionHash: '0xb6f6a4e9c513882353aeedd18b1843e6c451ed6bee2075487d5e013c6b0eeaba',
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: '0',
  startingBefore: new Date(),
  limit: 40,
});

// For perpetual
const { id } = existingOrder;

// order has type ApiTradeV2
const { trades }: { trades: ApiTradeV2[] } = await perpetual.api.getTradesV2({
  orderId: id,
  side: 'BUY',
  market: ['PBTC-USDC'],
  transactionHash: '0xb6f6a4e9c513882353aeedd18b1843e6c451ed6bee2075487d5e013c6b0eeaba',
  accountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  accountNumber: '0',
  startingBefore: new Date(),
  limit: 40,
});
# Get trades created by my account for both sides of the orderbook
my_trades = client.get_my_trades(
    market=['WETH-DAI', 'DAI-WETH'],
    limit=None,  # optional
    startingBefore=None  # optional
)

# Get all trades from one side of the book
all_trades = client.get_trades(
    market=['WETH-DAI'], # 'DAI-WETH' side of the book is not included
    makerAccountOwner='0x5F5A46a8471F60b1E9F2eD0b8fc21Ba8b48887D8',  # optional
    makerAccountNumber=0,  # optional
    limit=2,  # optional
    startingBefore=None  # optional
)
{
  "trades": [
    {
      "uuid": "f3c049a8-ca91-41a3-9466-a0bdbd1a058c",
      "transactionHash": "0x90c4a9835f5c242d1dd18919dfb9b8444cff8df75d518ae0966a6d8205ac9721",
      "status": "CONFIRMED",
      "market": "WETH-DAI",
      "side": "BUY",
      "price": "142.569999999999978406",
      "amount": "1000000000000000000",
      "makerOrderId": "0x145a78477771cea8ecf077c41c8301de3fedcdca9521361df3e40066bf4aab92",
      "makerAccountOwner": "0x862821badb9c5800654015ba9a2d9d7894c83a7a",
      "makerAccountNumber": "0",
      "takerOrderId": "0x3908e04d89741d802127be31ba0698fe6728da766cf1a820194e13346068da4d",
      "takerAccountOwner": "0xe184468b7103af442509dfb087a9c222353787b3",
      "takerAccountNumber": "0",
      "createdAt": "2019-12-11T21:29:58.032Z"
    },
    {
      "uuid": "f1b7a849-f765-4c18-8842-86e5750e08f5",
      "transactionHash": "0x6d83c6d11d8f8a712acf3066d83292aa13422399b4ed77defd764e32971def4e",
      "status": "CONFIRMED",
      "market": "WETH-DAI",
      "side": "SELL",
      "price": "142.569999999999978406",
      "amount": "2000000000000000000",
      "makerOrderId": "0x145a78477771cea8ecf077c41c8301de3fedcdca9521361df3e40066bf4aab92",
      "makerAccountOwner": "0x862821badb9c5800654015ba9a2d9d7894c83a7a",
      "makerAccountNumber": "0",
      "takerOrderId": "0xa88bbd489128a0399c516a68d84622aba65971966d174cc98f692d07c70d9d1b",
      "takerAccountOwner": "0x3801d2d7e604e8333baacb2ab53ceeb8d7995416",
      "takerAccountNumber": "0",
      "createdAt": "2019-12-11T21:29:39.707Z"
    },
    {
      "uuid": "4711636c-8ac3-4d92-806b-7d811a2ee7d4",
      "transactionHash": "0xa6b0caa07f44b4d16d253c6a547771b10d230838e692eaa6aabba65aa1f72826",
      "status": "CONFIRMED",
      "market": "WETH-DAI",
      "side": "BUY",
      "price": "142.569999999999998833",
      "amount": "2000000000000000000",
      "makerOrderId": "0x9d503c9ec3789143f4e47a0928a71cadb83ec445b680eef01ae5808d020c3cab",
      "makerAccountOwner": "0x862821badb9c5800654015ba9a2d9d7894c83a7a",
      "makerAccountNumber": "0",
      "takerOrderId": "0xd93b9b62f44168b4cfa0f1877be5cf329288958c9024158870308d60fd2cc347",
      "takerAccountOwner": "0xe46fbdfc5ec01d5914a802aa06fd0e4c5cd41bd5",
      "takerAccountNumber": "0",
      "createdAt": "2019-12-11T21:19:59.157Z"
    },
    {
      "uuid": "22d04881-f427-45d7-88c8-da61fea00210",
      "transactionHash": "0xbdd78f7dd75f8304b896c6ca5aa9cec847cc14925f70ac93e14958756b3bc372",
      "status": "CONFIRMED",
      "market": "WETH-DAI",
      "side": "SELL",
      "price": "142.56999999999999883412062732488427883543558159273568954946785561652608982546567212",
      "amount": "500008846251751135",
      "makerOrderId": "0x9d503c9ec3789143f4e47a0928a71cadb83ec445b680eef01ae5808d020c3cab",
      "makerAccountOwner": "0x862821badb9c5800654015ba9a2d9d7894c83a7a",
      "makerAccountNumber": "0",
      "takerOrderId": "0x69ba7a2c7c2d4110e36af82c5f0a9076c4db70a5a3455e27a04a1c525d0233fd",
      "takerAccountOwner": "0xf03df965490882583018c64fd41fa82d7dee032f",
      "takerAccountNumber": "107168784608729135660257601028275559138738399573533131184788900278475157896234",
      "createdAt": "2019-12-11T21:11:02.247Z"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v2/trades

Description: Get all historical trades. Where a fill represents one side of a trade, a trade contains both a maker and a taker. There will be single trade for each fill. The maker in this case represents the order that was already on the book, where the taker represents the order that was placed to fill the maker order(s).

Parameter Description
orderId (Optional): Id of order the fills are for.
side (Optional): Either BUY or SELL.
market (Optional): Array of markets that the orders' markets must be.
transactionHash (Optional): The transaction hash associated with the fills.
accountOwner (Optional): The wallet address the fill was performed on.
accountNumber (Optional): The accountNumber associated with the fill.
startingBefore (Optional): Set a date by which the orders had to be created.
limit (Optional): Number of orders requested, the max limit is 100.

Response Fields:

Trade Field Name Description
uuid Unique uuid of the order.
transactionHash Transaction hash for the on-chain operation.
status Status of the order involved in the trade.
market Market the trade is in.
side Either BUY or SELL.
price denominated in base/quote.
amount denominated in base units. i.e. 1 ETH = 1e18.
makerOrderId Id of maker order in trade.
makerAccountOwner Wallet address of maker order in trade.
makerAccountNumber Account number of maker order in trade.
takerOrderId Id of taker order in trade.
takerAccountOwner Wallet address of taker order in trade.
takerAccountNumber Account number of taker order in trade.
createdAt Date and time trade was cached at in ISO8601 format.
Trade Status Description
PENDING The trade is has not been fully processed on-chain.
REVERTED The trade was reverted on-chain.
CONFIRMED The trade was confirmed on-chain.

Get Orderbook

Get Orderbook

// For margin/spot
import { ApiMarketName } from '@dydxprotocol/solo';

const { bids, asks } = await solo.api.getOrderbookV2({
  market: ApiMarketName.WETH_DAI,
});

// For perpetual
import { ApiMarketName } from '@dydxprotocol/perpetual';

const { bids, asks } = await perpetual.api.getOrderbookV2({
  market: ApiMarketName.PBTC_USDC,
});
orderbook = client.get_orderbook(
    market='WETH-DAI'
)
{
  "bids": [
    {
      "id": "0xefa4562c0747a8f2a9aa69abb817474ee9e98c8505a71de6054a610ac744b0cd",
      "uuid": "c58be890-6e76-4e98-95d4-27977a91af19",
      "amount": "17459277053478281216",
      "price": "160.06010000000002787211"
    },
    {
      "id": "0xa2ab9f653106fefef5b1264a509b02eab021ffea442307e995908e5360f3cd4d",
      "uuid": "d2dba4c6-6442-46bc-b097-1f37312cf279",
      "amount": "149610989871929360384",
      "price": "160.06010000000000157722"
    },
    {
      "id": "0xec35d60dd1c5eab86cd7881fcbc1239193ceda695df2815d521a46f54bd90580",
      "uuid": "24d5a4e1-195b-43fa-a7d8-1d794619e97e",
      "amount": "54494000000000000000",
      "price": "160.05999999999998977766"
    },
  ],
  "asks": [
    {
      "id": "0xb242e2006a0d99c390fc7256d10558844a719d580e80eaa5a4f99dd14bd9ce5e",
      "uuid": "6fdff2f3-0175-4297-bf23-89526eb9aa36",
      "amount": "12074182754430260637",
      "price": "160.30000000000000000000"
    },
    {
      "id": "0xe32a00e11b91b6f8daa70fbe03ad0100fa458c0d87e5c59f2e629ce9d5d32921",
      "uuid": "3f9b35a8-d843-4ae6-bc8b-b534b07e8093",
      "amount": "50000000000000000000",
      "price": "160.40000000000000000000"
    },
    {
      "id": "0xcad0c2e92094bd1dd17a694bd25933a8825c6014aaf4ae2925512f62c15ae968",
      "uuid": "5aefdfd2-4e4d-4b37-9c99-35e8eec0ed9a",
      "amount": "50000000000000000000",
      "price": "160.50000000000000000000"
    },
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/orderbook/WETH-DAI

Description: Returns the active orderbook for a market. All bids and asks that are fillable are returned.

Market is one of: [WETH-DAI, WETH-USDC, DAI-USDC, PBTC-USDC]

Amounts for this endpoint are returned in the base asset for the market (e.g. WETH for WETH-DAI). Prices are denominated as (quote amount) / (base amount) for each given order. For markets where the tokens have different number of decimals (e.g. DAI-USDC & WETH-USDC) prices will include the decimal places (e.g. prices in DAI-USDC will look like 0.00000000000100252200).

Parameter Description
market (Optional): Array of markets that the orders' markets must be.

Get Positions

Response

{
  "positions": [
    {
      "uuid": "5f3f0dc0-d84f-4bf8-a0ce-61d4c98ae88c",
      "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
      "number": "72726098636314491067235956043692261150608981229613064856905296785781912974936",
      "market": "WETH-DAI",
      "type": "ISOLATED_LONG",
      "status": "CLOSED",
      "accountUuid": "836a4fdc-c994-450e-a07b-830ed37716ce",
      "expiresAt": "2020-05-29T22:13:39.000Z",
      "createdAt": "2020-05-01T22:13:52.847Z",
      "updatedAt": "2020-05-21T17:35:57.278Z",
      "account": {
        "uuid": "836a4fdc-c994-450e-a07b-830ed37716ce",
        "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
        "number": "72726098636314491067235956043692261150608981229613064856905296785781912974936",
        "createdAt": "2020-05-01T22:13:44.755Z",
        "updatedAt": "2020-05-01T22:13:44.755Z"
      },
      "standardActions": [
        {
          "uuid": "878c0f3e-ced0-478c-a9c5-76237107050b",
          "type": "ISOLATED_FULL_CLOSE",
          "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
          "number": "72726098636314491067235956043692261150608981229613064856905296785781912974936",
          "transferAmount": "139940891786496509",
          "tradeAmount": "160307343231895490",
          "price": "197.76",
          "market": "WETH-DAI",
          "asset": "WETH",
          "side": "LONG",
          "operationUuid": null,
          "transactionHash": "0xa5c242650815711b45784b57b8132e2523cd5044f0c6c53482c706713de29795",
          "positionUuid": "5f3f0dc0-d84f-4bf8-a0ce-61d4c98ae88c",
          "borrowAmount": null,
          "orderNumber": "1011061200670000",
          "confirmedAt": "2020-05-21T17:34:22.000Z",
          "feeAmount": "158511900987698260.512",
          "feeAsset": "DAI",
          "pnl": "-0.11680504725069452446144687474175947711343548096340565373461771439994077049174357",
          "payoutAmount": "139940891786496509",
          "isPendingBlock": false,
          "refundAmount": "0",
          "product": "SOLO",
          "createdAt": "2020-05-21T17:35:57.265Z",
          "updatedAt": "2020-05-21T17:35:57.280Z"
        },
        {
          "uuid": "d9ee4386-8810-4cf0-ab73-e5eaa7b6d7c8",
          "type": "ISOLATED_OPEN",
          "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
          "number": "72726098636314491067235956043692261150608981229613064856905296785781912974936",
          "transferAmount": "150200220768708569",
          "tradeAmount": "150000000000000000",
          "price": "208.62",
          "market": "WETH-DAI",
          "asset": "WETH",
          "side": "LONG",
          "operationUuid": null,
          "transactionHash": "0x2d39ca14ba40c5049d6983091fe430da8469619aae7657e872f531466fdf7d7a",
          "positionUuid": "5f3f0dc0-d84f-4bf8-a0ce-61d4c98ae88c",
          "borrowAmount": null,
          "orderNumber": "998298000710000",
          "confirmedAt": "2020-05-01T22:13:39.000Z",
          "feeAmount": "156465000000000000",
          "feeAsset": "DAI",
          "pnl": null,
          "payoutAmount": null,
          "isPendingBlock": false,
          "refundAmount": "0",
          "product": "SOLO",
          "createdAt": "2020-05-03T04:06:48.813Z",
          "updatedAt": "2020-05-03T04:06:48.834Z"
        }
      ]
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/positions

Description:

This endpoint retrieves an account's isolated margin positions.

Query Params

Field Description
owner (Optional) The account address.
number (Optional) The account number.
status (Optional)The position status eg: OPEN, CLOSED etc.
type (Optional) The position type eg: ISOLATED_SHORT or ISOLATED_LONG.
market (Optional) The position market eg: WETH-DAI.
limit (Optional) The number of positions to return ( max 100).

Position statuses:

status
STOP_EXECUTED
OPEN
LIQUIDATED
INVALID
EXPIRED
CLOSED

Position types:

type
ISOLATED_SHORT
ISOLATED_LONG

Position markets:

market
WETH-DAI
WETH-SAI
WETH-USDC
DAI-USDC
SAI-USDC
SAI-DAI

Example response object:

Query: https://api.dydx.exchange/v1/positions?owner=0x77A035b677D5A0900E4848Ae885103cD49af9633&limit=1

Position response object

Field Description
uuid The unique identifier for the position.
owner The account address.
number The account number.
market The market for this position eg WETH-DAI.
type The position type er: ISOLATED_LONG or ISOLATED_SHORT
status. The position status eg: OPEN, CLOSED.
account An object containing the account information.
standardActions An array of the associated standard actions for this position eg: the associated ISOLATED_FULL_CLOSE action.

Markets API

dYdX provides a means to query relevant market data to assist in programmatic strategies. Beyond querying Solo or Perpetual markets, funding rates, statistics and candles are also queryable.

Solo Get V1 Markets

Get Markets

const { markets } = await solo.api.getMarkets();
{
  "markets": [
    {
      "id": 0,
      "name": "Ethereum",
      "symbol": "ETH",
      "supplyIndex": "1.001398660619165827",
      "borrowIndex": "1.010368590898359639",
      "supplyInterestRateSeconds": "0.00000000008945112223964823567690892185119535814786489929645384878315331493235128",
      "borrowInterestRateSeconds": "0.000000000546421514",
      "totalSupplyPar": "98916437591968893681399",
      "totalBorrowPar": "16893907569901507548059",
      "lastIndexUpdateSeconds": "1590172676",
      "oraclePrice": "207420000000000000000",
      "collateralRatio": "1.15",
      "marginPremium": "0",
      "spreadPremium": "0",
      "currencyUuid": "9debe831-5ccd-448b-91f7-cd247ecddc22",
      "createdAt": "2019-04-03T01:11:55.990Z",
      "updatedAt": "2020-05-22T18:38:45.600Z",
      "deletedAt": null,
      "currency": {
        "uuid": "9debe831-5ccd-448b-91f7-cd247ecddc22",
        "symbol": "WETH",
        "contractAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
        "decimals": 18,
        "createdAt": "2018-07-10T04:08:53.352Z",
        "updatedAt": "2018-07-10T04:08:53.352Z"
      },
      "totalSupplyAPR": "0.00282093059094954676030699975949929681455106746421296857522552293970662996608",
      "totalBorrowAPR": "0.017231948865504",
      "totalSupplyAPY": "0.002824913159618525",
      "totalBorrowAPY": "0.017381275392271966",
      "totalSupplyWei": "99054788117816954779760.734139858486351973",
      "totalBorrowWei": "17069073586168517326002.814653240058390701"
    },
    {
      "id": 1,
      "name": "SAI",
      "symbol": "SAI",
      "supplyIndex": "1.060104599441753982",
      "borrowIndex": "1.094636157956433672",
      "supplyInterestRateSeconds": "0",
      "borrowInterestRateSeconds": "0",
      "totalSupplyPar": "8489728282227392446",
      "totalBorrowPar": "0",
      "lastIndexUpdateSeconds": "1590172676",
      "oraclePrice": "1",
      "collateralRatio": "1.15",
      "marginPremium": "0",
      "spreadPremium": "0",
      "currencyUuid": "3022f2e4-5ce8-4576-882b-cdae6e198e3b",
      "createdAt": "2019-04-03T01:11:55.990Z",
      "updatedAt": "2020-05-22T18:38:45.601Z",
      "deletedAt": null,
      "currency": {
        "uuid": "3022f2e4-5ce8-4576-882b-cdae6e198e3b",
        "symbol": "SAI",
        "contractAddress": "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359",
        "decimals": 18,
        "createdAt": "2018-07-10T04:08:53.352Z",
        "updatedAt": "2018-07-10T04:08:53.352Z"
      },
      "totalSupplyAPR": "0",
      "totalBorrowAPR": "0",
      "totalSupplyAPY": "0",
      "totalBorrowAPY": "0",
      "totalSupplyWei": "8999999999999999970.554429596497219972",
      "totalBorrowWei": "0"
    },
    {
      "id": 2,
      "name": "USDC",
      "symbol": "USDC",
      "supplyIndex": "1.04187613625421444",
      "borrowIndex": "1.072147697097366983",
      "supplyInterestRateSeconds": "0.00000000043237131807605842113005907414001250332155197748006575168539387950003242",
      "borrowInterestRateSeconds": "0.000000001201332793",
      "totalSupplyPar": "9508292364989",
      "totalBorrowPar": "3500532173579",
      "lastIndexUpdateSeconds": "1590172676",
      "oraclePrice": "1000000000000000000000000000000",
      "collateralRatio": "1.15",
      "marginPremium": "0",
      "spreadPremium": "0",
      "currencyUuid": "e714906e-d2ca-43d6-9d5e-d31b2d216157",
      "createdAt": "2019-05-07T23:33:55.642Z",
      "updatedAt": "2020-05-22T18:38:45.601Z",
      "deletedAt": null,
      "currency": {
        "uuid": "e714906e-d2ca-43d6-9d5e-d31b2d216157",
        "symbol": "USDC",
        "contractAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "decimals": 6,
        "createdAt": "2019-05-07T23:33:55.642Z",
        "updatedAt": "2019-05-07T23:33:55.642Z"
      },
      "totalSupplyAPR": "0.01363526188684657836875754296207943430474846316181135354515058138391302239712",
      "totalBorrowAPR": "0.037885230960048",
      "totalSupplyAPY": "0.0137286460265591",
      "totalBorrowAPY": "0.0386120255329192",
      "totalSupplyWei": "9906462911610.18622142595424116",
      "totalBorrowWei": "3753087508517.965354198819542157"
    },
    {
      "id": 3,
      "name": "DAI",
      "symbol": "DAI",
      "supplyIndex": "1.02352463593826795",
      "borrowIndex": "1.03145143300767834",
      "supplyInterestRateSeconds": "0.00000000071328015292052294081913899831940846447245786755728669312100503006956483",
      "borrowInterestRateSeconds": "0.000000001542996581",
      "totalSupplyPar": "9045574058734731599497129",
      "totalBorrowPar": "4367745908691120032726721",
      "lastIndexUpdateSeconds": "1590172676",
      "oraclePrice": "1000436176029173829",
      "collateralRatio": "1.15",
      "marginPremium": "0",
      "spreadPremium": "0",
      "currencyUuid": "3eb5c94b-1727-42bd-b5c8-2dd701e342b7",
      "createdAt": "2019-11-25T01:47:53.051Z",
      "updatedAt": "2020-05-22T18:38:45.601Z",
      "deletedAt": null,
      "currency": {
        "uuid": "3eb5c94b-1727-42bd-b5c8-2dd701e342b7",
        "symbol": "DAI",
        "contractAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
        "decimals": 18,
        "createdAt": "2019-11-25T00:47:45.213Z",
        "updatedAt": "2019-11-25T00:47:45.213Z"
      },
      "totalSupplyAPR": "0.02249400290250161146167236745100086533560343131128659315426401462827379647888",
      "totalBorrowAPR": "0.048659940178416",
      "totalSupplyAPY": "0.022748900621180734",
      "totalBorrowAPY": "0.049863273712147826",
      "totalSupplyWei": "9258367895319106950860481.35493330725771555",
      "totalBorrowWei": "4505117776532879950251522.64743327989092314"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/markets

Description:

Gets high level information for all solo assets.

Query Params:

None

Markets Response body:

Field name Description
markets An array of different asset objects.
id Id of asset determined by protocol.
name Name of asset.
supplyIndex Current index of the supply.
borrowIndex Current index of the borrow.
totalSupplyPar Summation of total available asset par in asset.
totalBorrowPar Summation of total asset borrowed par from asset.
totalSupplyWei totalSupplyPar multiplied by supplyIndex.
totalBorrowWei totalBorrowPar multiplied by borrowIndex.
supplyInterestRateSeconds Current interest rate per second earned from lending assets.
borrowInterestRateSeconds Current interest rate per second paid to borrowed assets.
supplyInterestAPY Current interest rate per second earned from lending assets including compound interest.
borrowInterestAPY Current interest rate per second paid to borrowed assets including compound interest.
supplyInterestAPR Current interest rate per second earned from lending assets, multiplied by 1 year in seconds.
borrowInterestAPR Current interest rate per second paid to borrowed assets, multiplied by 1 year in seconds.
oraclePrice Price determined by oracle.
lastIndexUpdateSeconds Timestamp of last indexUpdate associated with the current asset values.
marginPremium Current marginPremium of the particular asset.
spreadPremium Current spreadPremium of the particular asset.
currencyUuid Unique id for a currency.
createdAt Date and time market was cached at in ISO8601 format.
updatedAt Date and time market was updated in the cache at in ISO8601 format.
deletedAt Date and time market was deleted in the cache at in ISO8601 format.
currency Information about the currency of the market.
totalSupplyAPR Annual rate charged for supplying to the market.
totalBorrowAPR Annual rate charged for borrowing from the market.
totalSupplyAPY Annual rate of yield earned for supplying to the market.
totalBorrowAPY Annual rate of yield earned for borrowing from the market.
totalSupplyWei Total supply in Wei.
totalBorrowWei Total borrow in Wei.

Get the markets that exist on the protocol. There is one market per asset:

id Asset
0 WETH
1 SAI
2 USDC
3 DAI

Solo Get V1 Market

Response

{
  "market": {
    "id": 0,
    "name": "Ethereum",
    "symbol": "ETH",
    "supplyIndex": "1.001306342154952813",
    "borrowIndex": "1.009828284827031753",
    "supplyInterestRateSeconds": "0.00000000004969840736422012284564765239517392930721200621215594692201109713616485",
    "borrowInterestRateSeconds": "0.000000000407292234",
    "totalSupplyPar": "98971283228248394332654",
    "totalBorrowPar": "12604957188509875228312",
    "lastIndexUpdateSeconds": "1589227490",
    "oraclePrice": "186720000000000000000",
    "collateralRatio": "1.15",
    "marginPremium": "0",
    "spreadPremium": "0",
    "currencyUuid": "9debe831-5ccd-448b-91f7-cd247ecddc22",
    "createdAt": "2019-04-03T01:11:55.990Z",
    "updatedAt": "2020-05-11T20:05:03.473Z",
    "deletedAt": null,
    "currency": {
      "uuid": "9debe831-5ccd-448b-91f7-cd247ecddc22",
      "symbol": "WETH",
      "contractAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
      "decimals": 18,
      "createdAt": "2018-07-10T04:08:53.352Z",
      "updatedAt": "2018-07-10T04:08:53.352Z"
    },
    "totalSupplyAPR": "0.0015672889746380457940603443659342050346322378279065499421325419592860947096",
    "totalBorrowAPR": "0.012844367891424",
    "totalSupplyAPY": "0.0015685178139013267",
    "totalBorrowAPY": "0.01292721109424222",
    "totalSupplyWei": "99100573587659229539040.117656245995055702",
    "totalBorrowWei": "12728842297991091658963.688744490148590936"
  }
}

HTTP Request:

GET https://api.dydx.exchange/v1/markets/0

Description:

This endpoint returns information for a particular Solo asset.

Query Params:

Field Name Description
id The asset id.

Market Response body:

Field name Description
id Id of asset determined by protocol.
name Name of asset.
supplyIndex Current index of the supply.
borrowIndex Current index of the borrow.
totalSupplyPar Summation of total available asset par in asset.
totalBorrowPar Summation of total asset borrowed par from asset.
totalSupplyWei totalSupplyPar multiplied by supplyIndex.
totalBorrowWei totalBorrowPar multiplied by borrowIndex.
supplyInterestRateSeconds Current interest rate per second earned from lending assets.
borrowInterestRateSeconds Current interest rate per second paid to borrowed assets.
supplyInterestAPY Current interest rate per second earned from lending assets including compound interest.
borrowInterestAPY Current interest rate per second paid to borrowed assets including compound interest.
supplyInterestAPR Current interest rate per second earned from lending assets, multiplied by 1 year in seconds.
borrowInterestAPR Current interest rate per second paid to borrowed assets, multiplied by 1 year in seconds.
oraclePrice Price determined by oracle.
lastIndexUpdateSeconds Timestamp of last indexUpdate associated with the current asset values.
marginPremium Current marginPremium of the particular asset.
spreadPremium Current spreadPremium of the particular asset.

Solo Get V2 Markets

Get Markets(v2)

const { markets } = await solo.api.getMarketsV2();
markets = client.get_markets()
{
  "markets": {
    "WETH-DAI": {
      "name": "WETH-DAI",
      "baseCurrency": {
        "currency": "WETH",
        "decimals": 18,
        "soloMarketId": 0
      },
      "quoteCurrency": {
        "currency": "DAI",
        "decimals": 18,
        "soloMarketId": 3
      },
      "minimumTickSize": "0.01",
      "minimumOrderSize": "100000000000000000",
      "smallOrderThreshold": "500000000000000000",
      "makerFee": "0",
      "largeTakerFee": "0.005",
      "smallTakerFee": "0.0015"
    },
    "WETH-USDC": {
      "name": "WETH-USDC",
      "baseCurrency": {
        "currency": "WETH",
        "decimals": 18,
        "soloMarketId": 0
      },
      "quoteCurrency": {
        "currency": "USDC",
        "decimals": 6,
        "soloMarketId": 2
      },
      "minimumTickSize": "0.00000000000001",
      "minimumOrderSize": "100000000000000000",
      "smallOrderThreshold": "500000000000000000",
      "makerFee": "0",
      "largeTakerFee": "0.005",
      "smallTakerFee": "0.0015"
    },
    "DAI-USDC": {
      "name": "DAI-USDC",
      "baseCurrency": {
        "currency": "DAI",
        "decimals": 18,
        "soloMarketId": 3
      },
      "quoteCurrency": {
        "currency": "USDC",
        "decimals": 6,
        "soloMarketId": 1
      },
      "minimumTickSize": "0.0000000000000001",
      "minimumOrderSize": "20000000000000000000",
      "smallOrderThreshold": "100000000000000000000",
      "makerFee": "0",
      "largeTakerFee": "0.005",
      "smallTakerFee": "0.0005"
    }
  }
}

HTTP Request

GET https://api.dydx.exchange/v2/markets

Description: Get trading specification information on all margin/spot markets.

Query Params: None

Example Response Body:

Response Fields Description
market Specific market being explained.
market.name Name of the market.
market.baseCurrency The Base currency for the market, contains name, decimals and soloMarketId.
market.quoteCurrency The Quote currency for the market, contains name, decimals and soloMarketId.
market.minimumTickSize The smallest granularity an order size can be.
market.minimumOrderSize The smallest The order can be in base decimals.
market.smallOrderThreshold The smallest The order can be in base decimals to receive the largeTakerFee.
market.makerFee Fee paid by the maker.
market.largeTakerFee Fee paid by taker if they are below the smallOrderThreshold.
market.smallTakerFee Fee paid by taker if they are at or above the smallOrderThreshold.

Solo Get V2 Market

Get Market(v2)

const { market } = await solo.api.getMarketV2({
  market: string
});
market = client.get_market(
    market='WETH-DAI'
)
{
  "market": {
    "WETH-DAI": {
      "name": "WETH-DAI",
      "baseCurrency": {
        "currency": "WETH",
        "decimals": 18,
        "soloMarketId": 0
      },
      "quoteCurrency": {
        "currency": "DAI",
        "decimals": 18,
        "soloMarketId": 3
      },
      "minimumTickSize": "0.01",
      "minimumOrderSize": "100000000000000000",
      "smallOrderThreshold": "500000000000000000",
      "makerFee": "0",
      "largeTakerFee": "0.005",
      "smallTakerFee": "0.0015"
    }
  }
}

HTTP Request

GET https://api.dydx.exchange/v2/markets/WETH-DAI

Description: Get high-level information on a specific Solo market.

Parameter Description
market (Optional): Array of markets that the orders' markets must be.

Perpetual Get Markets

Get Markets

const { markets } = await perpetual.api.getMarkets();
markets = client.get_perpetual_markets()
{
  "markets": [
    {
      "uuid": "f6d20698-32ac-4f3a-a9c4-b6b7528b7b94",
      "market": "PBTC-USDC",
      "oraclePrice": "90.3551",
      "fundingRate": "0.000000017511403011",
      "minCollateral": "1.075",
      "globalIndexValue": "1.207692942350066675",
      "globalIndexTimestamp": "1590093314",
      "decimals": "8",
      "minimumTickSize": "0.01",
      "minimumOrderSize": "10000",
      "smallOrderThreshold": "1000000",
      "makerFee": "-0.00025",
      "largeTakerFee": "0.00075",
      "smallTakerFee": "0.005",
      "openInterest": "2835957144",
      "predictedFundingRate": "0.000000017611403011",
      "fundingRateUpdatedAt": "2020-06-29T21:00:33.000Z",
      "createdAt": "2020-04-09T22:42:35.696Z",
      "updatedAt": "2020-05-21T20:50:55.334Z"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/perpetual-markets

Description:

Get all v1 Perpetual Markets, this includes trading specification information as well as dynamic market changes.

Query Params

None

Markets Response Object:

Field Name Description
markets An array of the perpetual market objects.
market The market string, e.g.: PBTC-USDC.
oraclePrice The index price from the oracle.
fundingRate The funding rate for the market.
globalIndexValue The global index value for the market.
globalIndexTimestamp The Unix timestamp (seconds) for the last update to the global index.
minCollateral The minimum collaterization before getting liquidated eg: 1.07.
decimals Corresponds to the precision for the position units eg: if decimals = 8, then 100000000 = 1 BTC.
minimumTickSize The minimum price amount eg: 0.01 (equal to $1).
minimumOrderSize The minimum size, in position units, required for an order.
smallOrderThreshold The threshold, in position units, at which we charge different fees for takers.
makerFee The percentage fee charged for the maker of an order eg -0.00025 (equal to -0.025%).
largeTakerFee Applies to orders >= smallOrderThreshold. eg 0.00075 (equal to 0.075%).
smallTakerFee Applies to orders < smallOrderThreshold. eg 0.005 (equal to 0.5%).
openInterest openInterest is the sum of the position amount of all longs (equal to sum of amount of all shorts).
predictedFundingRate The predicted next funding rate.
fundingRateUpdatedAt When the funding rate was last updated.
createdAt The ISO 8601 date and time this balance update was created.
updatedAt The ISO 8601 date and time this balance update was updated.

Perpetual Get Market

Get Market

market = client.get_perpetual_market('PBTC-USDC')
{
  "market": {
    "uuid": "f6d20698-32ac-4f3a-a9c4-b6b7528b7b94",
    "market": "PBTC-USDC",
    "oraclePrice": "92.052",
    "fundingRate": "0.000000017178342607",
    "minCollateral": "1.075",
    "globalIndexValue": "1.258933718003697999",
    "globalIndexTimestamp": "1590170610",
    "decimals": "8",
    "minimumTickSize": "0.01",
    "minimumOrderSize": "10000",
    "smallOrderThreshold": "1000000",
    "makerFee": "-0.00025",
    "largeTakerFee": "0.00075",
    "smallTakerFee": "0.005",
    "openInterest": "3917905240",
    "predictedFundingRate": "0.000000017611403011",
    "fundingRateUpdatedAt": "2020-06-29T21:00:33.000Z",
    "createdAt": "2020-04-09T22:42:35.696Z",
    "updatedAt": "2020-05-22T18:30:55.429Z"
  }
}

HTTP Request

GET https://api.dydx.exchange/v1/perpetual-markets/PBTC-USDC

Market Response Object:

Field Name Description
market The market string, e.g.: PBTC-USDC.
oraclePrice The index price from the oracle.
fundingRate The funding rate for the market.
globalIndexValue The global index value for the market.
globalIndexTimestamp The Unix timestamp (seconds) for the last update to the global index.
minCollateral The minimum collaterization before getting liquidated eg: 1.07.
decimals Corresponds to the precision for the position units eg: if decimals = 8, then 100000000 = 1 BTC.
minimumTickSize The minimum price amount eg: 0.01 (equal to $1).
minimumOrderSize The minimum size, in position units, required for an order.
smallOrderThreshold The threshold, in position units, at which we charge different fees for takers.
makerFee The percentage fee charged for the maker of an order eg -0.00025 (equal to -0.025%).
largeTakerFee Applies to orders >= smallOrderThreshold. eg 0.00075 (equal to 0.075%).
smallTakerFee Applies to orders < smallOrderThreshold. eg 0.005 (equal to 0.5%).
openInterest openInterest is the sum of the position amount of all longs (equal to sum of amount of all shorts).
predictedFundingRate The predicted next funding rate.
fundingRateUpdatedAt When the funding rate was last updated.
createdAt The ISO 8601 date and time the Perpetual market update was created.
updatedAt The ISO 8601 date and time th Perpetual market update was updated.

Get Market Stats

Response

{
  "markets": {
    "ETH-DAI": {
      "symbol": "ETH-DAI",
      "low": "162.4405999999999897",
      "high": "174.2499999999999868",
      "open": "164.2299999999999944",
      "last": "172.3",
      "count": "471",
      "baseVolume": "5843.639421040800787051",
      "quoteVolume": "989969.012877626028804362",
      "usdVolume": "986637.73064075646796575518",
      "type": "SPOT"
    },
    "ETH-USDC": {
      "symbol": "ETH-USDC",
      "low": "164.6288399939555261",
      "high": "172.3813",
      "open": "165.6253902",
      "last": "172.024530000172056",
      "count": "39",
      "baseVolume": "1242.716813796154791774",
      "quoteVolume": "208529.481209",
      "usdVolume": "208996.90504319296510926476",
      "type": "SPOT"
    },
    "DAI-USDC": {
      "symbol": "DAI-USDC",
      "low": "0.9955",
      "high": "0.99990000047398794804",
      "open": "0.997",
      "last": "0.9992585",
      "count": "70",
      "baseVolume": "125214.755274428622751688",
      "quoteVolume": "124872.38461",
      "usdVolume": "125214.755274428622751688",
      "type": "SPOT"
    },
    "PBTC-USDC": {
      "symbol": "PBTC-USDC",
      "low": "8909.0000",
      "high": "9592.0000",
      "open": "9488.0000",
      "last": "8944.0000",
      "count": "221",
      "baseVolume": "116.5380",
      "quoteVolume": "1057559.1430",
      "usdVolume": "1057559.1430",
      "type": "PERPETUAL"
    }
  }
}

HTTP Request

GET https://api.dydx.exchange/v1/stats/markets

Description: Get market statistics for the last 24 hours.

Query Params: None

Example Response Body:

Markets.Pair Response Param Description
symbol Symbol representing the market pair.
low Low price in a 24 hour period for a market pair.
high High price in a 24 hour period for a market pair.
open First price in a 24 hour period for a market pair.
last Last price in a 24 hour period for a market pair.
count Number of trades placed in a 24 hour period for a market pair.
baseVolume Volume in base currency traded in a 24 hour period.
quoteVolume Volume in quote currency traded in a 24 hour period.
usdVolume Volume converted to USD traded in a 24 hour period.
type Type of exchange a market pair is traded on SPOT or PERPETUAL.

Get Candles for Market

Response

{
  "candles": [
    {
      "startedAt": "2019-09-04T00:00:00.000Z",
      "pair": "WETH-DAI",
      "resolution": "1DAY",
      "low": "0",
      "high": "300",
      "open": "184.89",
      "close": "300",
      "baseTokenVolume": "1.520026280892103673",
      "createdAt": "2019-10-31T18:36:51.159Z",
      "updatedAt": "2019-12-02T18:38:11.005Z"
    },
    {
      "startedAt": "2019-09-05T00:00:00.000Z",
      "pair": "WETH-DAI",
      "resolution": "1DAY",
      "low": "180",
      "high": "300",
      "open": "300",
      "close": "180",
      "baseTokenVolume": "0.2",
      "createdAt": "2019-10-31T18:36:51.159Z",
      "updatedAt": "2019-12-02T18:38:11.005Z"
    },
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/candles/WETH-DAI?res=1DAY

Description: Get historical trade statistics for a Solo market.

Query Params:

Field Name Description
res 1HOUR or 1DAY.
fromISO Start ISO 8601 date and time.
toISO End ISO 8601 date and time.

Funding Rate Object

The funding endpoints can be used to get information related to the funding rates for Perpetual markets.

Field Name Description
market The market string, e.g. PBTC-USDC.
effectiveAt ISO 8601 date and time representing the start of the hour for which the rate is expected to take effect.
fundingRate The funding rate for the market, as a per-second rate. Equal to the smart contract representation.
fundingRate8Hr The funding rate for the market, as an eight-hour rate. Equal to fundingRate * 28800.
averagePremiumComponent The average premium component which went into the calculation of the funding rate.
averagePremiumComponent8Hr The average premium component, as an eight-hour rate.

Get Funding Rates

Response

# Returns Promise<{ [market: string]: ApiFundingRates }>
const fundingRates = await perpetual.api.getFundingRates();

// Get Individual Funding Rate
const fundingRates = await perpetual.api.getFundingRates({ market: ['PBTC-USDC'] });
funding_rates = client.get_funding_rates()

# Get Individual Funding Rate
funding_rate = client.get_funding_rates(markets=['PBTC-USDC'])
{
  "PBTC-USDC": {
    "current": {
      "market": "PBTC-USDC",
      "effectiveAt": "2020-05-22T08:00:00.000Z",
      "fundingRate": "0.000000003192901192",
      "fundingRate8Hr": "0.0000919555543296",
      "averagePremiumComponent": "-0.000000000279321029",
      "averagePremiumComponent8Hr": "-0.000008044445661252"
    },
    "predicted": {
      "market": "PBTC-USDC",
      "effectiveAt": "2020-05-22T09:00:00.000Z",
      "fundingRate": "0.000000003726094076",
      "fundingRate8Hr": "0.0001073115093888",
      "averagePremiumComponent": "0.000000000253871854",
      "averagePremiumComponent8Hr": "0.000007311509403474"
    }
  }
}

HTTP Request

GET https://api.dydx.exchange/v1/funding-rates

Description: Get the current and predicted funding rates.

The current rate is updated each hour, on the hour. The predicted rate is updated each minute, on the minute, and may be null if no premiums have been calculated since the last funding rate update.

IMPORTANT: The “current” funding rate returned by this function is not active until it has been mined on-chain, which may not happen for some period of time after the start of the hour. To get the funding rate that is currently active on-chain, use the v1/perpetual-markets endpoint.

Query Params:

Field Name Description
markets (Optional) Markets to get rates for. Defaults to all Perpetual markets.

Response (Per Market):

Field name Description
current The funding rate expected to take effect in this hour. It will only actually take effect once the relevant transaction is mined.
predicted The predicted funding rate for the next hour. Calculated using premiums since the start of the hour. If no premiums are available (e.g. first minute of the hour) this will be null.

Get Historical Funding Rates

Response

// Returns Promise<{ [market: string]: ApiHistoricalFundingRates }>
const historicalFundingRates = await perpetual.api.getFundingRates();

// Get Individual Funding Rate
const historicalFundingRates = await perpetual.api.getFundingRates({ market: ['PBTC-USDC'], limit: 10 });
historical_funding_rates = client.get_historical_funding_rates()

# Get Subset of Historical Funding Rates (markets, limit and startingBefore are optional fields)
historical_funding_rates = client.get_historical_funding_rates(markets=['PBTC-USDC'], limit=10)
{
  "PBTC-USDC": {
    "history": [
      {
        "market": "PBTC-USDC",
        "effectiveAt": "2020-05-22T18:00:00.000Z",
        "fundingRate": "0.000000017178342607",
        "fundingRate8Hr": "0.0004947362670816",
        "averagePremiumComponent": "0.00000001370612038495",
        "averagePremiumComponent8Hr": "0.000394736267086484"
      },
      {
        "market": "PBTC-USDC",
        "effectiveAt": "2020-05-22T17:00:00.000Z",
        "fundingRate": "0.00000000115030126",
        "fundingRate8Hr": "0.000033128676288",
        "averagePremiumComponent": "-0.00000000232192096206",
        "averagePremiumComponent8Hr": "-0.0000668713237074407"
      }
    ]
  }
}

HTTP Request

GET https://api.dydx.exchange/v1/historical-funding-rates

Description: Get historical funding rates. The most recent funding rates are returned first.

Query Params:

Field Name Description
markets (Optional) Markets to get rates for. Defaults to all Perpetual markets.
limit (Optional) The maximum number of funding rates. The default, and maximum, is 100.
startingBefore (Optional) ISO 8601 string. Return funding rates effective before this date.

Response (Per Market):

Field name Description
history Array of past funding rates.

Example Response Body:

Get Index Price

Response

# Returns Promise<{ [market: string]: ApiIndexPrice }>
const indexPrices = await perpetual.api.getFundingIndexPrice();

// Get Individual Funding Rate
const indexPrice = await perpetual.api.getFundingIndexPrice({ market: ['PBTC-USDC'] });
index_prices = client.get_funding_index_price()

# Get Individual Index price
index_price = client.get_funding_index_price(markets=['PBTC-USDC'])
{
  "PBTC-USDC": {
    "price": "86.11512"
  }
}

HTTP Request

GET https://api.dydx.exchange/v1/index-price

Description: Get the index price used in the funding rate calculation. The index price is calculated as the median spot market price from major centralized exchanges. More info on the index price calculation can be found in the Perpetual Guide.

Index prices are available for the markets listed below, which include all Perpetual markets and some non-Perpetual markets. If price information can't be retrieved from all exchanges, then the median of the available exchanges will be returned. Prices from a minimum number of exchanges are required, otherwise a cached price will be returned, and the live flag will be set to false.

market number of exchanges used minimum exchanges for live price
PBTC-USDC 5 3
WETH-USDC 5 2

Query Params:

Field Name Description
markets (Optional) Markets to get index prices for. Defaults to all available markets.

Response (Per Market):

Field name Description
price The index price, denominated in base units.
live true if at least the minimum number of exchanges were available, otherwise false.

Example Response Body:

WebSocket API

dYdX offers a WebSocket API for streaming updates to dYdX.

You can connect to the WebSocket at wss://api.dydx.exchange/v1/ws

WebSocket Introduction

Subscribe

{
  "type": "channel_data",
  "connection_id": "1de645c9-9ed2-49d0-9192-1522cf5c45f7",
  "message_id": 289
  ...additional data...
}

The WebSocket API accepts and sends messages in JSON format. All messages sent to clients by our server will be of the form:

Field Name JSON type Description
type string The type of the message
connection_id string A uuid unique to your connection. Will remain the same for the life of the connection
message_id number A sequential number starting at 0 that increases by 1 for each message sent

Subscribing

Subscribe

{
  "type": "subscribe",
  "channel": "orderbook",
  "id": "WETH-DAI",
  ...optional parameter...
  "batched": "true"
}

Response

{
  "type": "subscribed",
  "connection_id": "1de645c9-9ed2-49d0-9192-1522cf5c45f7",
  "message_id": 289,
  "channel": "orderbook",
  "id": "WETH-DAI",
  "contents": {
    ...initial state...
  }
}

Update

{
  "type": "channel_data",
  "connection_id": "1de645c9-9ed2-49d0-9192-1522cf5c45f7",
  "message_id": 290,
  "channel": "orderbook",
  "id": "WETH-DAI",
  "contents": {
    ...update...
  }
}

On the WebSocket you can subscribe to various channels to receive updates. Subscribe messages sent by clients must be of the form:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string The channel to subscribe to
id string An id to subscribe to on the channel
batched boolean (optional) Whether to batch messages when sending

Initial Response

Once subscribed, clients will receive a message:

Where initial state is the initial state of what you have subscribed to. After this, updates will be sent of the form:

Batching messages

Subscribe

{
  "type": "subscribe",
  "channel": "orderbook",
  "id": "WETH-DAI",
  "batched": true
}

Update

{
  "type": "channel_batch_data",
  "connection_id": "6bc52ffd-258a-4554-a3c6-2ebf80fa0fe3",
  "message_id": 317,
  "channel": "orderbook",
  "id": "WETH-DAI",
  "contents": [
    {
      "updates": [
        {
          "type": "NEW",
          "id": "0x03ed69375550ab371ecf31c96d7479de6024baa5c1146b8c0bf225c140deeee3",
          "amount": "13000000000000000000",
          "price": "241.86",
          "side": "BUY"
        }
      ]
    },
    {
      "updates": [
        {
          "type": "REMOVED",
          "id": "0xa7c66256f295aa75524996a190175dc002720d6a3d65ce4af667560add7f27bd",
          "side": "BUY"
        },
        {
          "type": "NEW",
          "id": "0x7e41c2eca4325ff350adb54ef46c5f6f51406fb674efc105f2d23e13aa99ee25",
          "amount": "700000000000000000000",
          "price": "241.65",
          "side": "BUY"
        }
      ]
    }
  ]
}

For batched messages, dYdX will buffer the messages on the backend. The interval time is not configurable by clients. At certain times the interval will increase to 250ms due to performance demands.

Example message structure:

Unsubscribing

Unsubscribe

{
  "type": "unsubscribe",
  "channel": "orderbook",
  "id": "WETH-DAI"
}

Response

{
  "type": "unsubscribed",
  "connection_id": "1de645c9-9ed2-49d0-9192-1522cf5c45f7",
  "message_id": 289,
  "channel": "orderbook",
  "id": "WETH-DAI"
}
Field Name JSON type Description
type string Must be set to "subscribe"
channel string The channel to unsubscribe from
id string An id to unsubscribe from on the channel

Once unsubscribed, clients will receive a message:

Orderbook

Subscribe

{
  "type": "subscribe",
  "channel": "orderbook",
  "id": "WETH-DAI"
}

Order Removed & Order Updates Messgae

{
  "type": "channel_data",
  "connection_id": "0b88ebf2-98ec-4de6-b781-62e1648ae657",
  "message_id": 1278,
  "channel": "orderbook",
  "id": "WETH-DAI",
  "contents": {
    "updates": [
      {
        "type": "REMOVED",
        "id": "0xe8aad0c4ea79e014b398da781a1b711a4c12086348cd421e4f5c19ba077c3374",
        "side": "BUY"
      },
      {
        "type": "UPDATED",
        "id": "0x510f0a948e9b4488bfcc3b5aa2abf28334e174825a56fa2c6948fd5aaf3dd420",
        "side": "SELL",
        "amount": "50600000000000000000"
      }
    ]
  }
}

The orderbook channel allows clients to receive all updates to the active orderbook. These updates are presented on a per order basis. This is the fastest way to receive updates to the orderbook.

To subscribe send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "orderbook"
id string The market to subscribe to. e.g. WETH-DAI, WETH-USDC, DAI-USDC

Response

{
  "type": "channel_data",
  "connection_id": "1de645c9-9ed2-49d0-9192-1522cf5c45f7",
  "message_id": 290,
  "channel": "orderbook",
  "id": "WETH-DAI",
  "contents": {
    "bids": [
      {
        "id": "0xefa4562c0747a8f2a9aa69abb817474ee9e98c8505a71de6054a610ac744b0cd",
        "uuid": "c58be890-6e76-4e98-95d4-27977a91af19",
        "amount": "17459277053478281216",
        "price": "160.06010000000002787211"
      },
      {
        "id": "0xa2ab9f653106fefef5b1264a509b02eab021ffea442307e995908e5360f3cd4d",
        "uuid": "d2dba4c6-6442-46bc-b097-1f37312cf279",
        "amount": "149610989871929360384",
        "price": "160.06010000000000157722"
      },
    ],
    "asks": [
      {
        "id": "0xb242e2006a0d99c390fc7256d10558844a719d580e80eaa5a4f99dd14bd9ce5e",
        "uuid": "6fdff2f3-0175-4297-bf23-89526eb9aa36",
        "amount": "12074182754430260637",
        "price": "160.30000000000000000000"
      },
      {
        "id": "0xe32a00e11b91b6f8daa70fbe03ad0100fa458c0d87e5c59f2e629ce9d5d32921",
        "uuid": "3f9b35a8-d843-4ae6-bc8b-b534b07e8093",
        "amount": "50000000000000000000",
        "price": "160.40000000000000000000"
      },
    ]
  }
}

The initial response will contain the entire state of the active orderbook. The contents field will be of the same form as GET /v1/orderbook/:market:

Market is one of: [WETH-DAI, WETH-USDC, DAI-USDC, PBTC-USDC]

Amounts for this endpoint are returned in the base asset for the market (e.g. WETH for WETH-DAI). Prices are denominated as (quote amount) / (base amount) for each given order. For markets where the tokens have different number of decimals (e.g. DAI-USDC & WETH-USDC) prices will include the decimal places (e.g. prices in DAI-USDC will look like 0.00000000000100252200)

Channel Specific Response Field Description
channel Will always be orderbook
id Market pair subscribed to
contents Object containing entire state of the orderbook at connection request

Updates to the orderbook are sent in array form, indicating atomic updates to the orderbook. There are 3 types of updates that will be sent:





Order Added Message

{
  "type": "channel_data",
  "connection_id": "0b88ebf2-98ec-4de6-b781-62e1648ae657",
  "message_id": 1277,
  "channel": "orderbook",
  "id": "WETH-DAI",
  "contents": {
    "updates": [
      {
        "type": "NEW",
        "id": "0xe8aad0c4ea79e014b398da781a1b711a4c12086348cd421e4f5c19ba077c3374",
        "amount": "50600000000000000000",
        "price": "145.97665700000000000000",
        "side": "BUY"
      }
    ]
  }
}

An order was added to the orderbook:

Update Fields Description
type Specifies the type of update
id Unique id of the order
amount The current amount of the order
price base/quote price of the order
side Side of the market the order is on






An order was removed from the orderbook (e.g. cancelled or fully filled), and another order had its amount updated:

Update Fields Description
type Specifies the type of update
id Unique id of the order
amount The current amount of the order
side Side of the market the order is on



Orders

Subscribe

{
  "type": "subscribe",
  "channel": "orders",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}

Response

{
  "type": "subscribed",
  "connection_id": "a3f64f25-4744-46f8-8456-f456f75616b2",
  "message_id": 1,
  "channel": "orders",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "orders": [
      {
        "uuid": "210ab138-017d-4983-8d87-2ca6ff0955c8",
        "id": "0x119f4e6e453a90c0eb64f6c2d3015386c4d201e89ea35a35495cba4c7edb4665",
        "createdAt": "2020-01-14T21:56:18.765Z",
        "status": "OPEN",
        "accountOwner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "accountNumber": "0",
        "orderType": "LIMIT",
        "fillOrKill": false,
        "postOnly": true,
        "market": "DAI-USDC",
        "side": "BUY",
        "baseAmount": "20000000000000000000",
        "quoteAmount": "1000000",
        "filledAmount": "0",
        "price": "0.00000000000005",
        "cancelReason": null
      }
    ]
  }
}

Order Placed Update

{
  "type": "channel_data",
  "connection_id": "a17dcc8e-9468-4308-96f5-3f458bf485d9",
  "message_id": 4,
  "channel": "orders",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "type": "ORDER",
    "order": {
      "uuid": "29c9d044-4e13-468f-8cf4-7e529e614296",
      "id": "0xb0751a113c759779ff5fd6a53b37b26211a9f8845d443323b9f877f32d9aafd9",
      "createdAt": "2020-01-14T22:22:19.131Z",
      "status": "OPEN",
      "accountOwner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
      "accountNumber": "0",
      "orderType": "LIMIT",
      "fillOrKill": false,
      "postOnly": false,
      "market": "DAI-USDC",
      "side": "BUY",
      "baseAmount": "20000000000000000000",
      "quoteAmount": "20018000",
      "filledAmount": "0",
      "price": "0.0000000000010009",
      "cancelReason": null,
      "updatedAt": "2020-01-14T22:22:19.153Z"
    }
  }
}

Order Canceled Update

{
  "type": "channel_data",
  "connection_id": "8c510abb-2e45-4f9a-be17-9c992b441da8",
  "message_id": 7,
  "channel": "orders",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "type": "ORDER",
    "order": {
      "uuid": "d98b3b81-8ffa-45c8-8e1a-38a31ab9f690",
      "id": "0x1002e3ae34834109e8f0a8429df1faf9597b39701dc6a51e1950e4c170afa21f",
      "createdAt": "2020-01-14T21:28:04.719Z",
      "status": "CANCELED",
      "accountOwner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
      "accountNumber": "0",
      "orderType": "LIMIT",
      "fillOrKill": false,
      "postOnly": false,
      "market": "DAI-USDC",
      "side": "BUY",
      "baseAmount": "20000000000000000000",
      "quoteAmount": "100000",
      "filledAmount": "0",
      "price": "0.000000000000005",
      "cancelReason": "USER_CANCELED",
      "updatedAt": "2020-01-14T21:28:19.191Z"
    }
  }
}

Order Filled Update

{
  "type": "channel_data",
  "connection_id": "839bd50b-77f6-4568-b758-cdc4b2962efb",
  "message_id": 5,
  "channel": "orders",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "type": "ORDER",
    "order": {
      "uuid": "5137f016-80dc-47e8-89b5-aee3b2db15d0",
      "id": "0x03dfd18edc2f26fc9298edcd28ca6cad4971bd1f44d40253d5154b0d1f217680",
      "createdAt": "2020-01-14T21:15:13.561Z",
      "status": "FILLED",
      "accountOwner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
      "accountNumber": "0",
      "orderType": "LIMIT",
      "fillOrKill": true,
      "postOnly": false,
      "market": "DAI-USDC",
      "side": "SELL",
      "baseAmount": "20000000000000000000",
      "quoteAmount": "19900000",
      "filledAmount": "20000000000000000000",
      "price": "0.000000000000995",
      "cancelReason": null,
      "updatedAt": "2020-01-14T21:15:14.020Z"
    }
  }
}

PENDING Fill for Order

{
  "type": "channel_data",
  "connection_id": "839bd50b-77f6-4568-b758-cdc4b2962efb",
  "message_id": 6,
  "channel": "orders",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "type": "FILL",
    "fill": {
      "uuid": "5a2efda1-39f7-44c3-a62b-d5ca925937f9",
      "status": "PENDING",
      "orderId": "0x03dfd18edc2f26fc9298edcd28ca6cad4971bd1f44d40253d5154b0d1f217680",
      "transactionHash": "0xbc331c8894dbe19f65cf4132a98ff81793d1a9e5a437ecf62801d28f4d09caa9",
      "createdAt": "2020-01-14T21:15:14.008Z",
      "updatedAt": "2020-01-14T21:15:14.026Z",
      "amount": "20000000000000000000",
      "price": "0.000000000001",
      "side": "SELL",
      "market": "DAI-USDC",
      "liquidity": "TAKER",
      "accountOwner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
    }
  }
}

The orders channel allows clients to subscribe to orders and fills pertaining to the wallet address.

Subscribing

To subscribe, send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "orders"
id string The wallet address to listen to

The initial response will be all the user's open and pending orders, inside the contents field.

Channel Specific Response Field Description
channel Will always be orders
id Wallet Address whose orders are being reported
contents Object containing entire state of the orderbook at connection request
















Updates to the orders are posted on the channel. If an order is filled, the corresponding fills will also be sent on the channel. The orders and fills are in the same format as the V2 HTTP API:

An order is first placed:

Status Explanation
PENDING The order has not yet been fully processed by the Matching-Engine.
OPEN The order is in an open position in the Matching-Engine and has not yet been filled at all.
FILLED The order has been fully filled.
PARTIALLY_FILLED The order has been partially filled.
CANCELED The order has been canceled. See Cancel Reasons below for explanations.
UNTRIGGERED Stop-Limit order has not been triggered yet.

Updates to the orders are sent as individual objects. There are 2 types of updates that will be sent:





An order was cancelled:

Cancel Reasons:

Reason Explanation
EXPIRED The order reached the expiration date specified by the field expiresAt.
UNDERCOLLATERALIZED Either this order would put the position under collateralization or the position is currently undercollateralized.
CANCELED_ON_CHAIN The order was canceled on-chain.
USER_CANCELED The user cancled the order either through an API client or on https://trade.dydx.exchange/.
SELF_TRADE Execution of the order would have led the user to be both the maker and the taker.
FAILED Either before filling or on-chain, a failure occurred that prevented the order from being placed or filled.
COULD_NOT_FILL An order with fillOrKill: true could not be filled.
POST_ONLY_WOULD_CROSS An order with postOnly: true would cross the book.




An order was filled:

Trade Status Description
PENDING The trade is has not been fully processed on-chain
REVERTED The trade was reverted on-chain
CONFIRMED The trade was confirmed on-chain














The PENDING fill for the order:

Fill Field Name Description
uuid Unique uuid of the order
status Status of the order involved in the fill
orderId Id of the order being filled
transactionHash Transaction hash for the on-chain operation
createdAt Date and time fill was cached at in ISO8601 format
updatedAt Date and time fill was updated in the cache at in ISO8601 format
amount denominated in base units. i.e. 1 ETH = 1e18
price denominated in base/quote
side Either BUY or SELL
market Market the fill is in
liquidity Either MAKER or TAKER
makerAccountOwner Wallet address of order in fill

Unsubscribing

{
  "type": "unsubscribe",
  "channel": "orders",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}

Response

{
  "type": "unsubscribed",
  "connection_id": "e7259ee2-98f5-4187-8623-9175234d5fb2",
  "message_id": 3,
  "channel": "orders",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}

Unsubscribing:

Field Name JSON type Description
type string Must be set to "unsubscribe"
channel string The channel to unsubscribe from
id string An id to unsubscribe from on the channel

Once unsubscribed, clients will receive a message:

Trades

The trades channel allows clients to receive all trades for the market. This is the fastest way to receive trades made on the market.

Subscribing

Subscribe

{
  "type": "subscribe",
  "channel": "trades",
  "id": "DAI-USDC"
}

To subscribe send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "trades"
id string The market to subscribe to. e.g. WETH-DAI, WETH-USDC, DAI-USDC

Initial Response

Response

{
  "type": "channel_data",
  "connection_id": "1de645c9-9ed2-49d0-9192-1522cf5c45f7",
  "message_id": 290,
  "channel": "trades",
  "id": "DAI-USDC",
  "contents": {
    "trades": [
      {
        "uuid": "f363d287-932e-4008-a688-fe62e9fac687",
        "createdAt": "2020-03-25T21:46:31.302Z",
        "transactionHash": "0x87bfd011dc8dcc43c512d19686d41ea9a56da3fc4cc332f245615f289d8702e0",
        "status": "PENDING",
        "market": "DAI-USDC",
        "side": "SELL",
        "price": "0.0000000000010226022495140206638887019651459949910297896178723973394978374208193",
        "amount": "957489517355305926656",
        "makerOrderId": "0xe5cdaa6dfea6e04d2f520d24b94d730b0de8cf58ee6e1e326bbdfe172b5f402a",
        "makerAccountOwner": "0x97ef7039309b938e2893d97ef75c0ceebccfbd55",
        "makerAccountNumber": "0",
        "takerOrderId": "0x8cd16a9964d83707d840cd6e26f54ab4ca425176f479d9fd1b8642fbc8f50a2c",
        "takerAccountOwner": "0x8ebab0129ffea1145a505d8d6d5d046770dd97e6",
        "takerAccountNumber": "0"
      },
      {
        "uuid": "f1909f3d-7d07-438a-8962-985083ad2e2d",
        "createdAt": "2020-03-25T21:46:31.294Z",
        "transactionHash": "0x87bfd011dc8dcc43c512d19686d41ea9a56da3fc4cc332f245615f289d8702e0",
        "status": "PENDING",
        "market": "DAI-USDC",
        "side": "SELL",
        "price": "0.0000000000010231",
        "amount": "2929446700000000081920",
        "makerOrderId": "0x5060c37571e2d243961623a8bc0d76fd63c46387ccf37241c4ee95a167e02e72",
        "makerAccountOwner": "0x97ef7039309b938e2893d97ef75c0ceebccfbd55",
        "makerAccountNumber": "0",
        "takerOrderId": "0x8cd16a9964d83707d840cd6e26f54ab4ca425176f479d9fd1b8642fbc8f50a2c",
        "takerAccountOwner": "0x8ebab0129ffea1145a505d8d6d5d046770dd97e6",
        "takerAccountNumber": "0"
      },
      {
        "uuid": "39c55c38-4829-4344-a723-dc44f867019d",
        "createdAt": "2020-03-25T21:46:31.290Z",
        "transactionHash": "0x87bfd011dc8dcc43c512d19686d41ea9a56da3fc4cc332f245615f289d8702e0",
        "status": "PENDING",
        "market": "DAI-USDC",
        "side": "SELL",
        "price": "0.0000000000010216",
        "amount": "1002063782644693991424",
        "makerOrderId": "0x289b2cb5ad4673beff2b1b8819a7a17df7d1ddfecde352cd53344343787bbaaf",
        "makerAccountOwner": "0x97ef7039309b938e2893d97ef75c0ceebccfbd55",
        "makerAccountNumber": "0",
        "takerOrderId": "0x8cd16a9964d83707d840cd6e26f54ab4ca425176f479d9fd1b8642fbc8f50a2c",
        "takerAccountOwner": "0x8ebab0129ffea1145a505d8d6d5d046770dd97e6",
        "takerAccountNumber": "0"
      },
    ],
  }
}

The initial response will contain the most recent 100 orders from the active market:

Response Fields:

Trade Field Name Description
uuid Unique uuid of the order
createdAt Date and time trade was cached at in ISO8601 format
transactionHash Transaction hash for the on-chain operation
status Status of the order involved in the trade
market Market the trade is in
side Either BUY or SELL
price denominated in base/quote
amount denominated in base units. i.e. 1 ETH = 1e18
makerOrderId Id of maker order in trade
makerAccountOwner Wallet address of maker order in trade
makerAccountNumber Account number of maker order in trade
takerOrderId Id of taker order in trade
takerAccountOwner Wallet address of taker order in trade
takerAccountNumber Account number of taker order in trade
Trade Status Description
PENDING The trade is has not been fully processed on-chain
REVERTED The trade was reverted on-chain
CONFIRMED The trade was confirmed on-chain
















Updates

Update

{
  "type": "channel_data",
  "connection_id": "0b88ebf2-98ec-4de6-b781-62e1648ae657",
  "message_id": 1277,
  "channel": "trades",
  "id": "DAI-USDC",
  "contents": {
    "updates": [
      {
        "uuid": "7cb4e283-20bf-4ccf-a15b-dc84b86965dd",
        "createdAt": "2020-03-25T21:46:23.351Z",
        "transactionHash": "0xe7cd5f4fafc05c707205d8090d9cd592a87daec3977c5d1c7f0953c68f562bf6",
        "status": "CONFIRMED",
        "market": "DAI-USDC",
        "side": "BUY",
        "price": "0.0000000000010245",
        "amount": "1024685243041289076736",
        "makerOrderId": "0x9bd33ad14caa817135dd92d062b449ffa477f75c4f28f85825e752148e22a96e",
        "makerAccountOwner": "0x97ef7039309b938e2893d97ef75c0ceebccfbd55",
        "makerAccountNumber": "0",
        "takerOrderId": "0x195a54220932ccb9416e9eba6189ffee4248b2e37b403f340982ba695c55a311",
        "takerAccountOwner": "0x97ef7039309b938e2893d97ef75c0ceebccfbd55",
        "takerAccountNumber": "0"
      }
    ]
  }
}

New trades are sent in array form.

A trade executed for the market:

Response Fields:

Trade Field Name Description
uuid Unique uuid of the order
createdAt Date and time trade was cached at in ISO8601 format
transactionHash Transaction hash for the on-chain operation
status Status of the order involved in the trade
market Market the trade is in
side Either BUY or SELL
price denominated in base/quote
amount denominated in base units. i.e. 1 ETH = 1e18
makerOrderId Id of maker order in trade
makerAccountOwner Wallet address of maker order in trade
makerAccountNumber Account number of maker order in trade
takerOrderId Id of taker order in trade
takerAccountOwner Wallet address of taker order in trade
takerAccountNumber Account number of taker order in trade

Unsubscribing

Unsubscribe

{
  "type": "unsubscribe",
  "channel": "trades",
  "id": "DAI-USDC"
}
Field Name JSON type Description
type string Must be set to "unsubscribe"
channel string The channel to unsubscribe from
id string A market to unsubscribe from on the channel

Response

Response

{
  "type": "unsubscribed",
  "connection_id": "e7259ee2-98f5-4187-8623-9175234d5fb2",
  "message_id": 3,
  "channel": "trades",
  "id": "DAI-USDC"
}

Once unsubscribed, clients will receive a message:

Index Price

The index price channel allows clients to receive updates about a particular market.

Subscribing

Subscribe

{
  "type": "subscribe",
  "channel": "index_price",
  "id": "<market name>"
}

To subscribe send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "index_price"
id string The market to receive updates for eg: "PBTC-USDC"

Initial Response

Response

{
  "type": "subscribed",
  "connection_id": "ab262c58-985f-4bd5-84f6-d49f6cf154cc",
  "message_id": 1,
  "channel": "index_price",
  "id": "PBTC-USDC",
  "contents": {
    "PBTC-USDC": {
      "price": "94.38959",
      "live": true
    }
  }
}

The initial response will contain the information for the specified index-price:

Response Field Description
market Name of market eg: "PBTC-USDC"
price Current index price for the market off-chain
live If the price is live or if it is a cached (most recent) price






Updates

Update

{
  "type": "channel_data",
  "connection_id": "ab262c58-985f-4bd5-84f6-d49f6cf154cc",
  "message_id": 2,
  "channel": "index_price",
  "id": "PBTC-USDC",
  "contents": {
    "type": "INDEX_PRICE",
    "indexPrice": {
      "market": "PBTC-USDC",
      "price": "94.38959"
    }
  }
}

New index-price updates are sent to the channel:

Example:

Websocket update message content structure

Field Description
type Type of the message.
indexPrice The IndexPrice object
market The market string, e.g.: PBTC-USDC.
price The index price from the off-chain oracle.

Unsubscribing

Unsubscribe

{
  "type": "unsubscribe",
  "channel": "index_price",
  "id": "<the market name>"
}
Field Name JSON type Description
type string Must be set to "unsubscribe"
channel string The channel to unsubscribe from
id string A market to unsubscribe from on the channel

Response

Response

{
  "type": "unsubscribed",
  "connection_id": "ab262c58-985f-4bd5-84f6-d49f6cf154cc",
  "message_id": 27,
  "channel": "index_price",
  "id": "PBTC-USDC"
}

Once unsubscribed, clients will receive a message:

Positions

Subscribe

{
  "type": "subscribe",
  "channel": "positions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}

The positions channel allows clients to receive updates about their existing positions.

To subscribe send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "positions"
id string The wallet address to subscribe to

Response

{
  "type": "subscribed",
  "connection_id": "e08534fb-f52b-4754-85b2-4a81e26f2cd4",
  "message_id": 1,
  "channel": "positions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "positions": [
      {
        "uuid": "d4b60574-f1d3-478c-921b-48b416640b0a",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "number": "18391807697043682023758523528032951427719342564248970230470210680141737387458",
        "market": "WETH-DAI",
        "type": "ISOLATED_LONG",
        "status": "OPEN",
        "accountUuid": "6793b2f8-5b07-4bce-ba54-da33372ae988",
        "expiresAt": "2020-03-26T23:10:31.000Z",
        "createdAt": "2020-02-27T23:10:37.319Z",
        "updatedAt": "2020-02-27T23:11:31.773Z",
        "account": {
          "uuid": "6793b2f8-5b07-4bce-ba54-da33372ae988",
          "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
          "number": "18391807697043682023758523528032951427719342564248970230470210680141737387458",
          "createdAt": "2020-02-27T23:08:55.303Z",
          "updatedAt": "2020-02-27T23:08:55.303Z"
        },
        "standardActions": [
          {
            "uuid": "b95fa3fc-84a7-46f1-9ce0-1eca1b144117",
            "type": "ISOLATED_OPEN",
            "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
            "transferAmount": "33720746949513441",
            "tradeAmount": "66666666666666667",
            "price": "227.9799999999999999901000000000000000494999999999999997525000000000000012375",
            "market": "WETH-DAI",
            "asset": "WETH",
            "side": "LONG",
            "operationUuid": "3ce07798-433f-4cab-b699-3cd17f90308f",
            "transactionHash": "0x028e9c22856673a89e649d0d13ded6cb7ff6968313e52ababd66b49900d39123",
            "positionUuid": "d4b60574-f1d3-478c-921b-48b416640b0a",
            "borrowAmount": null,
            "orderNumber": "956855500050000",
            "confirmedAt": "2020-02-27T23:10:31.000Z",
            "createdAt": "2020-02-27T23:11:31.758Z",
            "updatedAt": "2020-02-27T23:11:31.778Z"
          }
        ]
      }
    ]
  }
}

The initial response is an array of positions that are open.

The intial subscription message is sent as an object of two arrays. There are 2 values in the array that will be sent:

Subsequent updates will only include a position object

Position Status Description
OPEN Position is Currently Open
CLOSED The position has been closed out
INVALID The position is invalid and does not exist
EXPIRED The position reached its expiration date and closed as a result
LIQUIDATED Due to undercollateralization, the position was liquidated.
STOP_EXECUTED Triggerable order associated with the position was met and the position closed out
























Position Closed

{
  "type": "channel_data",
  "connection_id": "fcccc0a9-20af-4c55-ab48-a7f285efdfde",
  "message_id": 6,
  "channel": "positions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "pending": true,
    "hash": "0x2dbe08ace3c10a16dfc7137333ba32463631d698f768b97b28cb9e8265075a3d",
    "position": {
      "uuid": "e2827c5f-a651-40b6-aaf7-01b2a04bd2d4",
      "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
      "number": "10301656009924513450047526987008292264633253953002046801477043073002343349750",
      "market": "WETH-DAI",
      "type": "ISOLATED_SHORT",
      "status": "CLOSED",
      "accountUuid": "eda666d3-8a89-4f8d-adb5-2e47b6aa630c",
      "expiresAt": "2020-04-01T00:03:20.000Z",
      "createdAt": "2020-03-04T00:03:50.175Z",
      "updatedAt": "2020-03-04T00:07:47.296Z"
    }
  }
}

Updates to the users position are posted to the positions channel. eg:- A position is closed:

Update Response Field Description
pending Whether the position is still waiting to be confirmed
hash The transaction hash corresponding to the position
uuid The unique identifier for the position
owner The account address
number The account number
market The market for this position eg WETH-DAI
type The position type er: ISOLATED_LONG or ISOLATED_SHORT
status The position status eg: OPEN, CLOSED




Unsubscribe

{
  "type": "unsubscribe",
  "channel": "positions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}

Unsubscribing:

Field Name JSON type Description
type string Must be set to "unsubscribe"
channel string The channel to unsubscribe from i.e. "positions"
id string An id to unsubscribe from on the channel

Response

{
  "type": "unsubscribed",
  "connection_id": "e08534fb-f52b-4754-85b2-4a81e26f2cd4",
  "message_id": 7,
  "channel": "positions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}

Once unsubscribed, clients will receive a message:

Standard Actions

Subscribe

{
  "type": "subscribe",
  "channel": "standard_actions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}

The standard actions channel allows clients to receive updates about actions such as DEPOSIT, ISOLATED_OPEN, etc.

To subscribe send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "standard_actions"
id string The wallet address to subscribe to

Response

{
  "type": "subscribed",
  "connection_id": "63b32e89-a572-4e6b-833e-2faf6fe1e195",
  "message_id": 1,
  "channel": "standard_actions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "standardActions": [
      {
        "uuid": "b95fa3fc-84a7-46f1-9ce0-1eca1b144117",
        "type": "ISOLATED_OPEN",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "transferAmount": "33720746949513441",
        "tradeAmount": "66666666666666667",
        "price": "227.9799999999999999901000000000000000494999999999999997525000000000000012375",
        "market": "WETH-DAI",
        "asset": "WETH",
        "side": "LONG",
        "operationUuid": "3ce07798-433f-4cab-b699-3cd17f90308f",
        "transactionHash": "0x028e9c22856673a89e649d0d13ded6cb7ff6968313e52ababd66b49900d39123",
        "positionUuid": "d4b60574-f1d3-478c-921b-48b416640b0a",
        "borrowAmount": null,
        "orderNumber": "956855500050000",
        "confirmedAt": "2020-02-27T23:10:31.000Z",
        "createdAt": "2020-02-27T23:11:31.758Z",
        "updatedAt": "2020-02-27T23:11:31.778Z"
      },
      {
        "uuid": "c237ec6d-9599-40fa-acb5-e8b4c89827ad",
        "type": "ISOLATED_FULL_CLOSE",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "transferAmount": "7208389487816291503",
        "tradeAmount": "100000001487414238",
        "price": "225.85999763831216716128108275674475187561565528432069314401462859563656946568221903",
        "market": "WETH-DAI",
        "asset": "DAI",
        "side": "SHORT",
        "operationUuid": "0a0971b0-1fe2-45f9-bed5-b576bdacb732",
        "transactionHash": "0x16d9eed48b0cf10ffe96999c6c458fbbb6edd36f9d81fac3cc34e8d968f55e79",
        "positionUuid": "8ed5867f-aa3a-4cbf-a661-47cd0f24db85",
        "borrowAmount": null,
        "orderNumber": "956189301250000",
        "confirmedAt": "2020-02-26T22:35:39.000Z",
        "createdAt": "2020-02-26T22:38:17.152Z",
        "updatedAt": "2020-02-26T22:38:17.180Z"
      },
      {
        "uuid": "9b3738a0-92d3-46e2-b8fc-9211e5969ae8",
        "type": "ISOLATED_OPEN",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "transferAmount": "7379308716494646154",
        "tradeAmount": "100000000000000000",
        "price": "225.27999999999999644",
        "market": "WETH-DAI",
        "asset": "DAI",
        "side": "SHORT",
        "operationUuid": "130bc3fa-5ed7-42ca-b972-d1ade4d7c9f2",
        "transactionHash": "0xc98e1246c180278ffd1851e11b56afd59feeda26144d8f89d8e3dca02aab780e",
        "positionUuid": "8ed5867f-aa3a-4cbf-a661-47cd0f24db85",
        "borrowAmount": null,
        "orderNumber": "956188200160000",
        "confirmedAt": "2020-02-26T22:32:54.000Z",
        "createdAt": "2020-02-26T22:33:51.920Z",
        "updatedAt": "2020-02-26T22:33:51.946Z"
      },
      {
        "uuid": "e418ec53-d7fb-4f74-a4c4-5a8ecb6b7f73",
        "type": "ISOLATED_FULL_CLOSE",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "transferAmount": "50337795123416145",
        "tradeAmount": "50002015563715323",
        "price": "266.06001958983337426563213321841718225957351026342936018892644893242773949836804886",
        "market": "WETH-DAI",
        "asset": "WETH",
        "side": "LONG",
        "operationUuid": "719177b1-34be-4872-be11-c76da55358e4",
        "transactionHash": "0x68427cf28e08b0b00be4d58fa7e074adb595cf71f7409377398bc8b3ec3a740f",
        "positionUuid": "c088f1aa-cf10-4122-b767-1c78376865c0",
        "borrowAmount": null,
        "orderNumber": "954926000820000",
        "confirmedAt": "2020-02-24T23:56:56.000Z",
        "createdAt": "2020-02-24T23:58:02.477Z",
        "updatedAt": "2020-02-24T23:58:02.496Z"
      },
      {
        "uuid": "c94687cd-68d6-4b92-a34e-eac80be17028",
        "type": "DEPOSIT",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "transferAmount": "1000000000000000000",
        "tradeAmount": null,
        "price": null,
        "market": null,
        "asset": "WETH",
        "side": null,
        "operationUuid": "6bc95ff7-9c1e-4fab-9cf7-8d2c3492329b",
        "transactionHash": "0xfa53ce0a88f71d5671dd7695d3f3cd3344e9a0e0a638f710f5ec8bc791171c0d",
        "positionUuid": null,
        "borrowAmount": null,
        "orderNumber": "954918100860000",
        "confirmedAt": "2020-02-24T23:41:45.000Z",
        "createdAt": "2020-02-24T23:42:49.788Z",
        "updatedAt": "2020-02-24T23:42:49.792Z"
      },
      {
        "uuid": "ae1bffd4-95bc-45e1-87cc-08cb3c0f8af7",
        "type": "TRADE",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "transferAmount": null,
        "tradeAmount": "20000000000000000000",
        "price": "0.000000000000994204",
        "market": "DAI-USDC",
        "asset": null,
        "side": "SELL",
        "operationUuid": "7837d560-5d13-4bdc-874b-0762eede1173",
        "transactionHash": "0x5fdc86ffb39350070801130c5beb82c7e98c5e9fd2ccd63880f51c5026af034b",
        "positionUuid": null,
        "borrowAmount": null,
        "orderNumber": "954918100580000",
        "confirmedAt": "2020-02-24T23:41:45.000Z",
        "createdAt": "2020-02-24T23:43:19.711Z",
        "updatedAt": "2020-02-24T23:43:19.717Z"
      }
    ]
  }
}

The initial response will be the latest 100 standard actions on the user's account.

Standard Action Field Description
uuid Unique id of the standard action
type Type of the standard action
owner Wallet address of the standard action performer
transferAmount The amount in settlement token that is
tradeAmount The amount traded. i.e. the base token amount in a trade
price The price in settlement token
market The market, e.g. WETH-USDC or PBTC-USDC
asset The asset eg WETH, DAI, USDC for deposit or withdraw
side The side for the standard action e.g. LONG, SHORT
operationUuid The unique identifier cached for the operation associated with the standard action
transactionHash The transaction corresponding to this standard action
positionUuid The unique identifier cached for the position associated with the standard action
borrowAmount For BORROW actions, the amount borrowed
orderNumber Used for ordering a standard action update
createdAt The ISO 8601 date and time this balance update was created
updatedAt The ISO 8601 date and time this balance update was updated
Standard Action Type Description
DEPOSIT Currency is being deposited into an account
REPAY Borrow action is being repaid
WITHDRAW Currency is being withdrawn from an account
BORROW Currency is being borrowed
LIQUIDATE A position or account is being liquidated
LIQUIDATED A position or account has been liquidated
EXPIRE A position is expiring
EXPIRED A position has expired
TRADE A trade between two accounts is occurring
ISOLATED_OPEN A new Isolated margin position is being opened
ISOLATED_PARTIAL_CLOSE An Isolated position has been partially closed
ISOLATED_FULL_CLOSE An Isolated position has been fully closed
ACCOUNT_SETTLE An account settlment action is occurring
OPEN A trade is in an open state on the matching-engine
CLOSE A trade has closed
INCREASE An account balance has been increased
DECREASE An account balance has been decreased








































Update

{
  "type": "channel_data",
  "connection_id": "8427b0ba-d703-43e5-acb6-3f04d9fbebea",
  "message_id": 10,
  "channel": "standard_actions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "pending": true,
    "hash": "0xa0acbb3ebeae61d692267ec7269fa851e12189e9238ad03ee48bc843fdb80b96",
    "standardAction": {
      "uuid": "a13255e8-586a-4a4c-8e9a-2454b138ffb9",
      "type": "DEPOSIT",
      "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
      "number": "0",
      "transferAmount": "100000000000000000",
      "tradeAmount": null,
      "price": null,
      "market": null,
      "asset": "WETH",
      "side": null,
      "operationUuid": "b4f8f664-7238-452d-89dd-69a45fb1a0be",
      "transactionHash": "0xa0acbb3ebeae61d692267ec7269fa851e12189e9238ad03ee48bc843fdb80b96",
      "positionUuid": null,
      "borrowAmount": null,
      "orderNumber": "960121200610000",
      "confirmedAt": "2020-03-03T23:37:00.000Z",
      "feeAmount": null,
      "feeAsset": null,
      "createdAt": "2020-03-03T23:37:04.198Z",
      "updatedAt": "2020-03-03T23:37:04.200Z"
    }
  }
}

New actions performed by the user are posted on the channel.

Websocket updates message contents structure

Field Description
pending Whether the standard action is still waiting to be confirmed
hash The transaction hash corresponding to the standard action
standardAction The standardAction object
uuid The unique id for the action.
owner The wallet address of the user.
type The type of standard action e.g. DEPOSIT, ISOLATED_OPEN (for solo), OPEN, ACCOUNT_SETTLE (for perpetual)
market The market, e.g. WETH-USDC or PBTC-USDC.
side The side for the standard action e.g. LONG, SHORT.
transferAmount The amount in settlement token that is transferred.
tradeAmount The amount traded. i.e. the base token amount in a trade
price The price in settlement token.
orderNumber Number used for ordering the standard actions.
updatedAt The ISO 8601 date and time the standard action was updated.
createdAt The ISO 8601 date and time the standard action was created.
confirmedAt The ISO 8601 date and time the standard action was confirmed.
product The product type, e.g. perpetual or solo.
transactionHash The transaction corresponding to this standard action
pnl The PnL for the corresponding position. Currently not set in the standard action for perpetual.
feeAmount The fee amount charged
feeAsset The asset of the feeAmount eg DAI, USDC
asset The asset eg WETH, DAI, USDC for deposit or withdraw
payoutAmount The amount refunded to the user when maker fee is negative

Unsubscribing

Unsubscribe

{
  "type": "unsubscribe",
  "channel": "standard_actions",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}
Field Name JSON type Description
type string Must be set to "unsubscribe"
channel string The channel to unsubscribe from
id string An id to unsubscribe from on the channel

Balance updates

The balance updates channel allows clients to receive updates about balances and expirations when an operation is confirmed etc.

Subscribing

Subscribe

{
  "type": "subscribe",
  "channel": "balance_updates",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}

To subscribe send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "balance_updates"
id string The wallet address to subscribe to

Initial Response

Response

{
  "type": "subscribed",
  "connection_id": "fbb65bfb-b460-49a0-9afa-029420b1b6d2",
  "message_id": 1,
  "channel": "balance_updates",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "balanceUpdates": [
      {
        "uuid": "787bc050-dc06-4d41-8dd0-43db57e0ba1b",
        "deltaWei": "-6443662021540585812",
        "newPar": "0",
        "accountUuid": "a108e8dc-043f-4e35-a61c-8c0d8bd605e6",
        "actionUuid": "55efbba1-08ba-4af5-b03a-bf50a47ae6c0",
        "marketId": 3,
        "expiresAt": null,
        "orderNumber": "963883600170002",
        "newWei": "0",
        "confirmedAt": "2020-03-09T18:26:06.000Z",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "number": "23250809876488196813448176070712780961598248407839150544631431380708932406146",
        "isPendingBlock": null,
        "createdAt": "2020-03-22T11:48:11.941Z",
        "updatedAt": "2020-03-22T11:48:11.941Z"
      },
      {
        "uuid": "8970e854-32b6-49a7-99eb-d5d491be03c0",
        "deltaWei": "6443662021540585812",
        "newPar": "9723610723617108642",
        "accountUuid": "6a56f996-42ee-4925-8e2b-3437e7734c34",
        "actionUuid": "55efbba1-08ba-4af5-b03a-bf50a47ae6c0",
        "marketId": 3,
        "expiresAt": null,
        "orderNumber": "963883600170002",
        "newWei": "9860083718207192031.997074607802540022",
        "confirmedAt": "2020-03-09T18:26:06.000Z",
        "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
        "number": "0",
        "isPendingBlock": null,
        "createdAt": "2020-03-22T11:48:11.942Z",
        "updatedAt": "2020-03-22T11:48:11.942Z"
      }
    ]
  }
}

The initial response will be the latest 100 balance updates on the user's account.

Balance Update Field Description
uuid Unique id of the balance update
deltaWei Change in balance Wei
newPar Resultant Par in the balance due to deltaWei
accountUuid Unique id of the associated account
actionUuid Unique id of the associated action
marketId The id of the market for this balance update
expiresAt When the balance will update, if at all
orderNumber Used for ordering a balance update
newWei The new wei value due to the balance update
confirmedAt The ISO 8601 date and time this balance update was confirmed
owner The account address
number The account number
isPendingBlock Whether the balance update is still pending
createdAt The ISO 8601 date and time this balance update was created
updatedAt The ISO 8601 date and time this balance update was updated






Updates

Update

{
  "type": "channel_data",
  "connection_id": "fbb65bfb-b460-49a0-9afa-029420b1b6d2",
  "message_id": 7,
  "channel": "balance_updates",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
  "contents": {
    "type": "BALANCE_UPDATE",
    "pending": false,
    "hash": "0xc7d682dcd18cf84e4b04cde01e65a9f4961faad476a12b9b6b66e7fcb48e53dd",
    "balanceUpdate": {
      "uuid": "63016bd1-fbc5-4544-876a-3b9eef6d60ca",
      "deltaWei": "-100000000000000000",
      "newPar": "1508081686843845130",
      "accountUuid": "6a56f996-42ee-4925-8e2b-3437e7734c34",
      "actionUuid": "1c900392-0589-4567-9d80-7b4427b4dd8a",
      "marketId": 0,
      "expiresAt": null,
      "orderNumber": "973118700550002",
      "newWei": "1509359692212859652.41423281486264464",
      "confirmedAt": "2020-03-24T01:14:10.000Z",
      "owner": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c",
      "number": "0",
      "isPendingBlock": null,
      "createdAt": "2020-03-24T01:15:04.269Z",
      "updatedAt": "2020-03-24T01:15:04.269Z"
    }
  }
}

New actions performed by the user are posted on the channel.

Websocket update message content structure

Field Description
pending Whether the balance update is still waiting to be confirmed
hash The transaction hash corresponding to the balance update
balanceUpdate The balanceUpdate object
uuid Unique identifier for a balance update
deltaWei The change in wei in a balance update
newPar The new par value due to the balance update
newWei The new wei value due to the balance update
orderNumber Used for ordering a balance update
isPendingBlock Whether the balance update is still pending
owner The account address
number The account number
marketId The id of the market for this balance update
confirmedAt The ISO 8601 date and time this balance update was confirmed
createdAt The ISO 8601 date and time this balance update was created
updatedAt The ISO 8601 date and time this balance update was updated

Unsubscribing

Unsubscribe

{
  "type": "unsubscribe",
  "channel": "balance_updates",
  "id": "0x014be43bf2d72a7a151a761a1bd5224f7ad4973c"
}
Field Name JSON type Description
type string Must be set to "unsubscribe"
channel string The channel to unsubscribe from
id string An id to unsubscribe from on the channel

Perpetual Balance Updates

The perpetual balance updates channel allows clients to receive balance updates for the perpetual product for their account.

Subscribing

Subscribe

{
  "type": "subscribe",
  "channel": "perpetual_balance_updates",
  "id": "<account address>"
}

To subscribe send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "perpetual_balance_updates"
id string The account address to receive perpetual balance updates for

Initial Response

Response

{
  "type": "subscribed",
  "connection_id": "5da13205-2f3a-41c8-9f4a-cb0e5aa72dd4",
  "message_id": 1,
  "channel": "perpetual_balance_updates",
  "id": "0x77A035b677D5A0900E4848Ae885103cD49af9633",
  "contents": {
    "balanceUpdates": [
      {
        "uuid": "3d7d6a8d-0202-4e40-ae2b-dff670efbbf9",
        "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
        "market": "PBTC-USDC",
        "deltaMargin": "-1741062",
        "newMargin": "40181034",
        "deltaPosition": "20000",
        "newPosition": "10000",
        "indexValue": "0.057858741951992068",
        "indexTimestamp": "1588271672",
        "isPendingBlock": false,
        "orderNumber": "997556200290002",
        "createdAt": "2020-05-03T02:53:41.421Z",
        "updatedAt": "2020-05-03T02:53:41.421Z"
      },
      {
        "uuid": "45bb37d9-f608-428a-9868-b1a9c1925e57",
        "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
        "market": "PBTC-USDC",
        "deltaMargin": "0",
        "newMargin": "41922096",
        "deltaPosition": "0",
        "newPosition": "-10000",
        "indexValue": "0.057858741951992068",
        "indexTimestamp": "1588271672",
        "isPendingBlock": false,
        "orderNumber": "997556200290000",
        "createdAt": "2020-05-03T02:53:41.419Z",
        "updatedAt": "2020-05-03T02:53:41.419Z"
      }
    ]
  }
}

The initial response will contain the most recent 100 perpetual balance updates for the account:

Field Description
uuid The unique ID for the balance update.
owner The wallet address of the user.
market The perpetual market, e.g. PBTC-USDC.
deltaMargin The change in settlement token (e.g. USDC).
newMargin The new balance of settlement token (e.g. USDC).
deltaPosition The change in position token (e.g. PBTC).
newPosition The amount in position token (e.g. PBTC).
indexValue The new index value of the account.
indexTimestamp The timestamp for when the index value was set.
isPendingBlock Whether the specific balance update is pending or not
orderNumber Number used for ordering the balance updates.
createdAt The ISO 8601 date and time this balance update was created
updatedAt The ISO 8601 date and time this balance update was updated










Updates

Update

{
  "type": "channel_data",
  "connection_id": "5a767699-aad6-425e-b18a-a96eb5711a1d",
  "message_id": 7,
  "channel": "perpetual_balance_updates",
  "id": "0x77a035b677d5a0900e4848ae885103cd49af9633",
  "contents": {
    "pending": true,
    "hash": "0xdcd230955f15d1c4747c36d0d094a6fb5c596ed3d43854d773f4a112a33bf7e6",
    "perpetualBalanceUpdate": {
      "uuid": "4bda3a11-f261-4dc8-ae40-7990541c7226",
      "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
      "market": "PBTC-USDC",
      "deltaMargin": "2321",
      "newMargin": "129190281",
      "deltaPosition": "0",
      "newPosition": "-990000",
      "indexValue": "1.205724630104738866",
      "indexTimestamp": "1590092070",
      "isPendingBlock": true,
      "orderNumber": "1011133800340001",
      "updatedAt": "2020-05-21T20:14:52.626Z",
      "createdAt": "2020-05-21T20:14:52.626Z"
    }
  }
}

New perpetual balance updates are sent in array form.

Example:

Websocket update message content structure

Field Description
pending Whether the perpetual balance update is still waiting to be confirmed
hash The transaction hash corresponding to the perpetual balance update
uuid The unique ID for the balance update.
owner The wallet address of the user.
market The perpetual market, e.g. PBTC-USDC.
deltaMargin The change in settlement token (e.g. USDC).
newMargin The new balance of settlement token (e.g. USDC).
deltaPosition The change in position token (e.g. PBTC).
newPosition The amount in position token (e.g. PBTC).
indexValue The new index value of the account.
indexTimestamp The timestamp for when the index value was set.
orderNumber Number used for ordering the balance updates.
isPendingBlock Whether the specific balance update is pending or not

Unsubscribing

Unsubscribe

{
  "type": "unsubscribe",
  "channel": "perpetual_balance_updates",
  "id": "<the account address>"
}
Field Name JSON type Description
type string Must be set to "unsubscribe"
channel string The channel to unsubscribe from
id string A market to unsubscribe from on the channel

Response

Response

{
  "type": "unsubscribed",
  "connection_id": "6c9cfd91-d20e-4920-9545-70640876a677",
  "message_id": 1,
  "channel": "perpetual_balance_updates",
  "id": "0x77A035b677D5A0900E4848Ae885103cD49af9633"
}

Once unsubscribed, clients will receive a message:

Perpetual Markets

The perpetual markets channel allows clients to receive updates about a particular market.

Subscribing

Subscribe

{
  "type": "subscribe",
  "channel": "perpetual_markets",
  "id": "<market name>"
}

To subscribe send:

Field Name JSON type Description
type string Must be set to "subscribe"
channel string Must be set to "perpetual_markets"
id string The market to receive updates for eg: "PBTC-USDC"

Initial Response

Response

{
  "type": "subscribed",
  "connection_id": "e0107276-e4dd-4b33-9cbf-7746f87b7799",
  "message_id": 1,
  "channel": "perpetual_markets",
  "id": "PBTC-USDC",
  "contents": {
    "market": {
      "uuid": "f6d20698-32ac-4f3a-a9c4-b6b7528b7b94",
      "market": "PBTC-USDC",
      "oraclePrice": "90.3551",
      "fundingRate": "0.000000017511403011",
      "minCollateral": "1.075",
      "globalIndexValue": "1.207692942350066675",
      "globalIndexTimestamp": "1590093314",
      "decimals": "8",
      "minimumTickSize": "0.01",
      "minimumOrderSize": "10000",
      "smallOrderThreshold": "1000000",
      "makerFee": "-0.00025",
      "largeTakerFee": "0.00075",
      "smallTakerFee": "0.005",
      "openInterest": "2835957144",
      "predictedFundingRate": "0.000000017611403011",
      "fundingRateUpdatedAt": "2020-06-29T21:00:33.000Z",
      "createdAt": "2020-04-09T22:42:35.696Z",
      "updatedAt": "2020-05-21T20:46:35.941Z"
    }
  }
}

The initial response will contain the information for the specified market:

Field Description
uuid The unique ID for the market
market The perpetual market, e.g. PBTC-USDC
oraclePrice The index price from the oracle
fundingRate The funding rate for the market
minCollateral The minimum collaterization before getting liquidated eg: 1.07
globalIndexValue The global index value for the market
globalIndexTimestamp The Unix timestamp (seconds) for the last update to the global index
decimals Corresponds to the precision for the position units eg: if decimals = 8, then 100000000 = 1 BTC
minimumTickSize The minimum price amount eg: 0.01 (equal to $1)
minimumOrderSize The minimum size, in position units, required for an order
smallOrderThreshold The threshold, in position units, at which we charge different fees for takers
makerFee The percentage fee charged for the maker of an order eg -0.00025 (equal to -0.025%)
largeTakerFee Applies to orders >= smallOrderThreshold. eg 0.00075 (equal to 0.075%)
smallTakerFee Applies to orders < smallOrderThreshold. eg 0.005 (equal to 0.5%)
openInterest openInterest is the sum of the position amount of all longs (equal to sum of amount of all shorts)
predictedFundingRate The predicted next funding rate
fundingRateUpdatedAt When the funding rate was last updated
createdAt The ISO 8601 date and time this markete was created
updatedAt The ISO 8601 date and time this market was updated

Updates

Update

{
  "type": "channel_data",
  "connection_id": "e0107276-e4dd-4b33-9cbf-7746f87b7799",
  "message_id": 16,
  "channel": "perpetual_markets",
  "id": "PBTC-USDC",
  "contents": {
    "market": {
      "uuid": "f6d20698-32ac-4f3a-a9c4-b6b7528b7b94",
      "market": "PBTC-USDC",
      "oraclePrice": "90.3551",
      "fundingRate": "0.000000017511403011",
      "minCollateral": "1.075",
      "globalIndexValue": "1.207692942350066675",
      "globalIndexTimestamp": "1590093314",
      "decimals": "8",
      "minimumTickSize": "0.01",
      "minimumOrderSize": "10000",
      "smallOrderThreshold": "1000000",
      "makerFee": "-0.00025",
      "largeTakerFee": "0.00075",
      "smallTakerFee": "0.005",
      "openInterest": "2835957144",
      "predictedFundingRate": "0.000000017611403011",
      "fundingRateUpdatedAt": "2020-06-29T21:00:33.000Z",
      "createdAt": "2020-04-09T22:42:35.696Z",
      "updatedAt": "2020-05-21T20:49:05.482Z"
    }
  }
}

New perpetual market updates are sent to the channel:

Example:

Websocket update message content structure

Field Description
market The market string, e.g.: PBTC-USDC.
oraclePrice The index price from the oracle.
fundingRate The funding rate for the market.
globalIndexValue The global index value for the market.
globalIndexTimestamp The Unix timestamp (seconds) for the last update to the global index.
minCollateral The minimum collaterization before getting liquidated eg: 1.07
decimals Corresponds to the precision for the position units eg: if decimals = 8, then 100000000 = 1 BTC
minimumTickSize The minimum price amount eg: 0.01 (equal to $1)
minimumOrderSize The minimum size, in position units, required for an order
smallOrderThreshold The threshold, in position units, at which we charge different fees for takers
makerFee The percentage fee charged for the maker of an order eg -0.00025 (equal to -0.025%)
largeTakerFee Applies to orders >= smallOrderThreshold. eg 0.00075 (equal to 0.075%)
smallTakerFee Applies to orders < smallOrderThreshold. eg 0.005 (equal to 0.5%)
openInterest openInterest is the sum of the position amount of all longs (equal to sum of amount of all shorts)
predictedFundingRate The predicted next funding rate
fundingRateUpdatedAt When the funding rate was last updated

Unsubscribing

Unsubscribe

{
  "type": "unsubscribe",
  "channel": "perpetual_markets",
  "id": "<the market name>"
}
Field Name JSON type Description
type string Must be set to "unsubscribe"
channel string The channel to unsubscribe from
id string A market to unsubscribe from on the channel

Response

Response

{
  "type": "unsubscribed",
  "connection_id": "e0107276-e4dd-4b33-9cbf-7746f87b7799",
  "message_id": 27,
  "channel": "perpetual_markets",
  "id": "PBTC-USDC"
}

Once unsubscribed, clients will receive a message:

Solo Protocol


GitHub

The dYdX protocol (A.K.A. "Solo") consists of smart contracts that run on the Ethereum blockchain. These contracts support margin trading, borrowing, and lending.

Solo is used by trade.dydx.exchange.

Accounts

Solo is Account based. Each Account is referenced by its owner Ethereum address and an account number unique to that owner address. Accounts have balances on each asset supported by Solo, which can be either positive (indicating a net supply of the asset) or negative (indicating a net borrow of an asset). Accounts must maintain a certain level of collateralization or they will be liquidated.

Example

Ethereum Address 0x6b5Bb4E60821eCE7363CaFf836Be1A4f9e3559B3 has the following balances in its account number 123456:

This account is borrowing 10,000 DAI and 5,000 USDC. These borrows are collateralized by 1,000 ETH. The account will earn interest on ETH and pay interest on DAI and USDC.

Solo Markets

Solo has a Market for each ERC20 token asset it supports. Each Market specifies the Price Oracle used to determine the price for its asset, and the Interest Setter contract which determines what the interest rates are for the Market.

Markets are referenced by their numerical IDs. Currently on Mainnet Solo has the following markets, but more will be added over time:

id Asset
0 WETH
1 SAI
2 USDC
3 DAI

Solo Trading Amounts

Amounts in Solo are denominated by 3 things:

A very important thing to note is that amounts are always relative to how the balance of the Account being Operated on will change, not the amount of the Action occurring. So, for example you'd say [pseudocode] withdraw(-10), because when you Withdraw, the balance of the Account will decrease.

Interest

Interest rates in Solo are dynamic and set per Market. Each interest rate is automatically and algorithmically set based on the the ratio of (total borrow) / (total supply) of that Market. Account balances either continuously earn (if positive) or pay (if negative) interest.

Interest is earned / paid continuously (down to the second). Rates on the protocol are denominated yearly in APR.

Wei & Par

There are two types of balances amounts on Solo: Wei and Par.

Wei

Wei refers to the actual token amount of an asset held in or owed by an account. Wei amounts are constantly changing as interest accrues on the balance. For example, if Bob deposits 10 DAI to a Solo Account, its Wei balance would initially be 10. The balance would start increasing every second as Bob started earning interest on his DAI.

Likely, most times you will want to use Wei balances.

Par

Par refers to an interest adjusted amount that is static and does not change on the protocol. These are the balances that are actually stored on the protocol smart contracts. The protocol uses the current market index (see below) to transform Par to Wei values.

Index

Each Market has a global borrow index and supply index. These indexes are used to transform Par <-> Wei values using the formula:

Borrow Wei Balance = (Borrow Par Balance) * (Borrow Market Index)

and

Supply Wei Balance = (Supply Par Balance) * (Supply Market Index)

Indexes start at 1 upon the addition of the Market to the protocol. They increase based on how much interest has accrued for that asset. For example upon adding USDC both the borrow index and supply index for USDC were 1. Say over the next month 2% interest accrues to borrowers and 1% interest accrues to lenders (based on the interest rates and time that has passed). After this, the supply index will be 1.01, and the borrow index will be 1.02. These indexes will keep increasing based on interest accrued, forever.

Example

Alice deposits 10 DAI to the protocol (10 DAI in Wei). The supply index on DAI is currently 2. Using Supply Par Balance = (Supply Wei Balance) / (Supply Market Index) = 10 / 2 = 5, the protocol credits 5 Par balance to Alice's account.

Later, interest has accrued for DAI on the protocol, and now the supply index for DAI is 3. Now, Alice goes to withdraw her DAI. Her DAI Par balance is still 5 (Par does not change over time). Now the protocol calculates Supply Wei Balance = (Supply Par Balance) * (Supply Market Index) = 5 * 3 = 15, and sends Alice 15 DAI.

Actions

All state changes to accounts happen through Actions. Actions can modify the balances of 1 or more Accounts. There is no such thing as a "Borrow" action on Solo, Actions can automatically borrow funds if Account balances decrease. The following Actions are supported by Solo:

Deposit

Deposit funds into an Account. Funds are moved from the sender or an approved address to Solo, and the Account's balance is incremented.

Withdraw

Withdraw funds from an Account. Funds are sent from Solo to a specified address and the Account's balance is decremented.

Transfer

Transfer funds internally between two Solo accounts.

Buy

Buy an asset on a decentralized exchange using another asset. Uses dYdX's Exchange Wrappers to interact with different decentralized exchanges. Causes the bought asset's balance to go up, and the asset used to do the buy's balance to go down. Example: Buy 1 WETH on eth2dai using DAI

Sell

Sell an asset on a decentralized exchange for another asset. Uses dYdX's Exchange Wrappers to interact with different decentralized exchanges. Causes the sold asset's balance to go down, and the received assets balance to go up. Example: Sell 1 WETH on eth2dai for DAI

Trade

Trade assets with another account on Solo internally. No actual tokens are moved, but Account balances are updated. Uses the AutoTrader interface, which allows a smart contract to be specified which is called to determine the price of the trade.

Call

Calls a function specified by the ICallee interface through the context of an Account. Does not modify Account balances. An example of how this can be used is for setting expiration on the Expiry contract.

Liquidate

Liquidates an undercollateralized Account. Operates on two Accounts: the liquidating Account, and the undercollateralized Account. Does not transfer any tokens, but just internally updates balances of accounts. Liquidates at the price specified by Example:

Starting Account Balances:

Liquidating Account (L): +100 DAI\ Undercollateralized Account (U): -1 ETH, +140 DAI\ ETH oracle price: $125\ DAI oracle price: $1\ Liquidation spread: 5%

The liquidate action causes 1 ETH to be transferred from L -> U, and 1 ETH * (($125/ETH) / ($1/DAI)) * 1.05 = 131.25 DAI to be transferred from U -> L. After the liquidation the balances will be:

Liquidating Account (L): +231.25 DAI, -1 ETH\ Undercollateralized Account (U): +8.75 DAI

Vaporize

Pulls funds from the insurance fund to recollateralize an underwater account with only negative balances.

Operations

Every state changing action to the protocol occurs through an Operation. Operations contain a series of Actions that each operate on an Account.

Sell ETH for DAI
Deposit DAI

Multiple Actions can be strung together in an Operation to achieve more complex interactions with the protocol. For example, taking short ETH position on Solo could be achieved with an Operation containing the following Actions:

Importantly collateralization is only checked at the end of an operation, so accounts are allowed to be transiently undercollateralized in the scope of one Operation. This allows for Operations like a Sell -> Trade, where an asset is first sold, and the collateral is locked up as the second Action in the Operation.

Solo Amounts

Amounts in Solo are denominated by 3 things:

A very important thing to note is that amounts are always relative to how the balance of the Account being Operated on will change, not the amount of the Action occurring. So, for example you'd say [pseudocode] withdraw(-10), because when you Withdraw, the balance of the Account will decrease.

Solo Logs

const soloLogs = solo.logs.parseLogs(transactionReceipt);

Solo provides a helper to parse Solo-specific logs from a transaction:

Parameter Description
transactionReceipt TxResult to be parsed
options Specifications for logs to skip

Solo Types

Import Solo Types

import {
  ProxyType,
  AmountDenomination,
  AmountReference,
  ConfirmationType,
} from '@dydxprotocol/solo';

You can import types from Solo as:

Solo Web3

Solo uses Web3 1.2.X under the hood. You can access it through solo.web3

Solo BigNumber

Import BigNumber

import { BigNumber } from '@dydxprotocol/solo';

Solo uses BigNumber 8.X. You can import this from Solo as:

Solo Standard Actions

Solo exposes a number of "standard" actions for interacting with the protocol. These are a subset of what is possible with Operations, but are simpler to use.

Solo Operations

The main way to interact with Solo is through Operations. See Operations.

Initialize

To initialize an Operation:

const operation = solo.operation.initiate();

To initialize a Proxy Payable Operation:

const operation = solo.operation.initiate({ proxy: ProxyType.Payable });

Solo also provides a Payable Proxy contract that will automatically wrap and unwrap ETH <-> WETH, so that users can interact with Solo using only ETH. You can use it by:

Parameter Description
options (Optional): AccountOperationOptions for the operation.
Proxy Type Description
None No proxy type is used.
Payable Allows interacting with Solo using ETH.
Sender DEPRECATED and replaced with Signed.
Signed Sender proxy that sends Signed Operations through Sender.

Add Actions

Add Actions

import { MarketId } from '@dydxprotocol/solo';

operation.withdraw({
    primaryAccountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
    primaryAccountId: new BigNumber('123456'),
    marketId: MarketId.WETH,
    amount: {
      value: new BigNumber('-1e18'),
      reference: AmountReference.Delta,
      denomination: AmountDenomination.Actual,
    },
    to: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5'
  })
  .deposit({
    primaryAccountOwner: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
    primaryAccountId: new BigNumber('123456'),
    marketId: MarketId.DAI,
    amount: {
      value: new BigNumber('200e18'),
      reference: AmountReference.Delta,
      denomination: AmountDenomination.Actual,
    },
    from: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  });

Once an operation is initialized, Actions can be added to it. Action functions modify the operation itself, and also always return the operation.

In this example 1 ETH is being withdrawn from an account, and then 200 DAI are being deposited into it:

See AccountOperation for the full list of Actions available to add to an Operation.

Parameter Description
primaryAccountOwner Your address.
primaryAccountId If one exists, your account number.
marketId Specified token for some asset.
amount Base units of the token, so 1e18 = 1 ETH. USDC has 6 decimal places, so 1e6 = 1 USDC.





Commit

Commit

const response = await operation.commit({
  from: '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5',
  gasPrice: '1000000000',
  confirmationType: ConfirmationType.Confirmed,
});

After Actions have been added to the operation, it can be committed. This is what sends the transaction to the blockchain to execute the Operation on the protocol.

Parameter Description
from Your address.
gasPrice Price being offered to miners.
confirmationType How the operation should be handled off-chain.
Confirmation Type Description
Hash The transaction hash is returned without waiting for it to get mined.
Confirmed Promise doesn't resolve until the transaction is mined.
Both Returns the hash and also a promise that resolves when the transaction is confirmed.
Simulate For estimating gas, no transaction is sent to be mined.

Get Standard Actions

Response

{
  "standardActions": [
    {
      "uuid": "878c0f3e-ced0-478c-a9c5-76237107050b",
      "type": "ISOLATED_FULL_CLOSE",
      "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
      "number": "72726098636314491067235956043692261150608981229613064856905296785781912974936",
      "transferAmount": "139940891786496509",
      "tradeAmount": "160307343231895490",
      "price": "197.76",
      "market": "WETH-DAI",
      "asset": "WETH",
      "side": "LONG",
      "operationUuid": null,
      "transactionHash": "0xa5c242650815711b45784b57b8132e2523cd5044f0c6c53482c706713de29795",
      "positionUuid": "5f3f0dc0-d84f-4bf8-a0ce-61d4c98ae88c",
      "borrowAmount": null,
      "orderNumber": "1011061200670000",
      "confirmedAt": "2020-05-21T17:34:22.000Z",
      "feeAmount": "158511900987698260.512",
      "feeAsset": "DAI",
      "pnl": "-0.11680504725069452446144687474175947711343548096340565373461771439994077049174357",
      "payoutAmount": "139940891786496509",
      "isPendingBlock": false,
      "refundAmount": "0",
      "product": "SOLO",
      "createdAt": "2020-05-21T17:35:57.265Z",
      "updatedAt": "2020-05-21T17:35:57.280Z"
    },
    {
      "uuid": "d9ee4386-8810-4cf0-ab73-e5eaa7b6d7c8",
      "type": "ISOLATED_OPEN",
      "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
      "number": "72726098636314491067235956043692261150608981229613064856905296785781912974936",
      "transferAmount": "150200220768708569",
      "tradeAmount": "150000000000000000",
      "price": "208.62",
      "market": "WETH-DAI",
      "asset": "WETH",
      "side": "LONG",
      "operationUuid": null,
      "transactionHash": "0x2d39ca14ba40c5049d6983091fe430da8469619aae7657e872f531466fdf7d7a",
      "positionUuid": "5f3f0dc0-d84f-4bf8-a0ce-61d4c98ae88c",
      "borrowAmount": null,
      "orderNumber": "998298000710000",
      "confirmedAt": "2020-05-01T22:13:39.000Z",
      "feeAmount": "156465000000000000",
      "feeAsset": "DAI",
      "pnl": null,
      "payoutAmount": null,
      "isPendingBlock": false,
      "refundAmount": "0",
      "product": "SOLO",
      "createdAt": "2020-05-03T04:06:48.813Z",
      "updatedAt": "2020-05-03T04:06:48.834Z"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/standardActions

Description:

Example Response Body for solo:

Query: https://api.dydx.exchange/v1/standard-actions?owner=0x77A035b677D5A0900E4848Ae885103cD49af9633&limit=2&product=solo

Gets the perpetual and solo standard actions for a particular user. Standard Actions are actions performed by the user, such as depositing, withdrawing, or any other action that happens to a user's account, eg EXPIRED or LIQUIDATED.

Query Params:

Field Name Description
owner (Optional) The wallet address of the user.
number (Optional) The account number for the specified wallet address.
type (Optional) The type of standard action e.g. OPEN, CLOSE, DEPOSIT.
asset (Optional) The asset for the standard action eg: WETH, DAI
market (Optional) The market of the action e.g. PBTC-USDC.
limit (Optional) The maximum number of standard actions to retrieve.
product (Optional) The product of the standard action, e.g. PERPETUAL or SOLO.

Standard Action types:

Type Product
DEPOSIT SOLO, PERPETUAL
REPAY SOLO
WITHDRAW SOLO, PERPETUAL
BORROW SOLO
LIQUIDATE SOLO, PERPETUAL
LIQUIDATED SOLO, PERPETUAL
EXPIRE SOLO
EXPIRED SOLO
TRADE SOLO
ISOLATED_OPEN SOLO
ISOLATED_PARTIAL_CLOSE SOLO
ISOLATED_FULL_CLOSE SOLO
ACCOUNT_SETTLE PERPETUAL
OPEN PERPETUAL
CLOSE PERPETUAL
INCREASE PERPETUAL
DECREASE PERPETUAL

Response

{
  "standardActions": [
    {
      "uuid": "f2f0ac19-373f-4a80-bd34-a8d973ee0235",
      "type": "OPEN",
      "owner": "0x77a035b677d5a0900e4848ae885103cd49af9633",
      "number": null,
      "transferAmount": null,
      "tradeAmount": "990000",
      "price": "90.85",
      "market": "PBTC-USDC",
      "asset": null,
      "side": "SHORT",
      "operationUuid": null,
      "transactionHash": "0x7c6367c2058e8c121437181a3e535a1ea06271ecf47be449c0217bdd0c785ad9",
      "positionUuid": null,
      "borrowAmount": null,
      "orderNumber": "1011122300520002",
      "confirmedAt": "2020-05-21T19:49:10.000Z",
      "feeAmount": "454250",
      "feeAsset": "USDC",
      "pnl": null,
      "payoutAmount": null,
      "isPendingBlock": false,
      "refundAmount": "0",
      "product": "PERPETUAL",
      "createdAt": "2020-05-21T19:49:48.039Z",
      "updatedAt": "2020-05-21T19:49:48.039Z"
    }
  ]
}

HTTP Request

GET https://api.dydx.exchange/v1/standardActions 0x77a035b677d5a0900e4848ae885103cd49af9633

Example Response Body for perpetual:

Query: https://api.dydx.exchange/v1/standard-actions?owner=0x77A035b677D5A0900E4848Ae885103cD49af9633&limit=1&product=perpetual

Standard action markets

market
WETH-DAI
WETH-SAI
WETH-USDC
DAI-USDC
SAI-USDC
SAI-DAI
PBTC-USDC

Standard action assets

asset
WETH
DAI
USDC
SAI

Standard Action Response Object

Field Name Description
uuid The unique id for the action.
owner The wallet address of the user.
type The type of standard action e.g. DEPOSIT, ISOLATED_OPEN (for solo), OPEN, ACCOUNT_SETTLE (for perpetual)
market The market, e.g. WETH-USDC or PBTC-USDC.
side The side for the standard action e.g. LONG, SHORT.
transferAmount The amount in settlement token that is transferred.
tradeAmount The amount traded. i.e. the base token amount in a trade.
price The price in settlement token.
orderNumber Number used for ordering the standard actions.
updatedAt The ISO 8601 date and time the standard action was updated.
createdAt The ISO 8601 date and time the standard action was created.
confirmedAt The ISO 8601 date and time the standard action was confirmed.
product The product type, e.g. perpetual or solo.
transactionHash The transaction corresponding to this standard action.
pnl The PnL for the corresponding position. Currently not set in the standard action for perpetual.
feeAmount The fee amount charged.
feeAsset The asset of the feeAmount eg DAI, USDC.
asset The asset eg WETH, DAI, USDC for deposit or withdraw.
payoutAmount The amount refunded to the user when maker fee is negative.

Solo Contract Addresses

Contract addresses can be found here

Perpetual Protocol


GitHub

The dYdX Perpetual markets are supported by the dYdX Perpetual Contracts protocol, a decentralized protocol running on the Ethereum blockchain. This protocol is distinct from the Solo protocol which supports all other trading, borrowing, and lending markets on dYdX.

This article focuses on the decentralized protocol layer of dYdX Perpetuals. A more trader-focused overview can be found in the Perpetual Guide.

Perpetual Introduction

The dYdX Perpetual Contracts protocol implements a synthetic trading market on Ethereum that allows for exposure to arbitrary liquid assets using ERC-20 tokens as collateral.

Similar to existing perpetual contracts, the price of the contract is tethered to the price of the underlying asset by a dynamic interest rate, called the funding rate. An on-chain price oracle is used for liquidation purposes, and secondarily, to calculate funding payments. The order book for the market can remain off-chain, allowing for faster price movements and better liquidity.

Importantly, the contract’s underlying asset does not have to already exist as a token. For each account trading the perpetual, profits and losses are exchanged using the margin ERC-20 token. This effectively allows users to trade assets that do not actually exist on Ethereum as long as a sufficient price oracle exists. For example a BTC–USDC perpetual contract can exist as long as a BTC–USDC oracle exists. Only USDC would be used as margin deposit for all parties; tokenized BTC is not required.

Defining a Perpetual Contract

Global State

Each Perpetual Contract is uniquely defined by:

  1. The Margin Token (e.g. USDC)
  2. The Margin Requirement (e.g. 7.5%)
  3. The Price Oracle Contract
  4. The Funding Oracle Contract

The choice of price oracle will determine the underlying asset of the contract (e.g. BTC).

In addition, the Perpetual Contract keeps track of:

  1. The Global Index
  2. The Unix time of the most recent Global Index update
  3. User accounts

The Global Index is used in funding payment calculations and is explained in greater detail later.

Account State

For a given Perpetual Contract, each Ethereum address has a single account. Each account’s state consists of:

  1. The Margin Balance
  2. The Position Balance
  3. The Cached Index

The Margin Balance and Position Balance are each signed integer values. The Margin Balance is denominated in Margin Token (e.g. USDC). The Position Balance is denominated in the underlying asset (e.g. BTC), that is traded against the Margin Token. The Margin Balance may change due to funding payments, deposits, and withdrawals. Both the Margin Balance and the Position Balance may change due to trades.

The Cached Index of an account is equal to the Global Index at the last time that the account was interacted with. The Cached Index is used when settling funding payments for an account.

Margin Requirement

The margin requirement is the minimum margin percentage that an account must maintain to avoid liquidation. The margin percentage is defined as the value of any positive balances divided by the value of any negative balances, minus 100%. For example, if 1 BTC is worth 1000 USDC according to the price oracle, then an account with a Position Balance of -1 BTC and a Margin Balance of +1100 USDC would have a margin percentage of 10%.

After each interaction with the Perpetual (except deposits), the smart contract checks the margin percentage of each affected account. If the margin requirement is not met for an account, then the account’s margin percentage must have increased and its position balance must have decreased in absolute size and not changed signs during the interaction. This condition must be met for each affected account, otherwise the transaction is reverted.

Funding Payments

The Perpetual aims to trade as close to the price of the underlying asset as possible. This helps traders and market-makers understand and predict the price, maintain expectations for how it will perform, and hedge their positions appropriately.

Like other perpetual contracts, we use a “funding rate” to incentivize traders to take the “unpopular” market position and help tether the price of the Perpetual. The funding rate operates similarly to a dynamic interest rate on traders’ positions, paid by longs and received by shorts, or vice-versa, depending on market conditions.

I = I + T × R × P

Funding payments are made continuously and are effectuated via updates to the Global Index. The Global Index is a signed number that starts at zero. It is updated at the start of any transaction to the smart contract according to the formula:

Where I is the Global Index, T is the time since the last index update, R is the current funding rate, and P is the current price of the underlying relative to the margin token, according to the price oracle.

The funding rate can be positive (longs pay shorts) or negative (shorts pay longs), thus the Global Index can both increase and decrease. The funding rate is determined by the funding oracle. This contract is fed updates by an Admin address according to an off-chain algorithm that aims to keep the market value of the Perpetual as close as possible to the underlying asset. The funding rate will be positive if the Perpetual is trading higher than the price of the underlying, and negative if the Perpetual is trading lower. Limits on the maximum value and the rate of change of the funding rate are implemented on the funding oracle contract itself.

M = M − (I1− I0) × P

Each account’s funding payments are derived from changes in the Global Index, scaled by the size of the account’s Position Balance (irrespective of leverage). Any time the Global Index is updated, each account involved in the transaction will settle its funding payments since its last update. This is done by updating the Margin Balance of the account according to the formula:

Where M is the Margin Balance of the account, I1 is the newly updated Global Index, I0 is the account’s Cached Index, and P is the Position Balance of the account. Note that all of these variables are signed numbers which can be positive or negative. After this settlement occurs, the account’s Cached Index is set to the new Global Index. These calculations result in continuous, non-compounding, peer-to-peer interest payments between traders.

Interacting with the Protocol

Protocol overview
Simplified overview of the protocol structure.

Overview

Users interact with the smart contract by calling one of three functions:

  1. Deposit
  2. Withdraw
  3. Trade

The structure of each function is as follows:

  1. The Global Index is updated.
  2. Funding payments of affected accounts are settled and Cached Indexes are updated.
  3. The action (Deposit/Withdraw/Trade) is processed.
  4. The margin percentage of each affected account is checked.

We describe each function in more detail below.

Deposit

This function increases an account’s Margin Balance by transferring in some amount of Margin Token from the caller’s ERC-20 balance.

Withdraw

This function decreases an account’s Margin Balance by transferring out some amount of Margin Token. The function takes as an argument a destination address to receive the tokens. Withdrawals cannot be completed if the account’s margin percentage is below the margin requirement.

Trade

A trade happens between two accounts, affecting the Margin and Position balances of those two accounts. The term “trade” is used broadly here to refer to any operation involving a transfer of balances, and the exact types of trades allowed will depend on the Trader contracts in use (described below).

Since a trade is the only way to change the Position Balance of an account, and is always executed as a transfer between two parties, the total net Position Balances across all accounts in a given Perpetual market will, at any time, sum to zero.

Trades are sent to external “Trader” smart contracts for processing and approval. These Trader contracts must be approved by the Perpetual Admin before they can be used. Arguments to the trade function include the address of the Trader contract to use, maker and taker addresses, and additional data depending on the Trader contract. If the trade is approved, the Trader will return an amount of Margin and Position to transfer between the two accounts. The transfer is then executed by the Perpetual contract.

Multiple trades may be processed at once as an atomic batch. The margin percentages of accounts are checked at the end of a batch of trades.

Trader Contracts

Below, we outline the three Trader Contracts that will be available at the launch of the protocol. Our architecture aims to keep trader logic outside of the core Perpetual smart contract, allowing us to cleanly make changes and upgrades to trade functionality by approving new Trader contracts.

Orders

The Orders contract is a Trader that allows a taker to execute a trade with a maker, given a signed order from the maker. This allows traders to place orders by signing an order object off-chain. An order matching service (e.g. dYdX) can then match and execute trades on-chain by acting as the “taker” for each order.

Makers can cancel orders, either via an off-chain signature (which must then be relayed on chain), or by calling the cancel function directly on the Orders smart contract.

Note that since no tokens are actually transferred during trades (only Margin and Position Balances), liquidity for trades is exclusive to the Perpetual and cannot be sourced from other DEXes.

Liquidation

If an account’s margin percentage falls below the Perpetual’s margin requirement, then the account may be liquidated. This process allows the liquidator to assume the margin and position balances (wholly or in-part) of the liquidated account. This transfer of balances occurs at the exact ratio of balances in the liquidated account, therefore, the margin percentage of the liquidated account does not change during liquidation.

Any account may choose to act as a liquidator. If there exists enough liquidity in the market, this action is beneficial to the liquidator since the liquidated account has positive market-value.

Deleveraging

If the oracle price changes rapidly, the value of some accounts may drop below zero before there is a chance to liquidate them at a profit. In such cases, deleveraging is used to maintain the solvency of the system.

An account with negative net value (i.e. a negative margin percentage) is said to be underwater, and may be targeted for deleveraging. The process is similar to liquidation, in that the balances of the target account are taken on by another account, in this case called the offsetting account. Unlike liquidation, the deleveraging operation allows the caller to specify any account as the offsetting account, as long as it has a position opposite the target (short vs. long) and of greater or equal size.

The Perpetual Admin is responsible for triggering deleveraging whenever an account is underwater. The Admin will use an “insurance fund” as the offsetting account, if available. Otherwise, the Admin will determine the offsetting account via an off-chain algorithm that prioritizes accounts with a high amount of profit and leverage.

If, due to unforeseen circumstances, the Perpetual Admin is offline for a period of time, then any third-party may trigger deleveraging to maintain the solvency of the system. Third-parties are required to mark underwater accounts and wait a time lock in advance of deleveraging, ensuring that the Admin has priority in executing deleveraging.

Final Settlement

Final settlement is a one-way operation which locks in the current oracle price and Global Index, and restricts all operations except for a special withdrawal function allowing users to exit their positions at the locked price.

Final settlement may be triggered by the Perpetual Admin at the end-of-life of a given Perpetual smart contract. It may also be triggered in the event that a critical vulnerability is discovered that is deemed to pose a significant risk to user funds.

Perpetual Types

Import Perpetual Types

import {
  Order,
  SignedOrder,
} from '@dydxprotocol/perpetual';

You can import types from Perpetual as:

Perpetual Web3

Perpetual uses Web3 1.2.X under the hood. You can access it through perpetual.web3

Perpetual BigNumber

Import BigNumber

import { BigNumber } from '@dydxprotocol/perpetual';

Perpetual uses BigNumber 8.X. You can import this from Perpetual as:

Perpetual Contract Addresses

Contract addresses can be found here.

Perpetual Contract Guide

The dYdX Perpetual is a non-custodial, decentralized margin product that gives traders synthetic exposure to assets that cannot normally be traded on the Ethereum blockchain. Like other margin trading products offered by dYdX, the market is primarily governed by Ethereum smart contracts, while hosting of the order book and matching of orders is handled off-chain by dYdX.

This article focuses on the technical information needed to trade the perpetual and compare it to other perpetual products. More details on the dYdX Perpetual Contracts Protocol and decentralization can be found here.

BTC–USD Perpetual Contract Specification

ETH–USD Perpetual Contract Specification

Margin

The “riskiness” of an account is measured via the margin percentage, defined as follows:

Margin Percentage = Collateralization Ratio - 1

Where the collateralization ratio of an account is defined as:

Collateralization Ratio = Value of Positive Balances / Absolute Value of Negative Balances

Each trader’s account consists of two balances: a margin balance (denominated in the margin asset, e.g. USDC) and a position balance (denominated in the underlying asset, e.g. BTC). Either balance may be positive or negative. Any trade executed by the trader will increase one balance and decrease the other. All withdrawals and deposits are made in the margin asset and affect only the margin balance. Positions (e.g. BTC) cannot be withdrawn directly.

Note that there is no isolated margin mode, as each account has only a single position balance. Also, an account cannot simultaneously hold positive and negative positions.

The relative value between currencies is determined by the on-chain index price. For example, in the BTC/USDC perpetual, margin percentage is a function of the BTC/USD index and the account’s BTC and USDC balances.

An account whose margin percentage falls below the maintenance margin requirement may be liquidated. Accounts are restricted from making trades or withdrawals that would bring their account below the initial margin requirement, which is set higher than the maintenance margin requirement. Movements in the index price may, however, cause an account to drop below the initial margin requirement and, eventually, the maintenance margin requirement.

Accounts which fall below the initial margin requirement are restricted from making withdrawals and certain trades until the account’s margin percentage is brought back to the initial margin requirement. These “risky” accounts are barred from making trades that do any of the following:

  1. Decrease the account’s margin percentage.
  2. Increase the absolute size of the account position.
  3. Change the sign of the account position (long to short, or vice versa).

These restrictions apply whether the “risky” account is a taker or a maker in the trade.

Margin Example

The following illustrates a hypothetical sequence of actions taken by a trader, and their margin percentage after each step. The on-chain index price at each point is given as well. We assume an initial margin requirement of 10% and a maintenance margin requirement of 7.5%.

Action Balances On-Chain Index Margin Percentage
1. Deposit 1000 USDC. +1000 USDC, 0 BTC 2000 USD / BTC Infinity
2. Buy 1 BTC for 2000 USDC. -1000 USDC, +1 BTC 2000 USD / BTC (1 BTC * 2000 USDC / BTC) / (1000 USDC) - 1 = 100%
3. Sell 2 BTC for 4000 USDC. +3000 USDC, -1 BTC 2000 USD / BTC (3000 USDC) / (1 BTC * 2000 USDC / BTC) - 1 = 50%
4. Withdraw 800 USDC. +2200 USDC, -1 BTC 2000 USD / BTC (2200 USDC) / (1 BTC * 2000 USDC / BTC) - 1 = 10%
5. (Movement in index price.) +2200 USDC, -1 BTC 2040 USD / BTC (2200 USDC) / (1 BTC * 2040 USDC / BTC) - 1 = 7.84%

In the final step, the on-chain index price increases while the trader holds a short position. This causes the margin percentage of the account to dip dangerously close to the maintenance margin requirement.

The account is not yet liquidatable, but may become so if the index price increases further. Since the margin percentage is below 10%, the account will be restricted from making withdrawals and certain trades, as described above, until the account is brought back above the initial margin requirement.

Liquidations

An account whose margin percentage falls below the maintenance margin requirement may be liquidated. During a liquidation, the liquidator is allowed to take on the entire account balance of the liquidated account, leaving it with zero margin and position. Partial liquidation is also permitted, in which case the liquidator will take on proportional amounts of the account’s margin and position (one of which will be negative).

Liquidations occur on-chain, and any account may act as a liquidator, provided that their ending balance after the liquidation meets the maintenance margin requirement. We will open-source a new liquidator bot for the perpetual which anybody may run to participate in liquidations.

Liquidation incentives

Since a liquidator may take on the liquidated account’s full balance, the incentive to liquidate is higher the closer the target account is to the liquidation threshold. Other factors impacting the liquidation reward are:

Liquidation Examples

Assume an initial margin requirement of 10% and a maintenance margin requirement of 7.5%.

Example 1

Trader A deposits 1000 USDC, then opens a short position of 1 BTC at a price of 2000 USDC. Their account balance is +3000 USDC, -1 BTC. The on-chain index price is 2000 USDC/BTC making their margin percentage 50%.

Over time, the price of BTC increases, and the on-chain index price hits 2791 USDC, at which point Trader A’s position is below the maintenance margin requirement and becomes liquidatable. Trader B, who has a balance of +100 USDC, 0 BTC, liquidates A’s position successfully, leaving A with zero balance, and bringing B’s balance to +3100 USDC, -1 BTC. Trader B then closes the short position on the market at a price of 2800 USDC, bringing their final balance to +300 USDC, 0 BTC.

At the time of liquidation, using the index price of 2791 USDC, Trader A’s account had a nominal value of 209 USDC, therefore we may say that A’s liquidation penalty was 209 USDC.

Trader B’s profit, after closing the short position, and ignoring any trade fees, is 200 USDC.

Example 2 - Partial Liquidation

Suppose Trader A has an account balance of +3000 USDC, -1 BTC, but due to a rapidly increasing price in the underlying spot market, the on-chain index is now 2900 USDC, giving A a margin percentage of only 3.45%.

Trader B, who has a balance of +100 USDC, 0 BTC, wants to liquidate Trader A’s account. However, at the current index price, a full liquidation is not possible since it would leave B with a margin percentage of 6.90%. Trader B chooses to execute a partial liquidation, taking on 60% of Trader A’s balances. This leaves A with 1200 USDC, -0.4 BTC, and B with 1900 USDC, -0.6 BTC.

At an index price of 2900 USDC, Trader B’s account has a nominal value of 160 USDC, giving them a hypothetical profit of 60 USDC. Trader B’s position is currently fairly risky however, with a margin percentage of 9.20%.

Trader A’s remaining position still has a margin percentage of 3.45%, and their remaining balance may be liquidated if they don’t make a deposit or trade out of their position.

Funding

Perpetual contracts have no expiry date and therefore no final settlement or delivery. Funding payments are therefore used to incentivize the price of the perpetual to trade at the price of the underlying.

Funding is calculated like an interest rate, and is determined by a funding rate which is calculated algorithmically based on the price of the underlying and market prices for the perpetual. When the rate is positive, traders who are long will make payments to traders who are short. When the rate is negative, this is reversed and shorts will pay longs. Traders make or receive payments in proportion to the size of their market position. These payments are exchanged solely between traders, and are neither paid nor received by the exchange.

Funding Interval

Funding payments are exchanged continuously every second. The funding rate is updated every hour, but is represented as an 8-hour rate, indicating the amount of funding accounts may expect to pay/receive over an 8-hour period.

Funding Payment Calculation

The funding amount paid or received by an account over some period of time of length T is calculated according to the formula:

F = (−1) * R * (T / 8 hours) * B * X

Where: * F is the change in account balance over the given period * R is the funding rate as an 8-hour rate * B is the position balance of the account (positive or negative) * X is the on-chain index price

Note that funding payments do not compound.

Funding Rate Calculation

Rates are represented as 8-hour rates unless stated otherwise.

The funding rate has two components, the interest rate component and the premium component. The interest rate component aims to account for the interest rate differential between the base and quote currencies. We currently use the fixed rate:

Interest Rate Component = 0.01%

The premium component takes into account market activity for the perpetual. It is calculated at the start of every minute based on the current order book and off-chain index price according to the formula:

Premium = (Max(0, Impact Bid Price - Index Price) - Max(0, Index Price - Impact Ask Price)) / Index Price

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

Where the impact bid and impact ask prices are defined as:

And the impact notional amount is defined as:

Impact Notional Value = 500 USDC / Initial Margin Requirement

For example, at a 10% initial margin requirement, the impact notional value is 5000 USDC.

At the end of each hour, the 1-hour premium is calculated as the simple average (i.e. TWAP) of the 60 premiums calculated over the course of the last hour. The funding rate is then calculated as:

Funding Rate = One-Hour Premium + Interest Rate Component

Index Price for Funding

Funding payments occur on-chain, so the calculation of funding payments from the funding rate makes use of an on-chain index price given by a MakerDAO v2 oracle. The funding rate itself is calculated off-chain, and makes use of an off-chain index which is updated more frequently than the on-chain index.

The off-chain index prices are calculated as follows:

Index Exchanges Weighting method
BTC-USD Bitstamp, Bittrex, Coinbase Pro, Gemini, Kraken median
ETH-USD Binance, Bitstamp, Coinbase Pro, Gemini, Kraken median

Funding Rate Updates

After the funding rate is calculated by dYdX, it is immediately sent to the funding rate smart contract. The smart contract will apply bounding as described below, and the rate will be rounded, toward zero, to the nearest value representable on the smart contract. Once the Ethereum transaction is mined, the new funding rate takes effect and is used to update account balances every second.

Funding Rate Bounding

The minimum funding rate is -0.75% and the maximum funding rate is 0.75%. For decentralization purposes, there is a limit to how quickly the admin can change the funding rate, but this does not take effect during normal operation.

Funding Examples

Example 1

At 01:30 UTC, trader A opens a long position of 100 BTC at a price of 1990 USDC. The on-chain index price is 2000 USDC. Based on the premium from 00:00–01:00 UTC, the current funding rate is -0.06%. Trader A begins earning funding each second. After one second, funding earned is given by the formula:

F = (−1) * R * (T / 8 hours) * B * X

Where, in this case: * R = -0.06% * T = 1 second * B = 100 BTC * X = 2000 USDC / BTC

Resulting in a change in balance of F = +0.00416667 USDC.

F = (−1) * -0.0006 * (1 minute / (8 * 60 minutes)) * 100 BTC * 2000 USDC / BTC = +0.25 USDC

Suppose the on-chain index price does not change over the next minute. We can use the same formula to calculate the funding accumulated, and find that the trader has earned:

F = (−1) * -0.0006 * (8 hours / 8 hours) * 100 BTC * 2150 USDC / BTC = +129 USDC.

A holds this long position for 8 hours until 09:30 UTC and the funding rate remains constant at -0.06%. Suppose that from 01:30–09:30 UTC the average on-chain index price is 2150 USDC. Then funding accumulated over this period is given by:

Note that over an 8-hour period, with a constant funding rate, the funding accumulated is simply equal to the funding rate times the value of the position at the average index price.

Example 2

FA = (−1) * 0.0015 * (1 minute / (8 * 60 minutes)) * 100 BTC * 2000 USDC / BTC = -0.625 USDC FB = (−1) * 0.0015 * (1 minute / (8 * 60 minutes)) * -50 BTC * 2000 USDC / BTC = +0.3125 USDC

At 01:59 UTC, trader A opens a long position of 100 BTC and trader B opens a short position of 50 BTC, both at a price of 1990 USDC. Based on the premium from 00:00–01:00 UTC, the current funding rate is 0.15%. Both traders begin accruing funding, with A paying funding and B receiving funding. For one minute, from 01:59–02:00 UTC, the funding rate remains at 0.15% and the on-chain index price averages 2000 USDC. Over this minute, balances are affected by funding as follows:

At 2:00 UTC the funding rate increases to 0.30%. Suppose over the next minute, from 2:00–2:01 UTC, the on-chain index price averages 2050 USDC. Over this minute, balances are affected by funding as follows:

FA = (−1) * 0.003 * (1 minute / (8 * 60 minutes)) * 100 BTC * 2050 USDC / BTC = -1.28125 USDC FB = (−1) * 0.003 * (1 minute / (8 * 60 minutes)) * -50 BTC * 2050 USDC / BTC = +0.640625 USDC

Contract Loss Mechanisms

Offering the perpetual market with a high amount of leverage inevitably entails increased risk. In particular, during times of high volatility in the underlying spot markets, it is possible that the value of some accounts will drop below zero before they can be liquidated at a profit. Should these “underwater” accounts occur, they must be handled promptly in order to ensure the solvency of the system as a whole.

Insurance Fund

At the time of launching the perpetual market, dYdX will seed an insurance fund that will be the initial backstop for any underwater accounts. This fund will be used before any deleveraging occurs. * The initial seed amount for the fund will be 250,000 USD. * The insurance fund account and its activities will be publicly auditable and verifiable. * The insurance fund will not be decentralized at launch, and the dYdX team will be directly responsible for deposits to and withdrawals from the fund. In the future, we may decentralize some aspects of the fund; however, initially, our priority is to ensure that underwater accounts are dealt with in a timely manner.

Deleveraging

Deleveraging is a feature made available by the perpetual smart contract, which is used as a last resort to close underwater positions if the insurance fund is depleted. Deleveraging works similarly to “auto-deleveraging” in other perpetual markets, and is a mechanism which requires profitable traders to contribute part of their profits to offset underwater accounts. * Deleveraging will only be used if the insurance fund is depleted. * Deleveraging is performed by automatically reducing the positions of some traders—prioritizing accounts with a combination of high profit and high leverage—and using their profits to offset underwater accounts. * Deleveraging is chosen over a socialized loss mechanism to reduce the uncertainty faced by traders trading at lower risk levels. * Any deleveraging that occurs will be public and auditable on-chain.

Deleveraging Example

Assume an initial margin requirement of 10% and a maintenance margin requirement of 7.5%.

Trader A deposits 1000 USDC, then opens a long position of 1 BTC at a price of 2000 USDC. Their account balance is -1000 USDC, +1 BTC. During a period of intense and prolonged volatility, the on-chain index price reaches 1080 USDC. Trader A is in a risky position, but not yet liquidatable. The price then rapidly drops further, and before A can be liquidated, the on-chain index price reaches 900 USDC, making the nominal value of A’s account -100 USDC.

The insurance fund is already depleted due to recent price swings, so deleveraging kicks in. Trader B, whose current balance is 10000 USDC, -9 BTC, is selected as the counterparty, on the basis of B’s profit and leverage, and the fact that B’s short position can offset A’s long position.

Trader B receives A’s entire balance, leaving A with zero balance, and bringing B’s total balance to 9000 USDC, -8 BTC. Trader B’s nominal loss due to deleveraging is 100 USDC, at an index price of 900 USDC. Trader B’s margin percentage increased (and leverage decreased) as a result of deleveraging, from 23.46% to 25%.

Security

Independent Audits

Solo

The Solo smart contracts were audited independently by both Zeppelin Solutions and Bramah Systems.

Zeppelin Solutions Audit Report

Bramah Systems Audit Report

Perpetual

The Perpetual smart contracts were audited independently by Zeppelin Solutions at commit c5e2b0e, excluding P1Orders.sol.

Zeppelin Solutions Audit Report

Code Coverage

All production smart contracts are tested and have 100% line and branch coverage.

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:

Scope

Any vulnerability not previously disclosed by us or our independent auditors in their reports.

Guidelines

We require that all reporters:

If you follow these guidelines when reporting an issue to us, we commit to: