Skip to content

Latest commit

 

History

History
973 lines (809 loc) · 32.6 KB

orders.mediawiki

File metadata and controls

973 lines (809 loc) · 32.6 KB

Client Order Management

Table of Contents

This section describes the steps required of the client to place an order, and the interactions between the client and server to execute an order once a match has been found. See the atomic settlement section for a high-level overview of the settlement process.

There are three available types of order.

  • Limit orders are used to buy or sell a specified amount of an asset at a rate no higher (buy) or lower (sell) than a specified price.
  • Market orders are used to buy or sell a specified amount of an asset at the best price available.
  • Cancel orders are used to remove standing limit orders from the order book.
The order book holds only limit orders with time in force standing that have not completely filled or been canceled. All other orders are only valid for one epoch match cycle.

Connection Persistence

Regardless of connection status, if a client does not respond to their preimage request, they are in violation of rule 1 and subject to penalty.

If a client's connection is lost during match negotiation, the client is expected to reconnect and complete settlement. Once a match is made, a client is always subject to violation of rule 2 via the broadcast timeout.

Order Book Subscriptions

An order book can be viewed and tracked by subscribing to a market.

Request route: orderbook, originator: client

payload

field type description
base int the base asset ID
quote int the quote asset ID

The response will contain the complete market order book. The order book and all updates include a sequence ID, which increments by +1 whenever the DEX accepts, removes, or modifies an order. The client is responsible for tracking the sequence ID to ensure all order updates are received. If an update appears to be missing, the client should re-subscribe to the market to synchronize the order book from scratch.

Response

payload

field type description
marketid string A unique market identifier, the market ID.
seq int A sequence ID
epoch int the current epoch
orders [object] A list of Order objects (described below)

JSON Order object

field type description notes
seq int A sequence ID superceded in orderbook response
marketid string the market ID
oid string the order ID
side string "b" for buy, "s" for sell epoch_order, book_order
qty int order size (atoms) epoch_order, book_order
rate int price rate. message-rate encoding only set on limit orders
tif string time in force. one of "i" for immediate or "s" for standing only set on limit orders
time int the order's UNIX timestamp epoch_order, book_order
com string the order commitment epoch_order only
otype string "l" for limit, "m" for market, "c" for cancel epoch_order only
epoch int the order's epoch index epoch_order only
target string target order ID only set on cancel orders (epoch_order only)

Changes to the order book will be received from the DEX as a stream of notifications. The action to be taken depends on the route according to the following table. The payload for all three routes is an Order object.

route action
book_order add (or update) the order to the order book
epoch_order add the order to the epoch queue
unbook_order remove the order from the order book

Additionally, there is a notification for updating the remaining quantity of an order. This notification is sent when a booked order partially fills and remains on the book with a reduced matchable quantity.

Notification route: update_remaining, originator: DEX

payload

field type description
seq int A sequence ID
marketid string The market identifier
oid string The order ID
remaining int remaining quantity (atoms)

At the beginning of the matching cycle, the DEX will publish a list of order preimages, the seed hash used for order sequencing, and the commitment checksum, which together can be used to independently verify matching.

Notification route: match_proof, originator: DEX

payload

field type description
marketid string the market ID
epoch int the epoch index for which the cycle occurs
preimages [string] list of order preimages for the epoch
misses [string] list of order IDs for which preimages were not received, so were not included in sorting or matching
csum string the commitment checksum
seed string epoch queue shuffling seed

A client can unsubscribe from order book updates without closing the WebSocket connection.

Request route: unsub_orderbook, originator: client

payload

field type description
marketid string the market ID

result: boolean true on success.

Order Preparation

As part of the order, the client must demonstrate control of funds. This is accomplished by supplying information and a signature for each coin that will be spent. The client covers the backing fees associated with the inputs spending their own coins.

In addition, the client must show the ability to cover base fees for any initialization transactions that will be generated. The client must show that they have the funds to cover all fees for the worst-case scenario, which is single-lot matches for the entire order. In practice, large orders will rarely pay the total of the base fees because many of the matches will be more than a single-lot.

Calculating Transaction Fees

The base fees cover transaction fees associated with making initialization transactions for every match in the order.

For asset Z, a base fee ratio, Rz is calculated based on the lot size, l (units Z), a fee rate, r (Z/byte), and a transaction size, s (bytes). s is pre-calculated based on a standard initialization transaction.

File:images/fee_max_ratio.png

The base fee ratio is a constant until the DEX operator changes one of its factors.

The base fees, fbase (units Z) can be calculated from Rz and the order quantity, Q.

File:images/base_fees.png

The base fees scale linearly with order size, but the actual realized portion of the base fees, ffin, can only be known to fall within a range r s ≤ ffin ≤ fbase .

The client also covers the backing fees associated with spending their backing coins, fcoin. The client must know how to calculate the script sizes to assess fees. The DEX will verify the coin sum before accepting the order.

Coin Preparation

With the exception of market buy orders, which are detailed below, for an order of quantity Q, the sum value of the selected coins, V, must satisfy the relation (with fees)

File:images/coin-sum.png

There may be types of coins which are not supported by the asset's DEX implementation. Asset developers should make coin-spending limitations clear to wallet users.

As part of the order, the client will submit a list of Coin objects.

JSON Coin object

field type description
coinid string hex-encoded coin ID
pubkeys [string] array of hex-encoded pubkeys which spend the coin
sigs [string] array of signatures of Blake-256 hashes of the serialized coin IDs
redeem string hex-encoded redeem script for P2SH. empty for P2PKH

In order to enable multi-signature support, more than one pubkey can be submitted. If more than one pubkey is submitted, there should be a signature for each one. The data is signed with the private key(s) corresponding to the pubkeys. The pubkeys themselves must correspond with addresses payable by the coin's pubkey script (or corresponding redeem script).

Order Commitment

As part of every submitted order, the client should submit a cryptographic commitment. To generate a commitment, the client creates a random 32-byte sequence, the preimage. The commitment is the Blake-256 hash of the preimage. Every order must be assigned a unique commitment, therefore preimages cannot be reused. They should be generated with a cryptographically-secure pseudo-random number generator.

The server will reject any zero-valued commitment as well as the specific commitment generated from hashing a zero-valued preimage. The server can also reject a commitment that has already been used for any previous order. Depending on server policy, the historical commitment duplicate search may be limited to only recent commitments and/or commitments received for orders on a specific market. Assuming that a cryptographically-secure PRNG is used to generate preimages, rejection should realistically be impossible.

At the expiration of the epoch, the server sends a preimage request for each order that is eligible for matching. The client responds with their preimage(s). If the client fails to respond to their preimage requests, or if their preimage response does not hash to their order commitment, the order is not matched and the client is considered in violation of rule 1.

The preimages are used as the inputs to the shuffling algorithm to determine matching order. Before matching commences, the preimages are broadcast in the match_proof message.

Order Signing

All orders must be signed by the client and the server. The basic signing procedure will involve serializing order data into a byte array following a specific procedure that can be replicated on the server. The serialized data is then signed using the client's private account key.

All integer encoding for all serialized structures is big endian.

All order serializations have common prefix fields.

Prefix fields and serialization

field size (bytes) JSON type description
accountid 32 string hex-encoded client account ID
base 4 int the base asset ID
quote 4 int the quote asset ID
ordertype 1 int the type of order. limit = 1, market=2, cancel=3
tclient 8 int the client's UNIX timestamp (milliseconds)
tserver 8 int the server's UNIX timestamp (milliseconds). zero for client signature
com 32 string hex-encoded cryptographic commitment

Order ID

The order serialization is used to create a unique order ID. The ID is defined as the Blake-256 hash of the serialized order, including the non-zero server's timestamp. The client does not know the order ID when submitting, but should independently verify the ID after parsing the server's response.

Because the order ID includes the server's timestamp, the order ID itself provides a checksum to ensure that order information is properly transmitted. The response to all order submissions is an order receipt, which includes the timestamp.

Order receipt

result

field type description
sig string server hex-encoded signature of the serialized order, after adding the DEX timestamp
orderid string the order ID
tserver int the server's UNIX timestamp (milliseconds)

The client should use the server's timestamp to create a serialized order and independently verify the order ID. The serialized order is also the message for the server's signature.

Order Types

Limit Order

Limit orders are for the trade of assets at a rate no higher (buy) or lower (sell) than a specified price. The client may specify the time in force of a limit order as one of: (a) standing, which remains on the books until filled or canceled, or (b) immediate, which can complete execution wholly or partially unfilled. As such, the immediate option is intended for limit orders with a price that crosses the spread (i.e. a taker rather than a maker). The ordersize must be an integer multiple of the asset's lot size.

Request route: limit, originator: client

payload

field type description
9 prefix fields
side int buy = 1, sell = 2
ordersize int order size (atoms)
rate int price rate. message-rate encoding
timeinforce int standing = 1, immediate = 2
coins [Coin] array of funding coins
address string address where the matched client will send funds
sig string client hex-encoded signature of the serialized order, with tserver = 0

Limit order serialization

field size (bytes) description
prefix 99 the order prefix
coin count 1 The number of funding coins
coin data coin length x count sequence of coin IDs
side 1 1 for buy, 2 for sell
quantity 8 quantity to buy or sell (atoms)
rate 8 price rate. message-rate encoding
time in force 1 1 for standing, 2 for immediate
address varies client's receiving address

result

field type description
sig string server hex-encoded signature of the serialized order, after adding the DEX timestamp
server time int the server's UNIX timestamp (milliseconds)

Market Order

A market order is an order to buy or sell an asset at the best available market price. The request payload fields are similar to a limit order, but without the rate field or timeinforce fields.

Market orders cannot be canceled. Any portion of the requested quantity that does not match immediately (during the epoch match cycle) is left unfilled.

Request route: market, originator: client

payload

field type description
9 prefix fields
side int buy = 1, sell = 2
ordersize int order size (atoms)
coins [Coin] array of funding coins
address string address where the matched client will send funds
sig string client hex-encoded signature of the serialized order, with tserver = 0

Market order serialization

field size (bytes) description
prefix 99 the order prefix
coin count 1 The number of funding coins
coin data coin length x count sequence of coin IDs
side 1 1 for buy, 2 for sell
quantity 8 quantity to buy or sell (atoms)
address varies client's receiving address

result

field type description
sig string server hex-encoded signature of the order by server, after adding the DEX timestamp
server time int the server's UNIX timestamp (milliseconds)

Market Buy Orders

Market buy orders have a slightly different ruleset than market sell orders or limit orders. First, the ordersize is not denominated in the base asset, but in the quote asset. As an example, on the DCR/BTC market, where DCR is the base asset, market sell orders and both types of limit orders' ordersize are quantified in the base asset, DCR, but the market buy order's ordersize is in BTC. The order is essentially a statement of "buy as much DCR as you can with this much BTC".

The ordersize is also not bound to the integral lot size constraints of other types of orders.

Since the market may move before the order is matched, at the time of submission it is not known with certainty how many lots will match. For orders that are nearly 1 lot, it is possible for no matching to occur because by the time the order is matched it cannot afford a single lot. The DEX server maintains an interest in ensuring that only valid orders that can match are accepted, so market buy orders must be handled carefully to make sure they remain valid.

To reduce the possibility of market buy orders becoming invalid (too small to match) due to a price increase, the DEX operator sets a market buy buffer, bm > 1 for each market. For a market where the base asset has lot size l, and for which there is a best known standing sell order price rate, r, the ordersize, Q, must satisfy the relation Q > bm l r. If the best rate increases before the order is matched, the order will still result in a fill as long as the price does not surpass ~bm r. If the market buy buffer is set too low or the market is particularly volatile and the price exceeds bm r, an order that was accepted but is now too small to match is considered executed but unfilled and there is no change to the account's cancellation statistics.

Cancel Order

Cancel orders remove standing limit orders from the order book. A client cannot cancel a market order or a limit order with time in force immediate. Further, due to the epoch-based pseudorandom matching process, a cancel order submitted in the same epoch as it's corresponding limit order has a 50% chance of being processed before the order it cancels, resulting in an error. This is by design and discourages certain types of spoofing.

Request route: cancel, originator: client

payload

field type description
9 prefix fields
targetid string hex-encoded order ID
sig string client hex-encoded signature of the serialized order data. serialization described below

Cancel order serialization

field size (bytes) description
prefix 99 the order prefix
orderid 32 the order ID

result

field type description
sig string server hex-encoded signature of the serialize order data, after adding the DEX timestamp
tserver int the server's UNIX timestamp (milliseconds)

Preimage Reveal

At the expiration of the epoch, the DEX sends out a preimage request for each order in the epoch queue. The match cycle begins 5 seconds after the last preimage request is sent by the server, so clients must respond before then.

A commitment checksum is included as part of the preimage request. The checksum is the Blake-256 hash of the concatenated, lexicographically-sorted commitments for every order in the epoch. For clients subscribed to the order book for the entire duration of the epoch, the checksum can be validated against the checksum generated from their local copy of the epoch queue.

Request route: preimage, originator: DEX

payload

field type description
orderid string order ID
csum string the commitment checksum

Preimage response

result

field size (bytes) description
pimg string hex-encoded preimage for the order's commitment

Match negotiation

Swap negotiation details will be relayed through the DEX with a series of notifications. Both the DEX and the clients will need to serialize and sign the notification data. The originator includes their signature with the request, while the recipient will return an acknowledgement, or a list of acknowledgements, as the result of their response payload.

Acknowledgement

field type description
matchid string the match ID
sig string hex-encoded signature of the notification data

If the client's order has one or more matches at the end of a match cycle, the DEX will send a list of match objects. The maker is the first to act, so after sending their acknowledgement, they should broadcast their initialization transaction and inform the server with an init notification (described after).

Request route: match, originator: DEX

payload (array)

field type description
orderid string order ID
matchid string the match ID to use for progress notifications
qty int the matched amount, in atoms of the base asset
rate int the matched price rate. message-rate encoding
tserver int server's UNIX timestamp (milliseconds)
address string the counterparty's receiving address
side int the client's side in the match. 0 = maker, 1 = taker
status int only provided in 'connect' response. For 'match' requests, status is 0 = 'MakerSwapCast'. See match.go for codes.
sig string DEX's hex-encoded signature of the serialized notification data. serialization described below

Match serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the ID assigned to this match
quantity 8 the matched amount, in atoms of the base asset
rate 8 the matched price rate. message-rate encoding
tserver 8 server's UNIX timestamp (milliseconds)
address varies UTF-8 encoded receiving address for the match

The tserver value is used as the basis for the the locktimes. If it is necessary to convert the time to seconds, the value should be rounded down.

The client will respond with a list of signed match acknowledgements.

After a client broadcasts their initialization transaction, they are expected to report the transaction details to the server for verification and relay to the matching party.

Request route: init, originator: client

payload

field type description
orderid string the order ID
matchid string the matchid, retrieved from the match notification
coinid string hex-encoded coin ID
contract string hex-encoded swap redeem script
sig string client signature of the serialized notification. serialization described below

Init serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the ID assigned to this match
coinid asset-dependent the coin ID
contract asset-dependent swap redeem script

The DEX will respond with an acknowledgement.

The DEX will send each client a notification when the counterparty has broadcast their initialization transaction. When the taker receives the audit notification, they will audit the maker's contract and after that contract asset's configured swap confirmation requirement is reached, broadcast their own initialization. When the maker receives the audit notification, they will audit the taker's contract and after the required confirmations, issue their redemption.

Request route: audit, originator: DEX

payload

field type description
orderid string the order ID
matchid string the match ID
timestamp int server's UNIX timestamp (milliseconds)
coinid string hex-encoded coin ID
contract string hex-encoded swap redeem script
sig string DEX's signature of the serialized notification. serialization described below

Audit serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID
timestamp 8 server's UNIX timestamp (milliseconds)
coin ID asset-dependent the coin ID
contract asset-dependent swap redeem script

The client responds with an acknowledgement.

When a client has redeemed their contract, they will notify the server.

Request route: redeem, originator: client

payload

field type description
orderid string the order ID
matchid string the match ID
coinid string hex-encoded coin ID
secret string the hex-encoded swap contract secret
sig string client signature of the serialized notification. serialization described below

Redeem serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID
coin ID asset-dependent the coin ID
secret 32 the swap contract secret

The DEX responds with an acknowledgement.

The DEX informs the taker when the maker has redeemed.

Request route: redemption, originator: DEX

payload

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID
coinid string hex-encoded coin ID
secret string the hex-encoded swap contract secret
timestamp int server's UNIX timestamp (milliseconds)
sig string DEX's signature of the serialized notification. serialization described below

Redemption serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID
coin ID asset-dependent the coin ID
secret 32 the swap contract secret
timestamp 8 server's UNIX timestamp (milliseconds)

The client will respond with an acknowledgement.

The taker will get the key from the maker's redemption and broadcast their own redemption transaction.

It is also possible for an epoch order to go through the matching cycle without generating a match. This will be common for limit orders, but can also occur for market orders if there are no booked orders to match with. When the server fails to find any matches, a nomatch notification will be sent to the client.

Notification route: nomatch, originator: DEX

payload

field type description
orderid string order ID

A client can request the current match status using the match_status request. Note that the route is provided as a convenience, and persistence of match data may be subject to the operator's archiving policy. match_status can be used to recover after a temporary disconnection, but should not be relied on as a source of historical match data.

Notification route: match_status, originator: client

payload: an array of MatchRequest objects

MatchRequest object

field type description
base int the base asset ID
quote int the quote asset ID
matchid string hex-encoded Match ID

result: an array of MatchStatus objects

MatchStatus object

field type description
matchid string the match ID
status int See match.go for codes.
makercontract string the swap contract broadcast by the maker
takercontract string the swap contract broadcast by the taker
makerswap string the coin ID for the swap broadcast by the maker
takerswap string the coin ID for the swap broadcast by the taker
makerredeem string the coin ID for the maker's redemption
takerredeem string the coin ID for the taker's redemption
secret string the swap contract secret
active bool whether the match is still active

Empty fields may be omitted from the encoded MatchStatus object. Results are only returned for matches that could be found in the server records. No error is set in the case of unfound matches.

Match Revocation

A match can be revoked by the server if a client fails to act within the broadcast timeout. A match revocation will result in penalties for the violating party only. The revoked match quantity is not added back to the order book in any form.

Request route: revoke_match, originator: DEX

payload

field type description
orderid string the order ID
matchid string the match ID
sig string DEX's hex-encoded signature of serialized revocation. serialization described below

Revocation serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID

The client will respond with an acknowledgement.

Trade Suspension

There are a number of scenarios where the server may suspend operations, intentionally or not. During trade suspension, standing limit orders are not necessarily revoked.

If the server intentionally suspends operations, they should provide a notification to connected clients as early as possible, ideally with several epochs for the client to get their orders situated before matching ceases.

Clients should be prepared to lose connection during suspension. Clients will need to reconnect and complete settlement when the server comes back online.

If the server disconnects without notice, it is expected that orders placed during the current epoch are revoked at no penalty to the client and that standing limit orders are persisted.

The suspension notification may indicate that standing limit orders will not be persisted. This would be the case if the DEX needs to change an asset variable such as the lot size or minimum transaction fee rate.

If standing limit orders are persisted, they will be auto-revoked if the client does not reconnect before the next start epoch.

Request route: suspension, originator: DEX

payload

field type description
marketid string the market ID
finalepoch uint64 the last epoch during which orders will be collected and matched
suspendtime uint64 the UNIX timestamp corresponding to the end of the final epoch (milliseconds)
persistbook bool whether standing limit orders will persist through the suspension

Clients will also be informed when trading is resumed.

Request route: resumption, originator: DEX payload

field type description
marketid string the market ID
startepoch uint64 the epoch number at which trading did or will commence. May be in the future
epochlen uint64 the epoch duration (milliseconds)