NAV Navbar
javascript
  • Introduction
  • Public Rest API
  • Private Rest API
  • Websocket
  • Examples
  • Introduction

    Welcome to the Hydro API.

    Our API is similar to major exchanges such as gdax and binance, but as our exchange is decentralized there are a few key differences:

    Endpoints

    Rest API Endpoint

    https://api.ddex.io/v2

    Websocket Endpoint

    wss://ws.ddex.io

    SDK

    We've provided a javascript SDK to get you started. You can view the Github project, or simply install it via npm:

    npm i @hydro-protocol/sdk

    Public Rest API

    Introduction

    These are API calls that do not require any user authentication to perform. They will generally give you information about the public state of the market.

    List Markets

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "markets": [
          {
            "id": "ABT-ETH",
            "quoteToken": "ABT",
            "quoteTokenDecimals": 18,
            "quoteTokenAddress": "0xb98d4c97425d9908e66e53a6fdf673acca0be986",
            "baseToken": "ETH",
            "baseTokenDecimals": 18,
            "baseTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
            "minOrderSize": "100.000000000000000000",
            "maxOrderSize": "4931.539990904282435005",
            "pricePrecision": 5,
            "priceDecimals": 8,
            "amountDecimals": 8
          },
          ...
        ]
      }
    }
    

    Returns all active markets.

    HTTP Request

    GET https://api.ddex.io/v2/markets

    Details

    The values returned for minOrderSize and maxOrderSize represent the upper and lower bounds for the amount of quoteToken you can specify in a single order.

    Both quoteToken and baseToken give you the contract address of the token, as well as the number of decimals used by the token.

    Price is limited to a precision value in pricePrecision which is the maximum amount of digits in a number. For example, if the precision is 4, a price of "0.000124" is valid, but a price of "1.9029" is not.

    Both price and amount have a minimum unit, as defined in priceDecimals and amountDecimals. Any value specified must not have an increment smaller than the minimum defined unit. For example if priceDecimals is 2, a price of "0.01" is valid, but a price of "1.001" is not.

    Get a Market

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "market": {
          "id": "ZRX-ETH",
          "quoteToken": "ZRX",
          "quoteTokenDecimals": 18,
          "quoteTokenAddress": "0xe41d2489571d322189246dafa5ebde1f4699f498",
          "baseToken": "ETH",
          "baseTokenDecimals": 18,
          "baseTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
          "minOrderSize": "0.000100000000000000",
          "maxOrderSize": "82908.204340748047172374",
          "pricePrecision": 5,
          "priceDecimals": 8,
          "amountDecimals": 8
        }
      }
    }
    

    Returns a single market identified by marketId.

    HTTP Request

    GET https://api.ddex.io/v2/markets/:marketId

    URL Parameters

    Parameter Description
    marketId Query for information on a specific market. Specified in the form of a trading pair of tokens, e.g. ZRX-ETH.

    Details

    Please see List Markets for a description of the returned metadata.

    List Tickers

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "tickers": [
          {
            "marketId": "ELEC-ETH",
            "price": "0.000144",
            "volume": "27849.39934497",
            "bid": "0.000144",
            "ask": "0.000145",
            "low": "0.000144",
            "high": "0.0001621",
            "updatedAt": 1363828259897
          },
          ...
        ]
      }
    }
    
    

    Returns ticker data for all active markets.

    HTTP Request

    GET https://api.ddex.io/v2/markets/tickers

    Details

    Each set of ticker data contains the market it represents in marketId, as well as the price of the last trade made. We also give you status of the market at the time of the last trade, with ask being the highest offer for tokens, and bid being the lowest purchase price available at the time. Data about the last 24 hours of trading is available in low, high, and volume.

    Get a Ticker

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "ticker": {
          "marketId": "ELEC-ETH",
          "price": "0.000144",
          "volume": "27849.39934497",
          "bid": "0.000144",
          "ask": "0.000143",
          "low": "0.000144",
          "high": "0.0001621",
          "updatedAt": 1363828259897
        }
      }
    }
    

    Return ticker data for a single market identified by marketId

    HTTP Request

    GET https://api.ddex.io/v2/markets/:marketId/ticker

    URL Parameters

    Parameter Description
    marketId Query for ticker data on a specific market. Specified in the form of a trading pair of tokens, e.g. ELEC-ETH.

    Details

    Please see List Tickers for a description of the returned metadata.

    Get Orderbook

    Aggregated Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "orderBook": {
          "marketId": "BKX-ETH",
          "bids": [
            {
              "price": "0.0010229",
              "amount": "210"
            },
            ...
          ],
          "asks": [
            {
              "price": "0.0011393",
              "amount": "200"
            },
            ...
          ]
        }
      }
    }
    

    Non-aggregated Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "orderBook": {
          "marketId": "BKX-ETH",
          "bids": [
            {
              "price": "0.0010229",
              "amount": "210",
              "orderId": "0x7e1e4ea61dc081da6a979848c6c1b12fa167ac7f006750e804a540a3cccbbf8d"
            },
            ...
          ],
          "asks": [
            {
              "price": "0.0011393",
              "amount": "200",
              "orderId": "0x762d6ce2a8b30151c7dc7d29f0068e2dda2d1dd852f637d9e302e4fa408a0611"
            },
            ...
          ]
        }
      }
    }
    

    Return order data for a single market specified by marketId

    HTTP Request

    GET https://api.ddex.io/v2/markets/:marketId/orderbook

    URL Parameters

    Parameter Description
    marketId Query for orderbook data on a specific market. Specified in the form of a trading pair of tokens, e.g. BKX-ETH.

    Query Parameters

    Parameter Description
    level (Optional) Controls the level of detail in the returned orderbook data. Defaults to level 1.

    Levels

    Level Description
    1 The best bid and ask prices
    2 The top 50 bids and asks, with orders at the same price aggregated together
    3 Returns the full orderbook with no aggregation

    Details

    This returns an array of bids and asks for the orderbook in the specified market. Each bid/ask contains the price and the amount of token available/requested at that price. If you set the level to 3, you will get the full orderbook with no aggregation, and as such we also include the orderId with each bid/ask.

    List Trades

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "totalPages": 10,
        "currentPage": 1,
        "trades": [
          {
            "marketId": "ZRX-ETH",
            "status": "successful",
            "amount": "2099.39882679",
            "price": "0.00138045",
            "executedAt": 1520914296000,
            "createdAt": 1520914269749
          },
          ...
        ]
      }
    }
    

    Return paginated data for all trades in a single market identified by marketId. The trades are sorted by creation time in descending order.

    HTTP Request

    GET https://api.ddex.io/v2/markets/:marketId/trades

    URL Parameters

    Parameter Description
    marketId Query for trade data on a specific market. Specified in the form of a trading pair of tokens, e.g. ZRX-ETH.

    Query Parameters

    Parameter Description
    page (Optional) Used for pagination. Defaults to 1.
    perPage (Optional) Used for pagination. Value must be between 1-100. Defaults to 100.

    Details

    Returns all trade data for the specified market. Results will be paginated with a default page size of 20 results.

    Each set of trade data includes the price and amount of the order, as well as the status. We also include the time at which the trade was created due to matching orders in the book (createdAt) and the time the trade was completed on the blockchain (executedAt).

    List Candles

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "candles": [
          {
            "time": 1518454800000,
            "volume": "25140",
            "open": "0.0012258",
            "close": "0.00118",
            "high": "0.0012258",
            "low": "0.0011755"
          },
          {
            "time": 1518458400000,
            "volume": "17322",
            "open": "0.00118",
            "close": "0.0011782",
            "high": "0.00119",
            "low": "0.0011769"
          },
          ...
        ]
      }
    }
    

    Returns "candles" for a specific market specified by marketId. These candles are useful for creating a chart of the trading history of a market.

    HTTP Request

    GET https://api.ddex.io/v2/markets/:marketId/candles

    URL Parameters

    Parameter Description
    marketId Query for candles on a specific market. Specified in the form of a trading pair of tokens, e.g. ZRX-ETH.

    Query Parameters

    Parameter Description
    from The beginning of the time range in seconds for which you want candles. Specified as a Unix Timestamp, e.g. 1518451200
    to The end of the time range in seconds for which you want candles. Specified as a Unix Timestamp, e.g. 1520870400
    granularity The width of each candle in seconds, e.g. 3600 for width of 1 hour.

    Details

    Returns a list of candles, each representing a span of time on the graph defined by the granularity passed in. The candle data includes the open and close price, the high and low price, and the amount of volume traded in the span of time represented by the candle.

    Calculate Fees

    Request

    {
      "amount": "5500000",
      "price": "0.001"
    }
    

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "totalFeeAmount": "5.5",
        "feeRate": "0.001"
      }
    }
    

    Calculates the approximate fee that will be charged for an order.

    HTTP Request

    GET https://api.ddex.io/v2/fees

    Query Parameters

    Parameter Description
    price The price of the order. e.g. 0.001
    amount The amount of token in the order. e.g. 5500000

    Details

    The server will calculate a fee based on current conditions and return the totalFeeAmount as well as the feeRate that was used to calculate that amount.

    Private Rest API

    Introduction

    API calls that return data about a specific account, or let you post data to the system. These calls will require you to authenticate in order to access them. Please see the Authentication) section below for more details.

    Authentication

    Example (web3)

    const address = web3.eth.coinbase
    const message = "[email protected]" + Date.now()
    web3.personal.sign(web3.toHex(message), address, (err, sign) => {
      console.log(address + '#' + message + '#' + sign)
    })
    

    Example (ethereumjs-util)

    import { hashPersonalMessage, ecsign, toRpcSig, toBuffer, privateToAddress } from "ethereumjs-util"
    
    const message = "[email protected]" + Date.now()
    const privateKey = '0xe4abcbf75d38cf61c4fde0ade1148f90376616f5233b7c1fef2a78c5992a9a50'
    const address = '0x' + privateToAddress(privateKey).toString("hex")
    
    const sha = hashPersonalMessage(toBuffer(message))
    const ecdsaSignature = ecsign(sha, toBuffer(privateKey))
    const signature = toRpcSig(ecdsaSignature.v, ecdsaSignature.r, ecdsaSignature.s)
    console.log(address + '#' + message + '#' + signature)
    

    Hydro uses an Authentication Header to control access to the API.

    Header Format

    Hydro-Authentication: {Address}#{Message}#{Signature}

    Header Components

    Component Description
    Address The ethereum address used for trading, e.g. 0xed6d484f5c289ec8c6b6f934ef6419230169f534
    Message A static message plus the current UTC timestamp in milliseconds, e.g. [email protected]
    Signature The result of signing the Message component with the private key of the Address

    Details

    In order to authenticate a request, you must construct a token validating your ownership of the trading address. The token is time sensitive to prevent a leaked token from giving irrevocable access to the Hydro API for a particular trading address. As part of the Message component, you will include a current timestamp in UTC. The token will be valid for up to 5 minutes. In general we suggest creating a new token for each request.

    A full example header using the example Address and Message values above:

    Hydro-Authentication: 0xed6d484f5c289ec8c6b6f934ef6419230169f534#[email protected]#0x2b3eacf8844008fe3822a9d3ba97a9d6df1a7aeb95636c10024e34334a0e008e7129b86a87c1dfcad9a25743fb6598e555c086cfede2e245e0d8043ac7e17f8e00

    Wrapping Ether

    Example Wrap (web3)

    import BigNumber from "bignumber.js"
    
    const wethAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    const value = 1 * (10**18) // 1 ETH in Wei
    web3.eth.contract(
      [
        {
          "constant": false,
          "inputs": [],
          "name": "deposit",
          "outputs": [],
          "payable": true,
          "stateMutability": "payable",
          "type": "function"
        }
      ]
    ).at(wethAddress).deposit(
      {
        value: value,
        // You can optionally pass in the gas price and gas limit you would like to use
        gasLimit: 80000,
        gasPrice: new BigNumber(10**10),
      },
      (err, res) => {
        console.log(res) // Transaction id
      }
    )
    

    Example Unwrap (web3)

    import BigNumber from "bignumber.js"
    
    const wethAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    const value = 1 * (10**18) // 1 ETH in Wei
    web3.eth.contract(
      [
        {
          "constant": false,
          "inputs": [
            {
              "name": "wad",
              "type": "uint256"
            }
          ],
          "name": "withdraw",
          "outputs": [],
          "payable": false,
          "stateMutability": "nonpayable",
          "type": "function"
        }
      ]
    ).at(wethAddress).withdraw(
      value,
      {
        // You can optionally pass in the gas price and gas limit you would like to use
        gasLimit: 80000,
        gasPrice: new BigNumber(10**10),
      },
      (err, res) => {
        console.log(res) // Transaction id
      },
    )
    

    Exchanges built using the Hydro Protocol allow users to trade ERC20 tokens directly from their digital wallets. Unfortunately, Ether itself does not conform to the ERC20 standards (yet!). Because of this, ETH must first be converted to what is known as "wrapped ether" (WETH), which does conform to the ERC20 Standard. ETH and WETH are always exchanged at a 1:1 ratio. You can wrap/unwrap ETH yourself with web3 as shown in the example, or visit our Support Article for information on how to wrap through our DDEX exchange.

    Enabling Token Trading

    Example Enable WETH (web3)

    import { ZeroEx } from '0x.js'
    import BigNumber from "bignumber.js"
    
    const wethAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    const makerAddress = "0xed6d484f5c289ec8c6b6f934ef6419230169f534"
    
    const zeroEx = new ZeroEx(web3.currentProvider)
    const enableTx = await zeroEx.token.setUnlimitedProxyAllowanceAsync(
      wethAddress,
      makerAddress,
      {
        // You can optionally pass in the gas price and gas limit you would like to use
        gasLimit: 80000,
        gasPrice: new BigNumber(10**10),
      }
    )
    console.log(enableTx) // Transaction id
    

    Example Disable WETH (web3)

    import { ZeroEx } from '0x.js'
    import BigNumber from "bignumber.js"
    
    const wethAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    const makerAddress = "0xed6d484f5c289ec8c6b6f934ef6419230169f534"
    
    const zeroEx = new ZeroEx(web3.currentProvider)
    const disableTx = await zeroEx.token.setProxyAllowanceAsync(
      wethAddress,
      makerAddress,
      new BigNumber("0"),
      {
        // You can optionally pass in the gas price and gas limit you would like to use
        gasLimit: 80000,
        gasPrice: new BigNumber(10**10),
      }
    )
    console.log(disableTx) // Transaction id
    

    To allow a relayer to match trades from your digital wallet for a given token type, users must first perform a 1-time transaction to "enable" (or unlock) each type of token they wish to trade. This enabling process only has to be done once, and can be done through our DDEX exchange. Please visit our Support Article for more information on how to make sure your tokens are enabled for trading.

    Build Unsigned Order

    Request

    {
      "amount": "100",
      "price": "0.0007",
      "side": "buy",
      "marketId": "ZEN-ETH"
    }
    

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "order": {
          "id": "0x36975d8312c7f09003e0d280f3e8f48d406961a74afdf023873c12b99d35e86f",
          "json": {
            "salt": "92585752206766496380174339000730928910631062426946021202697952754648081087236",
            "maker": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "taker": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "makerFee": "0",
            "takerFee": "0",
            "feeRecipient": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "makerTokenAmount": "2879645928000000",
            "takerTokenAmount": "314159260000000000000",
            "makerTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
            "takerTokenAddress": "0x69b148395ce0015c13e36bffbad63f49ef874e03",
            "exchangeContractAddress": "0x12459c951127e0c374ff9105dda097662a027093",
            "expirationUnixTimestampSec": "1556000600"
          },
          "marketId": "ZEN-ETH",
          "side": "buy",
          "price": "0.0007",
          "amount": "100",
          "feeAmount": "0.002",
        }
      }
    }
    

    Returns data about an unsigned 0x order based on the requested order parameters passed in. To place an order you will sign this data and post it back to the API to authenticate the use of your account in the trade.

    HTTP Request

    POST https://api.ddex.io/v2/orders/build

    Query Parameters

    Parameter Description
    marketId The market you wish to post the order to. Specified in the form of a trading pair of tokens, e.g. ZEN-ETH.
    side buy or sell.
    price The price of the order. e.g. 0.0007.
    amount The amount of token in the order. e.g. 100.

    Details

    Returns information about the order you wish to create. The field unsignedOrder contains values that 0x will need to complete the transaction. You can read about them in more detail on the 0x wiki. We also return orderId which is what you will sign and post to allow 0x to fulfill the order on your behalf. Finally we return the estimated feeAmount that will be charged for this order to be filled.

    Sign Order

    Example (web3)

    const address = web3.eth.coinbase
    const orderId = "0x36975d8312c7f09003e0d280f3e8f48d406961a74afdf023873c12b99d35e86f"
    web3.personal.sign(web3.toHex(orderId), address, (err, signature) => {
      console.log(signature)
    })
    

    Example (ethereumjs-util)

    import { hashPersonalMessage, ecsign, toRpcSig, toBuffer, privateToAddress } from "ethereumjs-util"
    
    const orderId = "0x36975d8312c7f09003e0d280f3e8f48d406961a74afdf023873c12b99d35e86f"
    const privateKey = '0xe4abcbf75d38cf61c4fde0ade1148f90376616f5233b7c1fef2a78c5992a9a50'
    const address = privateToAddress(privateKey).toString("hex")
    
    const sha = hashPersonalMessage(toBuffer(orderId))
    const ecdsaSignature = ecsign(sha, toBuffer(privateKey))
    const signature = toRpcSig(ecdsaSignature.v, ecdsaSignature.r, ecdsaSignature.s)
    console.log(signature)
    

    Once you have an orderId for an unsigned order built on the server, you will have to sign it in order to post it to the orderbook.

    Place Order

    Request

    {
      "orderId": "0x36975d8312c7f09003e0d280f3e8f48d406961a74afdf023873c12b99d35e86f",
      "signature": "0xb468081071544fdcae0292115cafc0f422dbc0ff2a3cc2d19e6147f5a6a6e20c5c5cfae18531e417164e5ef2a00d8c29060a816814874eaf554b004ae70fa49401"
    }
    

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "order": {
          "id": "0xa01e614884d10573b03c104ec5a8223ad029a8bfaddb165b0f5149ff31b2370c",
          "json": {
            "exchangeContractAddress": "0x12459c951127e0c374ff9105dda097662a027093",
            "expirationUnixTimestampSec": "1556000600",
            "feeRecipient": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "maker": "0x3ae88dfb252fe623a7fb6b4df96d96eb150e830a",
            "makerFee": "0",
            "salt": "8585329732592235586524381107271284455680411829518076630110672391309226489834",
            "taker": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "takerFee": "0",
            "makerTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
            "makerTokenAmount": "70750000000000000",
            "takerTokenAddress": "0xe41d2489571d322189246dafa5ebde1f4699f498",
            "takerTokenAmount": "100000000000000000000"
          },
          "marketId": "ZEN-ETH",
          "status": "pending",
          "amount": "100",
          "fee": "0.001",
          "availableAmount": "100",
          "pendingAmount": "0",
          "canceledAmount": "0",
          "confirmedAmount": "0",
          "price": "0.0007",
          "side": "buy",
          "feeAmount": "0.00075",
          "account": "0x3ae88dfb252fe623a7fb6b4df96d96eb150e830a"
        }
      }
    }
    

    After signing the orderId you can post it to this endpoint with the signature you created in order to send it to the orderbook.

    HTTP Request

    POST https://api.ddex.io/v2/orders

    Query Parameters

    Parameter Description
    orderId The id returned from the Build Unsigned Order endpoint.
    signature The signature created during the Sign Order step.

    Details

    Returns information about the order that was posted to the orderbook. The json field in the order contains values that 0x will need to complete the transaction. You can read about them in more detail on the 0x wiki. Also included in the data is the original marketId, side, price and amount requested for the order, the account used to make the order, and the feeAmount that will be charged upon completion of the order.

    Cancel Order

    Response

    {
      "status": 0,
      "desc": "success"
    }
    

    Used to cancel an order given an orderId

    HTTP Request

    DELETE https://api.ddex.io/v2/orders/:orderId

    URL Parameters

    Parameter Description
    orderId The id of the order you wish to cancel.

    Details

    Simply returns success if we were able to cancel the order, or an error if the order doesn't exist or is not in a cancellable state (e.g. being fulfilled).

    List Orders

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "totalPages": 100,
        "currentPage": 1,
        "orders": [
          {
            "id": "0x1d8711e3fc7af706e4a9b82d0a673901300ed9172f729cfdc121fba570f9b119",
            "marketId": "DTA-ETH",
            "status": "pending",
            "price": "0.0000028",
            "amount": "314.15926",
            "availableAmount": "314.15926",
            "pendingAmount": "0",
            "canceledAmount": "0",
            "confirmedAmount": "0",
            "side": "buy",
            "feeAmount": "0.002",
            "address": "0x266d3299d8ede74e9dce770366bbe59179f676ef",
            "createdAt": 1517396033687,
            "json": {
              "salt": "92585752206766496380174339000730928910631062426946021202697952754648081087236",
              "maker": "0x266d3299d8ede74e9dce770366bbe59179f676ef",
              "taker": "0xe269e891a2ec8585a378882ffa531141205e92e9",
              "makerFee": "0",
              "takerFee": "0",
              "feeRecipient": "0xe269e891a2ec8585a378882ffa531141205e92e9",
              "makerTokenAmount": "2879645928000000",
              "takerTokenAmount": "314159260000000000000",
              "makerTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
              "takerTokenAddress": "0x69b148395ce0015c13e36bffbad63f49ef874e03",
              "exchangeContractAddress": "0x12459c951127e0c374ff9105dda097662a027093",
              "expirationUnixTimestampSec": "33053396029"
            },
          },
          ...
        ],
      }
    }
    

    Return paginated data for all orders created by the currently authenticated trading account. The orders are sorted by creation time in descending order.

    HTTP Request

    GET https://api.ddex.io/v2/orders

    Query Parameters

    Parameter Description
    marketId (Optional) The market you wish to list orders from. Specified in the form of a trading pair of tokens, e.g. DTA-ETH.
    status (Optional) pending or all. Defaults to pending.
    page (Optional) Used for pagination. Defaults to 1.
    perPage (Optional) Used for pagination. Value must be between 1-100. Defaults to 100.

    Details

    Please see Place Order for a description of the data returned for each order in the list.

    Get Order

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "order": {
          "id": "0x1d8711e3fc7af706e4a9b82d0a673901300ed9172f729cfdc121fba570f9b119",
          "marketId": "DTA-ETH",
          "status": "pending",
          "price": "0.0000028",
          "amount": "314.15926",
          "availableAmount": "314.15926",
          "pendingAmount": "0",
          "canceledAmount": "0",
          "confirmedAmount": "0",
          "side": "buy",
          "feeAmount": "0.002",
          "address": "0x266d3299d8ede74e9dce770366bbe59179f676ef",
          "createdAt": 1517396033687,
          "json": {
            "salt": "92585752206766496380174339000730928910631062426946021202697952754648081087236",
            "maker": "0x266d3299d8ede74e9dce770366bbe59179f676ef",
            "taker": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "makerFee": "0",
            "takerFee": "0",
            "feeRecipient": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "makerTokenAmount": "2879645928000000",
            "takerTokenAmount": "314159260000000000000",
            "makerTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
            "takerTokenAddress": "0x69b148395ce0015c13e36bffbad63f49ef874e03",
            "exchangeContractAddress": "0x12459c951127e0c374ff9105dda097662a027093",
            "expirationUnixTimestampSec": "33053396029"
          }
        }
      }
    }
    

    Return a single order identified by orderId

    HTTP Request

    GET https://api.ddex.io/v2/orders/:orderId

    URL Parameters

    Parameter Description
    orderId The id of the order you wish to query.

    Details

    Please see Place Order for a description of the data returned for the order.

    List Account Trades

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "totalPages": 10,
        "currentPage": 1,
        "trades": [
          {
            "maker": "0xd01af191c9143e26e7103d6fe41412b894b25e97",
            "taker": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "amount": "2099.39882679",
            "price": "0.00138045",
            "takerPrice": "0.0013804",
            "feeAmount": "0.002898010140500916",
            "buyer": "0xe269e891a2ec8585a378882ffa531141205e92e9",
            "seller": "0xd01af191c9143e26e7103d6fe41412b894b25e97",
            "marketId": "ZRX-ETH",
            "transactionId": "0x762d6ce2a8b30151c7dc7d29f0068e2dda2d1dd852f637d9e302e4fa408a0611",
            "makerOrderId": "0x9c97edd05124ffa5ff4cf88e24acd9014034e26ba5151caec0564681a470dfe1",
            "takerOrderId": "0x20f79c4ce66d143f4894696b3b4340de6aa68d22ea2a7e67231359b6d26dec5d",
            "executedAt": 1520914296000,
            "status": "successful",
            "createdAt": 1520914269749
          },
          ...
        ]
      }
    }
    

    Return paginated data for all trades made by the currently authenticated user account in a single market identified by marketId. The trades are sorted by creation time in descending order.

    HTTP Request

    GET https://api.ddex.io/v2/markets/:marketId/trades/mine

    URL Parameters

    Parameter Description
    marketId Query for trade data on a specific market. Specified in the form of a trading pair of tokens, e.g. ZRX-ETH.

    Query Parameters

    Parameter Description
    page (Optional) Used for pagination. Defaults to 1.
    perPage (Optional) Used for pagination. Value must be between 1-100. Defaults to 100.

    Details

    Returns all of the authenticated user's trade data for the specified market. Results will be paginated with a default page size of 20 results.

    Each set of trade data contains all the information about the maker (creator of the order) and taker, including account addresses, order ids, and the final transaction id. It also includes all the order details including the price and amount of the order. We also return the feeAmount paid to the exchange, as well as the takerPrice. Finally you can view the status of the order, the time at which the trade was created due to matching orders in the book (createdAt) and the time the trade was completed on the blockchain (executedAt).

    List Locked Balances

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "lockedBalances": [
          {
            "amount": "6000000000000000000006",
            "symbol": "ZEN",
            "updatedAt": 1363828259897
          },
          ...
        ]
      }
    }
    

    List locked balances of each active symbol on the market for the currently authenticated user.

    HTTP Request

    GET https://api.ddex.io/v2/account/lockedBalances

    Details

    The locked balance for a symbol is the amount of that token that is currently listed in orders owned by the currently authenticated user. For example, if the account has created 3 sell orders for the ZEN symbol at 100, 1000, and 500 tokens respectively, and the orders are still pending, the locked balance for ZEN will be 1600.

    Get Locked Balance

    Response

    {
      "status": 0,
      "desc": "success",
      "data": {
        "lockedBalance": {
          "amount": "6000000000000000000006",
          "symbol": "ZEN",
          "updatedAt": 1363828259897
        }
      }
    }
    

    Get the locked balance of a specific symbol for the currently authenticated user.

    HTTP Request

    GET https://api.ddex.io/v2/account/lockedBalance

    Query Parameters

    Parameter Description
    symbol The symbol you wish to query for locked balance, e.g. ZEN.

    Details

    Please see List Locked Balances for details.

    Websocket

    Overview

    The Websocket API is intended to provide real-time updates to the state of the market. In order to receive updates, you must open a socket to the websocket endpoint, and send a subscription message. This message will define what real-time data you are interested in, so you only get the updates you need.

    Endpoint: wss://ws.ddex.io

    Subscribe

    Request

    {
      "type": "subscribe",
      "channels": [
        {
          "name": "full",
          "marketIds": [ "HOT-ETH" ]
        },
        {
          "name": "ticker",
          "marketIds": [ "HOT-ETH" ]
        }
      ]
    }
    

    Response

    {
      "type": "subscriptions",
      "channels": [
        {
          "name": "full",
          "marketIds": [ "HOT-ETH" ]
        },
        {
          "name": "ticker",
          "marketIds": [ "HOT-ETH" ]
        }
      ]
    }
    

    To begin receiving websocket messages, you must first send a subscribe message to the server indicating which channels you are interested in, and for which markets you wish to receive updates.

    JSON Fields

    Parameter Description
    type subscribe
    channels An array of Channel Data describing which channels and markets you wish to subscribe to.

    Channel Data

    Parameter Description
    name ticker, orderbook, or full
    marketIds An array of market ids, specified in the form of a trading pair of tokens, e.g. ZRX-ETH

    Details

    Once a subscribe message is received, the server will respond with a subscriptions message that lists all channels you are currently subscribed to.

    Unsubscribe

    Request

    {
      "type": "unsubscribe",
      "channels": [
        {
          "name": "full",
          "marketIds": [ "HOT-ETH" ]
        }
      ]
    }
    

    Response

    {
      "type": "subscriptions",
      "channels": [
        {
          "name": "ticker",
          "marketIds": [ "HOT-ETH" ]
        }
      ]
    }
    

    If you are no longer interested in a channel, you may send an unsubscribe message to the server indicating which channels you no longer wish to receive updates for.

    JSON Fields

    Parameter Description
    type unsubscribe
    channels An array of Channel Data describing which channels and markets you wish to unsubscribe to.

    Channel Data

    Parameter Description
    name ticker, orderbook, or full
    marketIds An array of market ids, specified in the form of a trading pair of tokens, e.g. ZRX-ETH

    Details

    Once an unsubscribe message is received, the server will respond with a subscriptions message that lists all channels you are currently subscribed to.

    Ticker Channel

    Subscription Request

    {
      "type": "subscribe",
      "channels": [
        {
          "name": "ticker",
          "marketIds": [ "ZRX-ETH" ]
        }
      ]
    }
    

    Sample Message

    {
      "type": "ticker",
      "time": 1520847743338,
      "marketId": "ZRX-ETH",
      "bid": null,
      "price": "0.08",
      "volume": "1",
      "high": "0.08",
      "low": "0"
    }
    

    Subscribing to the ticker channel will provide real time price updates every time a trade is completed. In case of cascading trades, the updates will be batched to avoid excess bandwidth usage.

    Details

    The ticker data returned in the message includes the marketId, as well as the current price, volume, high and low values for that market.

    Orderbook Channel

    Subscription Request

    {
      "type": "subscribe",
      "channels": [
        {
          "name": "orderbook",
          "marketIds": [ "HOT-ETH" ]
        }
      ]
    }
    

    Snapshot Message

    {
      "type": "level2OrderbookSnapshot",
      "marketId": "HOT-ETH",
      "bids": [
        {"price": "0.007", "amount" : "400"},
        {"price": "0.00911", "amount" : "270"},
        {"price": "0.00913", "amount" : "190"},
        {"price": "0.014412", "amount" : "120"},
        {"price": "0.014413", "amount" : "220"},
        {"price": "0.014434", "amount" : "130"},
        {"price": "0.014438", "amount" : "170"},
        {"price": "0.014456", "amount" : "100"},
        {"price": "0.01448", "amount" : "200"},
        {"price": "0.0145", "amount" : "400"}
      ],
      "asks": [
        {"price" : "0.01498", "amount": "100"},
        {"price" : "0.014977", "amount": "130"},
        {"price" : "0.014971", "amount": "130"},
        {"price" : "0.014949", "amount": "130"},
        {"price" : "0.0149", "amount": "0"},
        {"price" : "0.01489", "amount": "0"},
        {"price" : "0.014883", "amount": "0"},
        {"price" : "0.014855", "amount": "146"},
        {"price" : "0.014848", "amount": "110"},
        {"price" : "0.014843", "amount": "100"},
        {"price" : "0.014818", "amount": "100"},
        {"price" : "0.01481", "amount": "82"},
        {"price" : "0.0148", "amount": "400"},
        {"price" : "0.014774", "amount": "100"}
      ]
    }
    

    Update Message

    {
      "type": "level2OrderbookUpdate",
      "marketId": "HOT-ETH",
      "changes": [
        {"side": "sell", "price": "0.014789", "amount": "0"}
      ]
    }
    

    The orderbook channel provides an easy way to maintain a live view of the aggregated orderbook.

    Snapshot

    After subscribing to the channel, it will send a message of type level2OrderbookSnapshot for each subscribed market. The message is a complete, although aggregated, snapshot of the current orderbook, where bids and asks are lists of json data containing price and amount of token available at that price (aggregated over all orders in the book).

    Update

    Once you get the initial snapshot, messages will be sent corresponding to any change in the orderbook. The message will have the type level2OrderbookUpdate and list which market the change occurred in. It also contains a list of changes which contain which side the change occurred on, the price the change occurred at, and the new amount at that price level.

    Note that if the new amount in an update is 0, the price level can be removed from your orderbook.

    Full Channel

    Subscription Request

    {
      "type": "subscribe",
      "channels": [
        {
          "name": "full",
          "marketIds": [ "HOT-ETH" ]
        }
      ]
    }
    

    Snapshot Message

    {
      "type": "level3OrderbookSnapshot",
      "marketId": "HOT-ETH",
      "sequence": 345,
      "bids": [
        {
          "price": "0.00054",       // price,
          "amount": "1200",          // amount
          "orderId": "0xabde02351..." // orderId
        },
        ....
      ],
      "asks": [
        {
          "price": "0.00064",       // price,
          "amount": "40000",         // amount
          "orderId": "0x4055f060c..." // orderId
        },
        ....
      ]
    }
    

    Receive Message

    {
      "type": "receive",
      "time": 1520577582556,
      "marketId": "ZRX-ETH",
      "sequence": 1,
      "price": "0.1",
      "orderId": "0xa60d846292e50bed9a37eac69d91bb9180ed754f43fa44c5dff5bf9aeddb5128",
      "side": "sell",
      "canceledAmount": "0",
      "confirmedAmount": "0",
      "availableAmount": "1",
      "pendingAmount": "0"
    }
    

    Open Message

    {
      "type": "open",
      "time": 1520837845343,
      "marketId": "ZRX-ETH",
      "sequence": 2,
      "price": "0.8",
      "orderId": "0x531b9e9e7aba5f4f84940e4a9923ce44cf8a43b6e3f5aac98d56e439e467efdb",
      "side": "sell",
      "canceledAmount": "0",
      "confirmedAmount": "0",
      "availableAmount": "1",
      "pendingAmount": "0"
    }
    

    Done Message

    {
      "type": "done",
      "time": 1520837846102,
      "marketId": "ZRX-ETH",
      "sequence": 14,
      "price": "0.8",
      "orderId": "0x531b9e9e7aba5f4f84940e4a9923ce44cf8a43b6e3f5aac98d56e439e467efdb",
      "side": "sell",
      "canceledAmount": "0",
      "confirmedAmount": "0",
      "availableAmount": "0",
      "pendingAmount": "1"
    }
    

    Change Message

    {
      "type": "change",
      "time": 1520837846102,
      "marketId": "ZRX-ETH",
      "sequence": 14,
      "price": "0.8",
      "orderId": "0x531b9e9e7aba5f4f84940e4a9923ce44cf8a43b6e3f5aac98d56e439e467efdb",
      "side": "sell",
      "oldAvailableAmount": "2",
      "newAvailableAmount": "1"
    }
    

    Trade Message

    {
      "type": "trade",
      "time": 1520844812020,
      "marketId": "ZRX-ETH",
      "sequence": 15,
      "price": "0.8",
      "transactionId": "0xb1a42cbe03b749edb07d220286f4c99c5ac6ebcac6f8ef92b26769cb5f0f0fc2",
      "makerOrderId": "0x1f6d2e6c9deba47c842eda4a1529f53d4d74c071ab6dffcf8d4b71a5bc913c2b",
      "takerOrderId": "0x50ca7438f009d752bd4bd093d93f1db49076dea0c566690891cd6b9fee4c2343",
      "taker": "0x5409ed021d9299bf6814279a6a1411a7e866a631",
      "maker": "0x1edad6dad44367a6e0e342e76e9df595049b8224",
      "amount": "1",
      "makerSide": "sell"
    }
    

    Trade Success Message

    {
      "type": "trade_success",
      "time": 1520844820685,
      "marketId": "ZRX-ETH",
      "price": "0.09",
      "transactionId": "0x9ed3c60f199aaadf13e9766ceebb156f10817a2186a78f3f3f374757471bbfc5",
      "makerOrderId": "0x722794395d38d70c848be14484f016c8bb696c15c655bea3a951d47ae413f731",
      "takerOrderId": "0x8a3eddfd60a64714afcbfdf1079a45bcb6707931142e9cdc03181f6d5dd03640",
      "amount": "0.5",
      "makerSide": "sell"
    }
    

    The full channel provides real-time updates on all orders and trades for the specified markets. These updates can be applied on to a level 3 orderbook snapshot to maintain an accurate, non-aggregated copy of the exchange orderbook.

    Sequence Numbers

    Updates you receive will contain a sequence number. Sequence numbers are increasing integer values that will always increase by 1 for each new message in the sequence. If the sequence number you receive is more than 1 higher than the previous value, then a message has been dropped. If you see a sequence number lower than the previous value, then a message has arrived out of order and can likely be ignored. In both cases you may need to perform some logic to get your system to consistent state. For example, if you miss a change message, you should resubscribe to the channel in order to receive a full snapshot message and reset your state.

    Snapshot

    After subscribing to the channel, it will send a message of type level3OrderbookSnapshot for each subscribed market. The message is a complete, non-aggregated snapshot of the current orderbook, where bids and asks are lists of json data containing price, amount, and the orderId for the order it represents. These data blobs are not aggregated, so you will receive one for every order on the market.

    Receive

    A valid order has been received and is now active. This message is emitted for every valid order as soon as the matching engine receives it, whether it fills immediately or not.

    Open

    A new order is now open on the orderbook. This message will only be sent for orders which are not fulfilled immediately. availableAmount will indicate how much of the order is unfulfilled and available on the orderbook.

    Done

    An order is no longer available on the orderbook. This message can result from an order being canceled or completely filled. There will be no more messages for this orderId once this message has been received. canceledAmount indicates how much of the order went unfulfilled, and confirmedAmount indicates how much of the order was fulfilled.

    Change

    If an order is changed due to self-trade prevention, you will receive a change message for that orderId. It will contain the oldAvailableAmount, as well as the newAvailableAmount which is the amount of token left over in the order that can still be fulfilled.

    Trade

    Two orders have been matched, and a trade has occurred. The orders will be marked as pending until the trade is successfully validated on the blockchain.

    Trade Success

    A trade has been validated on the blockchain.

    Examples

    GitHub

    Maker Demo

    A simple "maker" bot that will post orders based on price changes. If the price goes up, it will place a bid order at the new price, and if the price goes down it will place an ask order at that price.

    Maker Demo

    Orderbook Demo

    Maintains a live orderbook, receiving websocket updates and keeping a full level 2 orderbook. Displayed graphically in the command line.

    Orderbook Demo