TDEX: API

Introduction

We provide simple and convenient REST API for access Tokenomica DEX.

Using this API you can do following:

Tokenomica DEX uses Waves Matcher as a part of its trading engine.

Get Started

You will need following to start:

  1. Programming language and execution environment of your choice. In this document we use Javascript (Node.JS) with waves-transactions library
  2. Your seed phrase, stored in Waves Keeper (only for orders management)
  3. Your public key, stored in Waves Keeper as well (only for orders management)
  4. Public key of matcher (only for orders management). It can be obtained by calling https://dex.tokenomica.com/matcher/ (without parameters)

Public endpoints

Tokenomica provides 2 public endpoints:

Endpoint Purpose Type Prices
https://dex.tokenomica.com/matcher/ Placing, cancelling orders, tracking orders execution. Private Normalized to integer (see below)
https://vfa.tokenomica.com/api/v1/exchange/ Fetching historical, statistical and market data. Public Regular (double).

Exchange status and general information

You should start with obtaining exchange general information, which includes list of available assets, pairs and their statuses.
It's as simple as request following URL:

GET https://vfa.tokenomica.com/api/v1/exchange/info

As a result you'll receive JSON with list of assets and pairs. Example:

{
    "assets": {
		"BTC": {
		  "assetTicker": "BTC",
		  "assetName": "Bitcoin",
		  "assetId": "9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd",
		  "url": "https://bitcoin.org/",
		  "logo": "https://vfa.tkn.es/img/assetsLogo/bitcoin.svg",
		  "decimals": 8,
		  "depositsEnabled": true,
		  "withdrawalsEnables": true
		},
		...
	},
	"pairs": {
		"WAVES/BTC": {
		  "amountAssetTicker": "WAVES",
		  "amountAssetName": "Waves",
		  "amountAssetId": "WAVES",
		  "priceAssetTicker": "BTC",
		  "priceAssetName": "Bitcoin",
		  "priceAssetId": "9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd",
		  "tradingEnabled": true
		},
		...
	}
}

When working with orders you should always use an ID of asset, not ticker and/or name. See "Trading" chapter below

Market and Historical data

For each pair you can get current market data (order book) and statistical information (trading volumes, etc).

Current market depth

GET https://vfa.tokenomica.com/api/v1/exchange/orderbook/{amountAsset}/{priceAsset}

where priceAsset and amountAsset are the ones (IDs or Tickers) from list of trading pairs (see above).
For example, this will bring current market depth for Waves/BTC:

GET https://vfa.tokenomica.com/api/v1/exchange/orderbook/WAVES/9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd

You can use tickers for convenience:

GET https://vfa.tokenomica.com/api/v1/exchange/orderbook/Waves/BTC

As a result you'll receive JSON with market data for desired pair:

{
  "timestamp": 1560889846129,
  "pair": {
    "amountAssetTicker": "WAVES",
    "amountAssetName": "Waves",
    "amountAssetId": "WAVES",
    "priceAssetTicker": "BTC",
    "priceAssetName": "Bitcoin",
    "priceAssetId": "9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd"
  },
  "bids": [
    {
      "amount": 44.35675864,
      "price": 0.00025855
    },
    {
      "amount": 35.92047907,
      "price": 0.00025835
    },
	...
  ],
  "asks": [
    {
      "amount": 25.41708391,
      "price": 0.00025913
    },
    {
      "amount": 35.74972729,
      "price": 0.00025928
    },
	...
  ]
}

bids and asks are the arrays of price levels with amounts placed at these levels. Amounts are in amountAsset (Waves for Waves/BTC, ETH for ETH/BTC, and so on).
bids are sorted ascending, asks are sorted descending. So, the 0-st bid always represent the best bid available (the best price at which you cal sell), and 0-st ask - the best price at which you can buy.
In the example above you can sell 44.35675864 Waves at the best price 0.00025855, and buy the 25.41708391 * 0.00025913 = 0.00658633 BTC at the best price (0,00025913).

Last trades

You can get the list of last trades (last deals) for desired pair.

GET https://vfa.tokenomica.com/api/v1/exchange/trades/{amountAsset}/{priceAsset}[/{limit}]

where priceAsset and amountAsset are the ones (IDs or Tickers) from list of trading pairs (see above).
For example, this will bring trades list for Waves/BTC:

GET https://vfa.tokenomica.com/api/v1/exchange/trades/WAVES/9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd

You can use tickers for convenience:

GET https://vfa.tokenomica.com/api/v1/exchange/trades/Waves/BTC

As a result you'll receive JSON with trades list for desired pair. Example:

{
  "timestamp": 1560889844968,
  "pair": {
    "amountAssetTicker": "WAVES",
    "amountAssetName": "Waves",
    "amountAssetId": "WAVES",
    "priceAssetTicker": "BTC",
    "priceAssetName": "Bitcoin",
    "priceAssetId": "9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd"
  },
  "trades": [
    {
      "amount": 1.28894385,
      "price": 0.00025877,
      "timestamp": 1560889819424
    },
    {
      "amount": 0.85025107,
      "price": 0.0002589,
      "timestamp": 1560889786255
    },
	...
  ]
}

You can use optional limit parameter to reduce the result set. Please note that engine will not return more than 100 last trades.

Statistical data

For supported trading pairs you can obtain last deal price, trading volume and other useful information.

GET https://vfa.tokenomica.com/api/v1/exchange/pairs

As a result you'll receive JSON with statistical data for all pairs supported:

{
  "WAVES/BTC": {
    "amountAssetTicker": "WAVES",
    "amountAssetName": "Waves",
    "amountAssetId": "WAVES",
    "priceAssetTicker": "BTC",
    "priceAssetName": "Bitcoin",
    "priceAssetId": "9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd",
    "firstPrice": 0.0002639,
    "lastPrice": 0.00025877,
    "low": 0.00025877,
    "high": 0.00026564,
    "weightedAveragePrice": 0.000261529928304029,
    "volume": 2992.23778545999,
    "quoteVolume": 0.782559733499958,
    "txsCount": 2707
  },
  "ETH/BTC" : {
	...
  },
 ...
}

Here's the explanation of the most important fields:

Fields Description
lastPrice The most recent price of trading pair
volume Volume for the last 24h in amount (base) asset. In case of "ETH/BTC" it's ETH.
quoteVolume Volume in terms of priceAsset (BTC for "ETH/BTC")
txsCount Number of deals for the last 24h

Trading

Currently only limit orders are supported.

Important notes

Price normalization

All prices in the orders data are presented in a special integer form, depending on the precision of quotations of assets of the pair. It differs from the marketdata representation (where prices are always double).
To get the price in objective (double) value, you need to divide the order's integer price representation by 10^(8 + priceAssetDecimals - amountAssetDecimals).
For example, the integer representation of Waves/BTC price is 30074. Both Waves and BTC have precision of 8 digits. So, the objective price for Waves/BTC wolud be: 30074 / 10^(8 + 8 - 8) = 30074 / 10^8 = 30074 / 100000000 = 0.00030074‬
And vice versa, if we want to place an order according to Waves/BTC at a price of 0.0005, it is necessary to perform the inverse operation to get an integer representation of the price: 0.0005 * 10^(8 + 8 - 8) = 0.0005 * 100000000 = 50000

Amount and fees normalization

All amounts are presented in integer form, depending on the precision of quotations of asset.
To get the price in objective value, you need to divide the integer amount representation by 10^assetDecimals
For example, the integer representation of Waves amount is 10000000. Waves has precision of 8 digits. So, the objective amount would be: 10000000 / 10^8 = 10000000 / 100000000 = 0.1
The mentioned above applies to fees as well. For example, 0.011 fee (in Waves) would be represented as 1100000 in integer, and vice versa.

Placing order

POST https://dex.tokenomica.com/matcher/orderbook

A user initiates his willingness to buy or sell assets by creating, signing and sending a Limit Order request. The order should contain the following fields:

Request parameters

Field name Description Example
id Uinque order ID (alphanumeric) 7dqsEqLnniYaEctKhuAdXq57usUs693a5hyVjfZ5rdAh
senderPublicKey Public key of order creator related to the address from which to send/receive assets 6FQGWUCRvxriuKimCqfP9yxFxVpvouYoYhEELzo9nHXr
matcherPublicKey Public key of matcher to whom user authorize to match his order E3UwaHCQCySghK3zwNB8EDHoc3b8uhzGPFz3gHmWon4W
orderType buy or sell buy
assetPair / amountAsset amountAsset in desired pair (ID of asset) WAVES
assetPair / priceAsset priceAsset in terms of pair (ID of asset) 9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd
price Normalized price of limit order 50000
amount Amount in amountAsset 10000000
timestamp Current timestamp 1560506906085
expiration Max time of open order to live before execution. Currently, max is 1 month 1563012506085
matcherFee Fee which goes to Matcher for order matching (execution) 1100000
proofs[] Signature of all order data created by private key of sender

See Order in waves-transactions npm for example of output JSON (and of construnction order using library).

Response

API returns JSON object. For the example above it would be:

{
  "result": true,
  "body": {
    "status": "OrderAccepted",
    "message": {
      "version": 2,
      "id": "7dqsEqLnniYaEctKhuAdXq57usUs693a5hyVjfZ5rdAh",
      "sender": "3PJJbWup1qJeoGuL5LbxZioRsy2MFcRQAx1",
      "senderPublicKey": "6FQGWUCRvxriuKimCqfP9yxFxVpvouYoYhEELzo9nHXr",
      "matcherPublicKey": "E3UwaHCQCySghK3zwNB8EDHoc3b8uhzGPFz3gHmWon4W",
      "assetPair": {
        "amountAsset": null,
        "priceAsset": "9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd"
      },
      "orderType": "sell",
      "amount": 10000000,
      "price": 50000,
      "timestamp": 1560506906085,
      "expiration": 1563012506085,
      "matcherFee": 1100000,
      "signature": "5wtx3kw2enrki7w7oNeruMCq1g8x42UJWByHRnsm5UB8mz9jsuika8Xbp68ESoF2yVSvSx2hqxYujqwsSPo5woEg",
      "proofs": [
        "5wtx3kw2enrki7w7oNeruMCq1g8x42UJWByHRnsm5UB8mz9jsuika8Xbp68ESoF2yVSvSx2hqxYujqwsSPo5woEg"
      ]
    }
  },
  "error": ""
}

In case result is false the error field would contain description of error. For example:

{
  "result": false,
  "body": {},
  "error": "StatusCodeError: 400 - {\"status\":\"OrderRejected\",\"message\":\"Order matcherFee should be >= 700000\"}"
}

Canceling order

POST https://dex.tokenomica.com/matcher/orderbook/{amountAsset}/{priceAsset}/cancel

amountAsset and priceAsset (both are IDs) are required, despite the fact that this information is contained in the order

Request parameters

Field name Description Example
orderId ID of previously created order 7dqsEqLnniYaEctKhuAdXq57usUs693a5hyVjfZ5rdAh
sender Public key of order creator related to the address from which to send/receive assets 6FQGWUCRvxriuKimCqfP9yxFxVpvouYoYhEELzo9nHXr
signature Signature of all data above created by private key of sender

Here's the example of canceling order using waves-transactions:

const { cancelOrder } = require('@waves/waves-transactions');
const request = require('request-promise');

const params = {
	orderId: '7dqsEqLnniYaEctKhuAdXq57usUs693a5hyVjfZ5rdAh',
	sender: '6FQGWUCRvxriuKimCqfP9yxFxVpvouYoYhEELzo9nHXr'
};

let myOrderCancelRequest = cancelOrder(params, seed);	//	Keep seed in secure place

const options =
		{
			uri : 'https://dex.tokenomica.com/matcher/orderbook/WAVES/9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd/cancel',
			method: 'POST',
			json: myOrderCancelRequest
		};

let body = await request(options);

Response

API returns JSON object. For the example above it would be:

{
  "result": true,
  "body": {
    "status": "OrderCanceled",
    "orderId": "7dqsEqLnniYaEctKhuAdXq57usUs693a5hyVjfZ5rdAh"
  },
  "error": ""
}

In case result is false the error field would contain description of error.

Order status

GET https://dex.tokenomica.com/matcher/orderbook/{amountAsset}/{priceAsset}/{orderId}

For example:

GET https://dex.tokenomica.com/matcher/orderbook/WAVES/9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd/AJF2byi1wpBk7C7C4VWGM1beBasPwYKC5EiLAvwV7NRa

returns

{"status":"Accepted"}

When order is canceled, result would be like following:

{
"status":"Cancelled",
"filledAmount":0
}

where filledAmount indicates part of order which was filled (partially) before cancelation.
For executed (filled) order result would be as following:

{
"status":"Filled",
"filledAmount":10000000
}

List of orders

Get list of active / executed / canceled orders

GET https://dex.tokenomica.com/matcher/orderbook/{publicKey}?activeOnly=(true|false)

Two additional headers needed to perform this request:

Header Description Example
Timestamp UNIX timestamp (current) 1560517617362
Signature Signature of concatenated publicKey + timestamp 5EFG9fFBEwQA9xwTEXZ8WYPgeeYqFYktgfpqV6ucMXuF49pemsyn5k1oifaPKGSHonXMbhb1KZXyZ2WzjqwkfBhr

Here's the example of making such an request

const {SeedAdapter, SIGN_TYPE} = require('@waves/signature-adapter');
const request = require('request-promise');

async function getMatcherOrdersRequest(timestamp, seed) {
	const adapter = new SeedAdapter(seed);
	const signable = adapter.makeSignable({
		type: SIGN_TYPE.MATCHER_ORDERS,
		data: {
			timestamp,
			senderPublicKey: await adapter.getPublicKey()
		}
	});
	await signable.sign();
	return await signable.getSignature();
}

let timestamp = (new Date).getTime();
let seed = '....';
let publicKey = '6FQGWUCRvxriuKimCqfP9yxFxVpvouYoYhEELzo9nHXr';

let signature = await getMatcherOrdersRequest(timestamp, seed);

const options =
{
	uri : 'https://dex.tokenomica.com/matcher/orderbook/'+publicKey+'?activeOnly=false',
	method: 'GET',
	json: true,
	headers: {
		'Timestamp' : timestamp,
		'Signature' : signature
	}
};

let body = await request(options);

Response

API returns JSON object. For the example above it would be:

[
  {
    "id": "BG6r5PgzQRaeAQn9w95cdkBM4Csorx43Es8xRNcsYJDq",
    "type": "sell",
    "amount": 10000000,
    "price": 20000,
    "timestamp": 1560509647257,
    "filled": 10000000,
    "status": "Filled",
    "assetPair": {
      "amountAsset": null,
      "priceAsset": "9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd"
    }
  },
  {
    "id": "AJF2byi1wpBk7C7C4VWGM1beBasPwYKC5EiLAvwV7NRa",
    "type": "sell",
    "amount": 10000000,
    "price": 50000,
    "timestamp": 1560508990227,
    "filled": 0,
    "status": "Cancelled",
    "assetPair": {
      "amountAsset": null,
      "priceAsset": "9SxLVHaEGTeEjRiAMnEw74YWWndQDRw8SZhknK9EYoUd"
    }
  },
  ...
]