├── 0xv2_upgrade.md ├── examples └── order_signing.ts └── readme.md /0xv2_upgrade.md: -------------------------------------------------------------------------------- 1 | # 0x v2 Migration Guide 2 | 3 | ## Allowances 4 | 5 | The 0x v2 contracts use a new proxy contract, so you will need to set new trading allowances for your accounts. For reference, the new proxy contracts are: 6 | 7 | ``` 8 | kovan: 0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e 9 | mainnet: 0x2240dab907db71e64d3e0dba4800c83b5c502d4e 10 | ``` 11 | 12 | ## /v0/orderParams 13 | 14 | Previously, this endpoint returned an unsigned 0x order in the following foramat: 15 | ``` 16 | { 17 | fee: { 18 | id: 'b046140686d052fff581f63f8136cce1', 19 | baseFeeDecimal: '1.697552694864903098033668128', 20 | tradingFeeDecimal: '21.21940868581128872542085161', 21 | secundsUntilPrune: 60, 22 | pruneUnixTimeStamp: 2017-11-21T18:00:00Z 23 | }, 24 | zrxOrder: { 25 | exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093', 26 | expirationUnixTimestampSec: '1518124088', 27 | feeRecipient: '0x0000000000000000000000000000000000000000', 28 | maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b', 29 | makerFee: '0', 30 | makerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', 31 | makerTokenAmount: '22000000000000000', 32 | salt: '54515451557974875123697849345751275676157243756715784155226239582178', 33 | taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32', 34 | takerFee: '0', 35 | takerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', 36 | takerTokenAmount: '10000000000000000', 37 | }} 38 | ``` 39 | 40 | After the migration is complete, you will receive orders in a 0x v2 compatible format: 41 | 42 | ``` 43 | { 44 | fee: { 45 | id: 'b046140686d052fff581f63f8136cce1', 46 | baseFeeDecimal: '1.697552694864903098033668128', 47 | tradingFeeDecimal: '21.21940868581128872542085161', 48 | secundsUntilPrune: 60, 49 | pruneUnixTimeStamp: 2017-11-21T18:00:00Z 50 | }, 51 | zrxOrder { 52 | exchangeAddress: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364' 53 | expirationTimeSeconds: '1539389400' 54 | feeRecipientAddress: '0x0000000000000000000000000000000000000000' 55 | makerAddress: '0x5bbbac1a500987f97ec705d5f914c45ae3549def' 56 | makerAssetAmount: '40000000000000000' 57 | makerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c' 58 | makerFee: '0' 59 | salt: '1538784915143' 60 | senderAddress: '0x0000000000000000000000000000000000000000' 61 | takerAddress: '0x634fce3ad082ed4efd1fa766f391f3d5bcec5c66' 62 | takerAssetAmount: '9145000000000000000' 63 | takerAssetData: '0xf47261b00000000000000000000000006ff6c0ff1d68b964901f986d4c9fa3ac68346570' 64 | takerFee: '0' 65 | }} 66 | ``` 67 | 68 | Going forward, you should expect any other endpoint that returns zrx order parameters to return the v2 order format. 69 | 70 | ## API keys 71 | 0xv2 is currently live if you'd like to test your migration. You can request an API key at: 72 | 73 | ``` 74 | https://kovan.paradex.io/developers 75 | ``` 76 | Note that we are also now requiring all newly issued API keys to first call `/verifyAddress` to enable it. -------------------------------------------------------------------------------- /examples/order_signing.ts: -------------------------------------------------------------------------------- 1 | import BN = require('bn.js'); 2 | import * as ethABI from 'ethereumjs-abi'; 3 | import * as ethUtil from "ethereumjs-util" 4 | 5 | let privateKey = '0xabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabca' 6 | // get orderParams from orderParams endpoint in paradex apx 7 | let orderParams = { 8 | fee: 9 | { 10 | id: 'c149d40732a98cd9c435bb0e24a83284', 11 | baseFeeDecimal: '0.00764', 12 | tradingFeeDecimal: '0.00064' 13 | }, 14 | zrxOrder: 15 | { 16 | exchangeContractAddress: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364', 17 | expirationUnixTimestampSec: '1519424092', 18 | feeRecipient: '0x0000000000000000000000000000000000000000', 19 | maker: '0xe97e33c819383ccfcaeacd5fd62b534b82003a1c', 20 | makerFee: '0', 21 | makerTokenAddress: '0xb18845c260f680d5b9d84649638813e342e4f8c9', 22 | makerTokenAmount: '8036540000000000000', 23 | salt: '18140479134825617220609856409120294369607089158088901951801076026344391201567', 24 | taker: '0x634fce3ad082ed4efd1fa766f391f3d5bcec5c66', 25 | takerFee: '0', 26 | takerTokenAddress: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', 27 | takerTokenAmount: '424969871400000000' 28 | } 29 | }; 30 | 31 | let hashHex = getOrderHashHex(orderParams.zrxOrder); 32 | let hashHexBuffer = ethUtil.toBuffer(hashHex); 33 | let prefix = ethUtil.toBuffer('\u0019Ethereum Signed Message:\n32'); 34 | let hashedHash = ethUtil.sha3(Buffer.concat([prefix, hashHexBuffer])); 35 | let signature = ethUtil.ecsign(hashedHash, ethUtil.toBuffer(privateKey)); 36 | 37 | let signedOrder = orderParams.zrxOrder; 38 | signedOrder['v'] = signature.v; 39 | signedOrder['r'] = ethUtil.bufferToHex(signature.r); 40 | signedOrder['s'] = ethUtil.bufferToHex(signature.s); 41 | signedOrder['feeId'] = orderParams.fee.id; 42 | // you now have a signed order that is your payload to submit to the order endpoint. 43 | // remember to add your nonce to the payload before you go through the payload signing process 44 | 45 | 46 | // this function is copied from the 0x.js library. If you already include that library you can 47 | // import using the following import statement 48 | // import { utils } from '0x.js/lib/src/utils/utils' 49 | // function is available at utils.getOrderHashHex() 50 | // If you used the 0x.js version of this function the 51 | // import * as ethABI from 'ethereumjs-abi'; 52 | // statement at the top of this file is superfluous 53 | function getOrderHashHex(zrxOrder) { 54 | const orderParts = [ 55 | { value: zrxOrder.exchangeContractAddress, type: 'address' }, 56 | { value: zrxOrder.maker, type: 'address' }, 57 | { value: zrxOrder.taker, type: 'address' }, 58 | { value: zrxOrder.makerTokenAddress, type: 'address' }, 59 | { value: zrxOrder.takerTokenAddress, type: 'address' }, 60 | { value: zrxOrder.feeRecipient, type: 'address' }, 61 | { 62 | value: new BN(zrxOrder.makerTokenAmount, 10), 63 | type: 'uint256', 64 | }, 65 | { 66 | value: new BN(zrxOrder.takerTokenAmount, 10), 67 | type: 'uint256', 68 | }, 69 | { 70 | value: new BN(zrxOrder.makerFee, 10), 71 | type: 'uint256', 72 | }, 73 | { 74 | value: new BN(zrxOrder.takerFee, 10), 75 | type: 'uint256', 76 | }, 77 | { 78 | value: new BN(zrxOrder.expirationUnixTimestampSec, 10), 79 | type: 'uint256', 80 | }, 81 | { value: new BN(zrxOrder.salt, 10), type: 'uint256' }, 82 | ]; 83 | const types = orderParts.map(o => o.type); 84 | const values = orderParts.map(o => o.value); 85 | const hashBuff = ethABI.soliditySHA3(types, values); 86 | const hashHex = ethUtil.bufferToHex(hashBuff); 87 | return hashHex; 88 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Note: This API is now deprecated. For documentation on the new API, please see see https://developers.paradex.io 2 | 3 | # Paradex Consumer API 4 | 5 | ## Contents 6 | [API URLs](#api-urls) 7 | 8 | [Sending Requests](#sending-requests) 9 | 10 | [Deposits/Withdrawals](#depositswithdrawals) 11 | 12 | [Placing and Signing Orders](#placing-and-signing-orders) 13 | 14 | [Order Expiry](#order-expiry) 15 | 16 | [Errors](#errors) 17 | 18 | [Misc](#misc) 19 | 20 | [Paradex Consumer API](#paradex-consumer-api) 21 | 22 | ## API URLs 23 | ### mainnet 24 | For mainnet, use the following base url: 25 | 26 | https://api.paradex.io/consumer 27 | 28 | You can request an API key at `https://paradex.io/developers` 29 | 30 | ### kovan 31 | For kovan, use: 32 | 33 | https://kovan-api.paradex.io/consumer 34 | 35 | You can request an API key at `https://kovan.paradex.io/developers` 36 | 37 | ## Sending Requests 38 | 39 | To access the API you need a valid API key. All endpoints require your API key to be sent in the header of every request. 40 | ``` 41 | API-KEY: odxnkc39oenis239p88geuth4p7fkbic 42 | ``` 43 | 44 | There are two types of endpoints in the Paradex Consumer API: `public` and `private`. While both require a valid API key, `private endpoints` return sensitive trading or order activity for that ethereum account and have additional checks in place to ensure account security. 45 | 46 | All private endpoints are POST requests which require you to sign the payload using the ethereum account associated with your API key. The API will only allow you to perform actions relating to this ethereum account. The resultant signature should be sent in the header of the request using the API-SIG header. A nonce is also included in the payload to ensure requests can't be harvested and replayed. For new API accounts the nonce is set to 0, and every request must contain an integer nonce greater than the nonce used in the last request. The nonce is incremented even if the request was not successful. The only actions that do not result in the nonce being incremented are an invalid API key or an invalid nonce. 47 | 48 | ### Signing the payload of requests 49 | 50 | Given the following POST parameters: 51 | ``` 52 | { 53 | market: 'REP/WETH' 54 | state: 'all' 55 | nonce: 1234567 56 | } 57 | ``` 58 | 59 | We create a payload message by ordering the payload by the keys then concatenating the keys together, followed by the values for those keys concatenated together. Please note this message contains the "Ethereum Signed Message:" prefix along with the length of the message. So for the above payload, we'd get the following payload message: 60 | 61 | ``` 62 | '\u0019Ethereum Signed Message:\n34marketnoncestateREP/WETH1234567all' 63 | ``` 64 | Depending on the language and library that you are using to hash the message, the prefix might be automatically added to the string you are passing in, so make sure that it isn't getting added twice. If the library you're using does automatically add in the prefix then the payload message to pass into the hash function would be 65 | ``` 66 | 'marketnoncestateREP/WETH1234567all' 67 | ``` 68 | 69 | This message is then hashed using Keccak-256 and signed by the private key for the ethereum account to produce a vrs signature which we include in the API-SIG header of the request. The API-SIG is constructed by concatenating the r + s + v values together in that order. A typescript example of the signing process is included here for reference: 70 | 71 | 72 | ``` 73 | import * as utils from "ethereumjs-util" 74 | 75 | let payload = { 76 | market: 'REP/WETH' 77 | state: 'all' 78 | nonce: 1234567 79 | } 80 | 81 | let message = createMessage(payload); // returns 'marketnoncestateREP/WETH1234567all' 82 | 83 | let privateKey = '0xabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabca'; 84 | 85 | let sha = utils.hashPersonalMessage(Buffer.from(message)); 86 | let signature = utils.ecsign(sha, utils.toBuffer(privateKey)); 87 | let APISIG = utils.toRpcSig(signature.v, signature.r, signature.s); 88 | 89 | function createMessage(payload) { 90 | let keys = Object.keys(payload).sort(); 91 | let message = keys.join(""); 92 | for (let key of keys) { 93 | message += payload[key]; 94 | } 95 | return message 96 | } 97 | ``` 98 | This produces the signature `0xa5539969aad2a815ac40b961e1fde9f5c12f60cff9b0fb140a90e581339698020202cde14a9ef9fc8d027fc0d3e99ca026570ee5fd10d70e041a9d1b5dbdb29401` 99 | 100 | 101 | 102 | ## Deposits/Withdrawals 103 | 104 | Paradex is a non-custodial platform. This means you retain complete control of your funds and they stay in your own wallet until a trade takes place. As such, there is no way to deposit or withdraw funds to or from Paradex. Assets can be moved in and out of your wallet either programmatically or via an application. You will need to wrap Ether and set allowances for tokens you want to offer. 105 | 106 | ## Wrapping ETH and Setting Allowances 107 | 108 | The ERC20 standard was created to provide a common interface for tokens. Ether is not currently an ERC20 token and has to be converted to an ERC20 compatible token called Wrapped-ETH (WETH). This conversion process is called wrapping, with 1 WETH being equivalent to 1 ETH. 109 | Another feature of ERC20 tokens is allowances. Allowances allow you to control how much of your funds can be transferred out of your wallet by the 0x contracts used by Paradex. By default your allowances are set to 0, so before you begin trading you'll need to set allowances for your tokens. Even once you have set your allowances set, no funds can be transferred out of your account without you putting a valid order on the orderbook. If you try and place an order to Paradex without setting an allowance for that token, your order will be in an unfunded state. If you want to set allowances programmatically, the 0x.js library provides some convenience methods to help you do that: https://www.0xproject.com/docs/0xjs#token 110 | 111 | ## Placing and Signing Orders 112 | 113 | To place orders on the book that can then be sent to the 0x contracts to be traded when matched you have to submit a signed order (zrxOrder). This is slightly different from the payload signing process described above. When placing requests to the order endpoint, you have to go through both signing processes as they maintain security at different points in the system. Signing the payload message proves to the Paradex API that you control the account you are sending orders for while signing the order itself gives authority to the 0x contract to settle your order. 114 | 115 | To get the correct parameters for a zrxOrder object we have a convenience method `orderParams` that returns a zrxOrder object and a fees object. The fees object tells you what fees your order will incur if traded. For transparency fees are split into two parts: baseFeeDecimal and tradingFeeDecimal. The baseFeeDecimal is the gas cost to execute the trade(s) while the tradingFee is the commission on the trade. Fees are proportional to the amount of your total order that get's filled. For example, if only 50% of your order gets filled you will only pay 50% of the fees quoted. Once issued fee quotes are valid for 30 minutes. 116 | 117 | To call the orderParams endpoint you need to submit the following: 118 | ``` 119 | market - symbol of market 120 | orderType - 'buy'|'sell' 121 | price - price in quote currency 122 | amount - amount of base currency 123 | expirationDate - expiration date and time of order in ISO 8601 format 124 | ``` 125 | There are some important details regarding the expirationDate. For more info please see the [order expiry](#order-expiry) section below) 126 | 127 | Once you have a zrxOrder to sign and a fee quote you can start the order submission process. First, you need to sign the zrxOrder. Here's an example of signing the zrxOrder and adding the correct fields to the order to allow it to be submitted to the order endpoint. Once you have the full signed order it should go through the same payload signing process required by the other endpoints. 128 | ``` 129 | import BN = require('bn.js'); 130 | import { utils } from '0x.js/lib/src/utils/utils' 131 | import * as ethUtil from "ethereumjs-util" 132 | 133 | let privateKey = '0xabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabca' 134 | // get orderParams from orderParams endpoint in paradex apx 135 | let orderParams = {.....} // data returned from orderParams endpoint 136 | 137 | let hashHex = utils.getOrderHashHex(orderParams.zrxOrder); 138 | let hashHexBuffer = ethUtil.toBuffer(hashHex); 139 | let prefix = ethUtil.toBuffer('\u0019Ethereum Signed Message:\n32'); 140 | let hashedHash = ethUtil.sha3(Buffer.concat([prefix, hashHexBuffer])); 141 | let signature = ethUtil.ecsign(hashedHash, ethUtil.toBuffer(privateKey)); 142 | 143 | let signedOrder = orderParams.zrxOrder; 144 | signedOrder['v'] = signature.v; 145 | signedOrder['r'] = ethUtil.bufferToHex(signature.r); 146 | signedOrder['s'] = ethUtil.bufferToHex(signature.s); 147 | signedOrder['feeId'] = orderParams.fee.id; 148 | ``` 149 | 150 | ## Order expiry 151 | 152 | All orders must have a valid expiration date. Min and max expiration times may change based on a number of factors like transaction backlogs and network conditions. You can look up the min and max expiration times by calling the `/v0/expirations` endpoint. 153 | 154 | 155 | The expiration date is the date that the order remains valid to be processed by the 0x contracts on the blockchain. To allow for enough time between trade broadcast and settlement on ethereum, an order will only remain valid on the Paradex orderbook if it has at least `minExpirationMinutes` minutes until its expiration. Therefore if you want an order to appear on the orderbook for 1 minute, you would set the expirationDate to be now() + minExpirationMinutes + 1 minute. Our goal is to eliminate settlement failures where an order reaches its expiration time while sitting in the pending tx pool waiting to be mined. 156 | 157 | You are of course free te set your expirations further in the future and cancel the order for free at any time. Specific details about your order's TTL will be returned to you in the fee object that is returned to you with `v0/orderParams`. 158 | 159 | 160 | ## Errors 161 | 162 | The consumer API will return an HTTP 200 response for most requests. The returned data should be checked for the presence of an error field which indicates that there was a problem processing your request. An example error response is shown below: 163 | 164 | ``` 165 | { 166 | error: { 167 | code: 100, 168 | reason: 'Validation Failed', 169 | validationErrors: [ 170 | { field: 'id', code: 1000, reason: 'id is required' }, 171 | ... 172 | ] 173 | } 174 | } 175 | ``` 176 | All error responses have `code` and `reason` properties. Additionally, validation errors contain an array of the fields that have failed validation. Incorrect nonce errors return the current nonce. Here are the current consumer API error codes: 177 | 178 | | Error Code | Reason 179 | | --------- | --------------------------------------- | 180 | | 100 | Validation failed | 181 | | 101 | Malformed JSON | 182 | | 104 | Invalid API key | 183 | | 105 | Invalid ethereum address | 184 | | 106 | Invalid signature | 185 | | 107 | Invalid nonce | 186 | | 108 | Server Error | 187 | | 109 | Exceeded max decimal places | 188 | | 110 | Unviable: Order fees exceed order value | 189 | | 111 | Region is read-only | 190 | | 112 | Market is suspended | 191 | | 113 | Unverified API Key | 192 | 193 | 194 | Aside from HTTP 200 responses the following HTTP error codes are used by the consumer API. 195 | 196 | | HTTP Code | Reason 197 | | --------- | -------------------------------------------- | 198 | | 404 | Url not found or request type not supported | 199 | | 429 | Too many requests - Rate limit exceeded | 200 | | 500 | Internal Server Error | 201 | 202 | ## Misc 203 | 204 | - All requests and responses are of **application/json** content type 205 | - All addresses are sent as lower-case (non-checksummed) Ethereum addresses with the `0x` prefix. 206 | - Before you can use your API key, you must first prove you own the ethereum address by registering it with the `/verifyAddress` endpoint. 207 | 208 | 209 | # Paradex Consumer API 210 | 211 | ## GET /v0/nonce 212 | `public endpoint` 213 | 214 | Returns your current nonce: 215 | 216 | ``` 217 | { 218 | nonce: 0 219 | } 220 | ``` 221 | 222 | 223 | ## GET /v0/verifyAddress 224 | `private endpoint` 225 | 226 | Proves that you are control the private key associated with the API key that you requested. You only need to call this once. 227 | 228 | ``` 229 | { "success": true } 230 | ``` 231 | 232 | 233 | ## GET /v0/expirations 234 | `public endpoint` 235 | 236 | Returns current min and max expiration time allowed for orders. These values should be considered dynamic and may change with network conditions. The fee object returned from `orderParams` will also convey this expiration information, as it will give you an estimate of when your order will be pruned from the book: 237 | 238 | ``` 239 | { 240 | minExpirationMinutes: 5, 241 | maxExpirationMinutes: 21600 242 | } 243 | ``` 244 | 245 | 246 | ## GET /v0/tokens 247 | `public endpoint` 248 | 249 | Returns a list of token addresses and their corresponding symbol: 250 | 251 | ``` 252 | [ 253 | { 254 | name: 'Wrapped Ether', 255 | symbol: 'WETH', 256 | address: '0xd0a1e359811322d97991e03f863a0c30c2cf029c' 257 | }, 258 | ... 259 | ] 260 | 261 | ``` 262 | ## GET /v0/markets 263 | `public endpoint` 264 | 265 | Returns a list of markets: 266 | 267 | ``` 268 | [ 269 | { 270 | id: '1', 271 | symbol: 'ZRX/WETH', 272 | baseToken: 'ZRX', 273 | quoteToken: 'WETH', 274 | minOrderSize: '0.001', 275 | maxOrderSize: '10000', 276 | priceMaxDecimals: 5, 277 | amountMaxDecimals: 6 278 | }, 279 | ... 280 | ] 281 | ``` 282 | 283 | 284 | ## GET /v0/ohlcv 285 | `public endpoint` 286 | 287 | Reruns OHLCV data: 288 | #### parameters 289 | * market - Symbol of a market 290 | * period - '1m'|'5m'|'15m'|'1h'|'6h'|'1d' 291 | * amount - (Int) How many candles to be returned 292 | 293 | ``` 294 | [ 295 | { 296 | high: '0.710000000000000000', 297 | date: '2017-11-21T18:00:00Z', 298 | volume: '0.760000000000000000000000000000000000', 299 | low: '0.500000000000000000', 300 | open: '0.500000000000000000', 301 | close: '0.710000000000000000' 302 | }, 303 | ... 304 | ] 305 | ``` 306 | 307 | 308 | ## GET /v0/ticker 309 | `public endpoint` 310 | 311 | Returns ticker data for a market: 312 | 313 | #### parameters 314 | * market - Symbol of a market 315 | 316 | ``` 317 | { 318 | bid: '0.004' 319 | ask: '0.005' 320 | last: '0.0045' 321 | } 322 | ``` 323 | 324 | 325 | 326 | ## GET /v0/orderbook 327 | `public endpoint` 328 | 329 | Returns the order book for a given market. The orderbook representation merges orders of the same value to show the overall volume at each value: 330 | #### parameters 331 | * market - Symbol of a market 332 | ``` 333 | { 334 | marketId: 1, 335 | marketSymbol: 'REP/ETH', 336 | bids:[ 337 | { amount: '300', price: '0.004' }, 338 | { amount: '440', price: '0.003' }, 339 | { amount: '500', price: '0.002' }, 340 | ... 341 | ], 342 | asks:[ 343 | { amount: '200', price: '0.005' }, 344 | { amount: '360', price: '0.006' }, 345 | { amount: '445', price: '0.007' }, 346 | ... 347 | ] 348 | } 349 | ``` 350 | 351 | 352 | ## POST /v0/orders 353 | `public endpoint` 354 | 355 | Returns the user's orders: 356 | 357 | #### parameters 358 | * market - Symbol of a market 359 | * state - 'all'|'unknown'|'open'|'expired'|'filled'|'unfunded'|'cancelled' 360 | 361 | ``` 362 | [ 363 | { 364 | orderParams: { 365 | exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093', 366 | maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b', 367 | taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32', 368 | makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', 369 | takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', 370 | feeRecipient: '0x0000000000000000000000000000000000000000', 371 | makerTokenAmount: '10000000000000000', 372 | takerTokenAmount: '20000000000000000', 373 | makerFee: '0', 374 | takerFee: '0', 375 | expirationUnixTimestampSec: '1518124088', 376 | salt: 67006738228878699843088602623665307406148487219438534730168799356281242528500, 377 | ecSignature: { 378 | v: 27, 379 | r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', 380 | s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254' 381 | } 382 | }, 383 | id: 3423, 384 | price: '0.078', 385 | amount: '100', 386 | type: 'buy'|'sell', 387 | market: 'REP/WETH', 388 | orderHash: 'b41664ebbb46b42fbf32fdce8be3c8df66f354a93dd272e62421e4573a8945d8', 389 | state: 'unknown'|'open'|'expired'|'filled'|'unfunded'|'cancelled', 390 | amountRemaining: '75', 391 | closedAt: None, 392 | expiresAt: '2017-11-01T21:24:20Z' 393 | }, 394 | ... 395 | ] 396 | ``` 397 | 398 | 399 | ## POST /v0/viewOrder 400 | `public endpoint` 401 | 402 | #### parameters 403 | * id - id of the order to view 404 | 405 | Returns information about the order identified by the orderId passed in the url: 406 | 407 | ``` 408 | { 409 | orderParams: { 410 | exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093', 411 | maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b', 412 | taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32', 413 | makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', 414 | takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', 415 | feeRecipient: '0x0000000000000000000000000000000000000000', 416 | makerTokenAmount: '10000000000000000', 417 | takerTokenAmount: '20000000000000000', 418 | makerFee: '0', 419 | takerFee: '0', 420 | expirationUnixTimestampSec: '1518124088', 421 | salt: '67006738228878699843088602623665307406148487219438534730168799356281242528500', 422 | ecSignature: { 423 | v: 27, 424 | r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', 425 | s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254' 426 | } 427 | }, 428 | id: 3423, 429 | price: '0.078', 430 | amount: '100', 431 | type: 'buy'|'sell', 432 | market: 'REP/WETH', 433 | orderHash: 'b41664ebbb46b42fbf32fdce8be3c8df66f354a93dd272e62421e4573a8945d8', 434 | state: 'unknown'|'open'|'expired'|'filled'|'unfunded'|'cancelled', 435 | amountRemaining: '75', 436 | closedAt: None, 437 | expiresAt: '2017-11-01T21:24:20Z' 438 | } 439 | ``` 440 | 441 | 442 | ## POST /v0/viewOrderTrades 443 | `public endpoint` 444 | 445 | #### parameters 446 | * id - id of the order whose trades you want to view 447 | 448 | Returns trades and corresponding price adjustments connected with the order identified by the orderId passed in the url: 449 | ``` 450 | [ 451 | { 452 | id: 2, 453 | state: 'pending', 454 | type: 'buy'|'sell', 455 | amount: '10.236319460000000000', 456 | price: '0.073249280000000000', 457 | baseToken: 'REP', 458 | quoteToken: 'ETH', 459 | txHash: None, 460 | completedAt: None, 461 | baseFee: '', 462 | tradingFee: '', 463 | netAmount: '10.236319460000000000', 464 | priceAdjustments: [] 465 | }, 466 | { 467 | id: 1, 468 | state: 'confirmed', 469 | type: 'buy'|'sell', 470 | amount: '0.011986460000000000', 471 | price: '0.073249280000000000', 472 | baseToken: 'REP', 473 | quoteToken: 'ETH', 474 | txHash: '0x1234567891234567891234567890000', 475 | completedAt: '2017-11-14T23:15:18Z', 476 | baseFee: '', 477 | tradingFee: '', 478 | netAmount: '0.011986460000000000', 479 | priceAdjustments: [ 480 | { 481 | id: 2, 482 | state: 'pending', 483 | token: 'REP', 484 | amount: '2.000000000000000000', 485 | completedAt: None, 486 | txHash: '0x234', 487 | feeAdjustment: '0E-18', 488 | netAmount: '2.000000000000000000' 489 | }, 490 | { 491 | id: 1, 492 | state: 'confirmed', 493 | token: 'REP', 494 | amount: '12.000000000000000000', 495 | completedAt: '2017-11-14T23:15:18Z', 496 | txHash: '0x23', 497 | feeAdjustment: '0E-18', 498 | netAmount: '12.000000000000000000' 499 | } 500 | ] 501 | } 502 | ] 503 | 504 | ``` 505 | 506 | 507 | 508 | ## POST /v0/trades 509 | `public endpoint` 510 | 511 | Returns the users trades: 512 | 513 | #### parameters 514 | * market - Symbol of a market 515 | 516 | ``` 517 | [ 518 | { 519 | id: 2, 520 | state: 'pending', 521 | type: 'buy'|'sell', 522 | amount: '10.236319460000000000', 523 | price: '0.073249280000000000', 524 | baseToken: 'REP', 525 | quoteToken: 'ETH', 526 | txHash: None, 527 | createdAt: "2018-03-09T02:50:27Z" 528 | completedAt: None, 529 | baseFee: '', 530 | tradingFee: '', 531 | netAmount: '10.236319460000000000', 532 | priceAdjustments: [] 533 | }, 534 | { 535 | id: 1, 536 | state: 'confirmed', 537 | type: 'buy'|'sell', 538 | amount: '0.011986460000000000', 539 | price: '0.073249280000000000', 540 | baseToken: 'REP', 541 | quoteToken: 'ETH', 542 | txHash: '0x1234567891234567891234567890000', 543 | createdAt: "2018-03-09T02:50:27Z" 544 | completedAt: '2017-11-14T23:15:18Z', 545 | baseFee: '', 546 | tradingFee: '', 547 | netAmount: '0.011986460000000000', 548 | priceAdjustments: [ 549 | { 550 | id: 2, 551 | state: 'pending', 552 | token: 'REP', 553 | amount: '2.000000000000000000', 554 | completedAt: None, 555 | txHash: '0x234' 556 | feeAdjustment: '0E-18', 557 | netAmount: '12.000000000000000000' 558 | }, 559 | { 560 | id: 1, 561 | state: 'confirmed', 562 | token: 'REP', 563 | amount: '12.000000000000000000', 564 | completedAt: '2017-11-14T23:15:18Z', 565 | txHash: '0x23', 566 | feeAdjustment: '0E-18', 567 | netAmount: '12.000000000000000000' 568 | } 569 | ] 570 | } 571 | ] 572 | ``` 573 | 574 | 575 | 576 | ## POST /v0/balances 577 | `public endpoint` 578 | 579 | Returns the users balances: 580 | 581 | ``` 582 | [ 583 | { 584 | id: 1 585 | name: 'REP' 586 | symbol: 'REP' 587 | balance: '1234' 588 | allowance: '1201' 589 | } 590 | ... 591 | ] 592 | ``` 593 | 594 | 595 | 596 | ## POST /v0/orderParams 597 | `private endpoint` 598 | 599 | Create an unsigned 0x compatible order: 600 | #### parameters 601 | * market - Symbol of a market 602 | * orderType - 'buy'|'sell' 603 | * price - price in quote currency 604 | * amount - amount of base currency 605 | * expirationDate - expiration date and time of order in ISO 8601 format 606 | 607 | The expirationDate format is 2017-11-21T18:00:00Z 608 | A valid expirationDate needs to be between now() + min_expiration and now() + max_expiration. Min/max expiration can be obtained by calling the `/v0/expirations` endpoint. 609 | 610 | Returns: 611 | ``` 612 | { 613 | fee: { 614 | id: 'b046140686d052fff581f63f8136cce1', 615 | baseFeeDecimal: '1.697552694864903098033668128', 616 | tradingFeeDecimal: '21.21940868581128872542085161', 617 | secundsUntilPrune: 60, 618 | pruneUnixTimeStamp: 2017-11-21T18:00:00Z 619 | }, 620 | zrxOrder: { 621 | exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093', 622 | expirationUnixTimestampSec: '1518124088', 623 | feeRecipient: '0x0000000000000000000000000000000000000000', 624 | maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b', 625 | makerFee: '0', 626 | makerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', 627 | makerTokenAmount: '22000000000000000', 628 | salt: '54515451557974875123697849345751275676157243756715784155226239582178', 629 | taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32', 630 | takerFee: '0', 631 | takerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', 632 | takerTokenAmount: '10000000000000000', 633 | }} 634 | ``` 635 | 636 | Note that on the fee object returned, it includes the approximate number of seconds that this order will live on the book for, and the approximate timestamp that this order will be pruned. 637 | 638 | 639 | ## POST /v0/order 640 | `private endpoint` 641 | 642 | Creates an order on Paradex by posting a signed 0x compatible order. To get a compatible unsigned order, see the zrxOrder object returned by POST `/v0/orderParams` 643 | The zrxOrder must be signed and the resultant vrs added to the order submission. 644 | The feeId in the order submission is also returned in the `v0/orderParams` endpoint in the fee object. 645 | 646 | #### parameters 647 | 648 | ``` 649 | { 650 | exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093', 651 | expirationUnixTimestampSec: '1518124088', 652 | feeRecipient: '0x0000000000000000000000000000000000000000', 653 | maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b', 654 | makerFee: '0', 655 | makerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', 656 | makerTokenAmount: '22000000000000000', 657 | salt: '54515451557974875123697849345751275676157243756715784155226239582178', 658 | taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32', 659 | takerFee: '0', 660 | takerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', 661 | takerTokenAmount: '10000000000000000', 662 | v: 27, 663 | r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', 664 | s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254' 665 | feeId: hexString 666 | } 667 | ``` 668 | 669 | **Returns** 670 | 671 | ``` 672 | { 673 | status: True, 674 | id: 23425 675 | } 676 | ``` 677 | ## POST /v0/orderCancel 678 | `private endpoint` 679 | 680 | Cancels an order: 681 | #### parameters 682 | * id - id of the order you want to cancel 683 | 684 | **Returns** 685 | ``` 686 | { 687 | status: true|false 688 | } 689 | ``` 690 | 691 | 692 | ## GET /v0/tradeHistory 693 | `public endpoint` 694 | 695 | Gets trade history for a market: 696 | #### parameters 697 | * market - Symbol of a market 698 | * page - optional. page of results (default 1) 699 | * per_page - optional. number of results per page (default 10, max 100) 700 | * since - optional. ISO 8601 start date (e.g., 2018-03-07T16:31:27Z) 701 | 702 | **Returns** 703 | ``` 704 | { 705 | count: 10, 706 | trades: [ 707 | { 708 | "id": 2825, 709 | "created": "2018-03-14T22:19:48Z", 710 | "completed": "2018-03-14T22:21:05Z", 711 | "type": "sell", 712 | "price": "0.0275", 713 | "amount": "25", 714 | "total": "0.6875", 715 | "market": "NMR/WETH", 716 | "state": "confirmed" 717 | }, 718 | { 719 | "id": 2139, 720 | "created": "2018-03-09T02:50:27Z", 721 | "completed": "2018-03-09T02:51:46Z", 722 | "type": "sell", 723 | "price": "0.033", 724 | "amount": "10", 725 | "total": "0.33", 726 | "market": "NMR/WETH", 727 | "state": "confirmed" 728 | }, 729 | ... 730 | ] 731 | } 732 | ``` 733 | --------------------------------------------------------------------------------