# Common Streams
Common streams can provide data from several sources.
Data is not received after opening connection. To receive data you need to send subscription request. Successfully subscribed Client receives the subscription id. You can also unsubscribe from receiving the changes with the subscription id.
There is max connection time limit - 24 hours. Please do not consider this in logic, as the limit may change. The time limit allows to automatically rebalance the loads. The update interval is 100 ms.
Request (MainNet):
wss://matcher.waves.exchange/ws/v0
Request (TestNet):
wss://matcher-testnet.waves.exchange/ws/v0
You can optionally specify query parameters to collect statistics:
a_client - the type of the Client and its version in format: <web|desktop|android|ios>-<version>
a_os - Client OS and its version, for example: Mac OS X 10.15.6, Windows 10, Linux or Android 7
Example of request with parameters (MainNet):
wss://matcher.waves.exchange/ws/v0?a_client=web-1.2.99&a_os=Windows%10%207
# Order Book Updates
You can send request to subscribe to the order book updates.
see base URLs
Request example:
{
"T": "obs",
"S": "WAVES-DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p",
"d": 10
}
In this example:
obs is the type of the message: ob - order book, s - subscribe.
WAVES-DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p is the subscription id that consists of: amount asset-price asset.
10 is the price depth.
The request will have no effect if you are already subscribed to this order book; One connection allows to subscribe to N order books (currently 10). Subscription to order book number N+1 cancels subscription to the 1st one. In such case the Client will receive error message as follows:
The limit of 10 subscriptions of this type was reached. The subscription of Co11Tbj83TeZCnuXrZQwv6Bs4XG2sm1vGQiQ4FLDjJWs-WAVES was stopped
# Possible Errors
RequestArgumentInvalid - request contains invalid arguments, for example, negative depth. Recommendation: check code on the Client side;
AssetPairIsDenied - the asset pair is blocked. You can get more detailed errors, such as AssetBlacklisted, AmountAssetBlacklisted or PriceAssetBlacklisted. Recommendation: check the logic on the Client side and/or tell the Client that the pair is blocked;
AssetPairSameAssets - the amount and price assets are the same. Recommendation: check code on the Client side;
OrderAssetPairReversed - the pair has wrong asset order, meaning that the amount and price asset are mixed up. Recommendation: check code of the Client side;
SubscriptionsLimitReached - max number of subscriptions exceeded. Recommendation: check code on the Client side. Or contact Matcher Server developers;
WavesNodeConnectionBroken - Waves NODE data request error. Recommendation: try more requests;
OrderBookStopped - order book stopped. Usually this happens when the pair is removed from the exchange or the order book is removed;
Balancing - Matcher Server is currently doing balancing of connections and the connection was closed. Recommendation: reconnect.
# Incoming Data
When the snapshot is received it contains the specified order book of the set depth - the number of returned sell/buy order price levels. If the order book is empty, an empty JSON object will be returned;
When you receive the updates please note the following:
If you received an update that has amount = 0 and the level (price) that you have in your local state, such level should be deleted.
If you received an update that has amount = 0 and the level (price) that you do not have in your local state, such level update should be ignored. Such case can happen if the order had been placed and completed by the level in the interval between websocket messages.
For example, somebody placed sell order by the price 16.95 in the interval between websocket messages - as a result, the amount level increased by the amount of the order. Then somebody completed the order - as a result, the amount of the level became 0. Then you received an update telling that "at price=16.95 level the amount is now 0".
Last trade is always received as a whole, as it is indivisible entity and it has no state that changes over time, it either existed or not.
Subscription Id is always sent.
Example:
{
"T": "ob",
"_": 1585148910776,
"S": "WAVES-DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p",
"U": 0,
"a": [ // asks (sell orders) sorted by price in ascending order
[
"0.12001", // price
"1001.00000001" // amount
],
...
],
"b": [ // bids (buy orders) sorted by price in descending order
[
"0.10001", // price
"997.97226" // amount
],
...
],
"t": [ // last trade
"0.10001", // price of the last trade
"997.97226", // amount of the last trade,
"BUY" // the side of the last trade: BUY | SELL | buy | sell. Lowercase or uppercase is supported
],
"s": [ // pair settings
"r": { // restrictions
// [min, step, max]
"a": ["0.00000001", "0.00000001", "1000000000"], // amount
"p": ["0.00000001", "0.00000001", "1000000"] // price
},
"m": { // matching settings on this pair
"t": "0.000001" // tick size
}
]
}
In this example:
ob is the type of the message.
1585148910776 is Unix timestamp of update in milliseconds. This field is only for debugging.
WAVES-DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p is the subscription id.
0 is the update id.
See other descriptions in the example.
# Address Updates
You can send request to subscribe to the address updates.
see base URLs
Request example:
{
"T": "aus",
"S": "3N93cuB7hDLhpg8n6QpyV7vbWaj5qwBXDF4",
"t": "jwt",
"j": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzaWciOiIzamRBeTg2WTVKSzg3RWVCM1pqdFdhTWJXUmYyOGlFUThmNmY0NGttQXRBRVlOWDJzbjN2V2taVExFb291WEFFdjF2Y3FqZXZid2p1eXRmeWJNdEVCVDNkIiwibmIiOiJXIiwidXNlcl9uYW1lIjoiNUE2TkJ4eTJNWXN5cmNuemgyVDdncEZoS0JVRnRtVXNTb0pNRHA3OExlcnMiLCJzY29wZSI6WyJnZW5lcmFsIl0sImx0IjoxNzY0LCJwayI6IjVBNk5CeHkyTVlzeXJjbnpoMlQ3Z3BGaEtCVUZ0bVVzU29KTURwNzhMZXJzIiwiZXhwIjoxNTg4MDU0MDg3LCJqdGkiOiJkNWM5M2Y2ZS05YTEwLTQ4ZTYtOTRkYi05NzhjYmI4MzgxMWUiLCJjaWQiOiJkZWZhdWx0LWNsaWVudCJ9.3Lwt0Akq2Xeg_UaDJHXlOq-D4kwpfdpMCTNuDG0IEMg"
"b": {
"f": ["-nft"]
}
}
In this example:
aus is the type of the message: au - address updates, s - subscribe.
3N93cuB7hDLhpg8n6QpyV7vbWaj5qwBXDF4, is the subscription id: the account address.
jwt is the auth type. Currently only "jwt" is available.
j fields contains JWT auth token.
b field contains options for balances.
f field contains filters. Currently only NFTs ("-nft" value) can be filtered out in the balances.
- You can get authentication token in the authentication service;
- The subscription is cancelled when the auth token expires;
- One connection allows to subscribe to N addresses (currently 10). Successful subscription to address number N+1 cancels subscription to the 1st one. In such case the Client will receive error message as follows:
The limit of 10 subscriptions of this type was reached. The subscription of 3N9zmtMGwnk8ZY3T3RZGDUoXYymtDYJNJzN was stopped
- You can extend subscription by sending request with active subscription and updated token. In such case the Client will not receive snapshot.
- The duration of subscription does not effect the duration of connection. You can not extend subscription (without reconnecting) for more than 24 hours.
# Possible Errors
SubscriptionAuthTypeUnsupported - the specified type of authentication is not supported. Recommendation: check code on the Client side;
JwtBroken - the provided token is not JWT. Recommendation: check code in the Client side, the token must be taken from the authentication service;
SubscriptionTokenExpired - token expired. Recommendation: check code on the Client side, token must not me expired;
JwtCommonError - other JWT errors. Recommendation: check code on the Client side, the token must be taken from the authentication service;
JwtPayloadBroken - unable to parse payload. Recommendation: check code on the Client side, the token must be taken from the authentication service;
TokenNetworkUnexpected - the provided token is not supported by the network. Recommendation: check code on the Client side, the token must be supported by the network;
InvalidJwtPayloadSignature - invalid signature in the token payload. Recommendation: check code on the Client side, the token must be taken from the authentication service;
AddressAndPublicKeyAreIncompatible - the token owner is trying to subscribe to another address with the token. Recommendation: check code on the Client side;
SubscriptionsLimitReached - max number of subscriptions is exceeded. Recommendation: check code on the Client side. Or contact Matcher Server developers;
Balancing - Matcher Server is currently doing balancing of connections and the connection was closed. Recommendation: reconnect.
# Incoming Data
When the snapshot is received it contains:
Current balances of all the assets that the user has in a form of two elements of the array:
Tradable - is the available (opens new window) balance of the account (on the NODE) minus balance reserved in open orders and expenses in UTX pool. This balance is used by the Matcher for validation;
Reserved - the assets of the Client that can be spent during execution of all the open orders, including Matcher fee;
All active (not cancelled and not filled) orders;
New users that have no WAVES or other assets do not receive balances:
{
"T": "au",
"_": 1585148910776,
"S": "3N93cuB7hDLhpg8n6QpyV7vbWaj5qwBXDF4",
"U": 0
}
In this example:
au is the type of the message, a - address, u - updates.
1585148910776 is Unix timestamp of update in milliseconds. This field is only for debugging.
3N93cuB7hDLhpg8n6QpyV7vbWaj5qwBXDF4 is the subscription id.
0 is the update id.
When the updates are received they contain:
- Updated balances. If the balances did not change, this field is not received;
- Updated orders. The update can contain not all the fields. For example, price asset and amount asset will not be received if the order was cancelled;
- Information about executed matching transactions when an order gets Filled or Partially filled status (when there are executed matching transactions). There can be no transactions at all if the order transitioned to Filled status because it became unmatchable (meaning that the amount is too small to be matched). Triggered status only works with new unfilled version 4 orders;
- Information about executed orders telling if an order was "maker" or "taker" is indicated in the mt field that can either have m value (if the order was maker) or t (if the order was taker);
- Subscription Id is always sent.
Example:
see the descriptions of the fields in the example.
{
"T": "au", // the type of the message
"_": 1585148910776, // unix timestamp of update in milliseconds. This field is only for debugging
"S": "3N93cuB7hDLhpg8n6QpyV7vbWaj5qwBXDF4", // subscription id
"U": 1, // update id
"b": { // balances
"DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p": [// asset id
"716.356", // tradable
"56.85" // reserved
]
...
},
"o": [ // Orders
{
"i": "89CyqyWeQmqG9QRdoXnYUGrV27eTNjy6HEDy3jBq8zDU", // order id
"t": 1579697243653, // order timestamp
"A": "WAVES", // amount asset
"P": "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p", // price asset
"S": "sell", // order side: BUY | SELL | buy | sell. Lowercase or uppercase is supported
"T": "limit", // order type: LIMIT | MARKET | limit | market. Lowercase or uppercase is supported
"p": "0.84", // order price
"a": "176.3002", // order amount
"f": "0.003", // order fee
"F": "8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS", // fee asset
"s": "PartiallyFilled", // order status: ACCEPTED | FILLED | PARTIALLY_FILLED | CANCELLED | Accepted | PartiallyFilled | Filled | Cancelled | Triggered. Lowercase or uppercase is supported
"q": "15.01", // the current filled amount, including this and all previous matches
"Q": "0.001", // the current filled fee, including this and all previous matches
"r": "0.835", // average filled price among all trades with maximum priceDecimals digits after point
"E": "12.53335" // total executed price assets.
"m": [ // information about matching transactions
{
"i":"8Ktd2RvW2TiFU1Q8LNtu25uxj6t1r2itk4huG75H2DFD", // match transaction id
"t":1579699001581, // transaction timestamp
"p":"0.8925", // execution price
"A":"46.044", // executed amount asset quantity
"P":"41.09427" // executed price asset quantity
"mt": "t" // maker or taker order; "m" for maker, "t" for taker
},
...
]
},
...
]
}
# FAQ
Q: Why only active orders are sent?
A: There is currently a limit of 100 last closed orders that are saved, but this limit might get removed (for example with postgresql
). There is currently no solution to implement the receiving of all the thousands of the orders in the snapshot.
Such large history would require filters. So that initiating WebSockets you will need to specify filters for sending the snapshot. That would cause logic duplication that has to be implemented in REST API.
Ideologically WS implies realtime operation, which is not necessary for closed orders, since the closed orders will never get any update and they do not need snapshots.
Also, such functionality is not supported by other exchanges (only Bitfinex has snapshot) - only active orders are received.
Q: Why the address is used as subscription id, but not public key?
A: While the address is generated, the network byte is used. In other words, the account with the same seed in different networks will have:
- Different address;
- The same private and public key;
- The same signature used for signing the set of bytes in different networks;
Q: What are "maker" and "taker" orders?
A: Maker order is a limit order that exists in the order book. Taker order is a limit/market order that is received by the matcher to be matched with the orders in the order book.
# Rates Updates
You can send request to subscribe to the rates updates.
see base URLs
Request example:
{
"T": "rus",
"S": "ru"
}
In this example:
rus is the type of the message: ru - rates updates, s - subscribe.
ru is the subscription id: all rates updates.
# Incoming Data
When the snapshot is received it contains all the current rates;
When the updates are received they contain updated rates, "-1" value means that the rate was deleted. Currently the updates are received as 1 message for every updated asset;
Example:
{
"T":"ru",
"_":1600163991902,
"U":0,
"R":{
"8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS":"0.00041863",
"WAVES":"1"
}
}
In this example:
ru is the message type, ru - rates updates.
1600163991902 is Unix timestamp of update in milliseconds. This field is only for debugging.
0 is the update Id, 0 means rates snapshot
# FAQ
Q: Why there is no way to send all the updated rates in one single message? Why send several messages?
A: Currently Mather does not support sending rates in batches, only one asset at a time. In the future we plan to implement sending several rates in batches.
# Unsubscribe
You can unsubscribe to stop receiving the changes with the subscription id.
Request example:
{
"T": "u",
"S": "3N93cuB7hDLhpg8n6QpyV7vbWaj5qwBXDF4"
}
In this example:
u is the type of request u - unsubscribe.
3N93cuB7hDLhpg8n6QpyV7vbWaj5qwBXDF4 is the subscription id.
The request will have no effect if you have no subscription;
There is no need to wait for reply for Server;