decred.org/dcrdex@v1.0.5/server/db/driver/pg/internal/orders.go (about)

     1  // This code is available on the terms of the project LICENSE.md file,
     2  // also available online at https://blueoakcouncil.org/license/1.0.0.
     3  
     4  package internal
     5  
     6  const (
     7  	// CreateOrdersTable creates a table specified via the %s printf specifier
     8  	// for market and limit orders.
     9  	CreateOrdersTable = `CREATE TABLE IF NOT EXISTS %s (
    10  		oid BYTEA PRIMARY KEY, -- UNIQUE
    11  		type INT2,
    12  		sell BOOLEAN,          -- TODO: ANALYZE or INDEX?
    13  		account_id BYTEA,      -- TODO: INDEX
    14  		address TEXT,          -- TODO:INDEX
    15  		client_time TIMESTAMPTZ,
    16  		server_time TIMESTAMPTZ,
    17  		commit BYTEA UNIQUE,
    18  		coins BYTEA,
    19  		quantity INT8,
    20  		rate INT8,
    21  		force INT2,
    22  		status INT2,
    23  		filled INT8,
    24  		epoch_idx INT8, epoch_dur INT4,
    25  		preimage BYTEA UNIQUE,
    26  		complete_time INT8      -- when the order has successfully completed all swaps
    27  	);`
    28  
    29  	// InsertOrder inserts a market or limit order into the specified table.
    30  	InsertOrder = `INSERT INTO %s (oid, type, sell, account_id, address,
    31  			client_time, server_time, commit, coins, quantity,
    32  			rate, force, status, filled,
    33  			epoch_idx, epoch_dur)
    34  		VALUES ($1, $2, $3, $4, $5,
    35  			$6, $7, $8, $9, $10,
    36  			$11, $12, $13, $14,
    37  			$15, $16);`
    38  
    39  	// SelectOrder retrieves all columns with the given order ID. This may be
    40  	// used for any table with an "oid" column (orders_active, cancels_archived,
    41  	// etc.).
    42  	SelectOrder = `SELECT oid, type, sell, account_id, address, client_time, server_time,
    43  		commit, coins, quantity, rate, force, status, filled
    44  	FROM %s WHERE oid = $1;`
    45  
    46  	SelectOrdersByStatus = `SELECT oid, type, sell, account_id, address, client_time, server_time,
    47  		commit, coins, quantity, rate, force, filled
    48  	FROM %s WHERE status = $1;`
    49  
    50  	PreimageResultsLastN = `SELECT oid, (preimage IS NULL AND status=$3) AS preimageMiss, 
    51  		(epoch_idx+1) * epoch_dur as epochCloseTime   -- when preimages are requested
    52  	FROM %s -- e.g. dcr_btc.orders_archived
    53  	WHERE account_id = $1
    54  		AND status >= 0         -- exclude forgiven
    55  	ORDER BY epochCloseTime DESC
    56  	LIMIT $2` // no ;
    57  	// NOTE: we could join with the epochs table if we really want match_time instead of epoch close time
    58  
    59  	// SelectUserOrders retrieves all columns of all orders for the given
    60  	// account ID.
    61  	SelectUserOrders = `SELECT oid, type, sell, account_id, address, client_time, server_time,
    62  		commit, coins, quantity, rate, force, status, filled
    63  	FROM %s WHERE account_id = $1;`
    64  
    65  	// SelectUserOrderStatuses retrieves the order IDs and statuses of all orders
    66  	// for the given account ID. Only applies to market and limit orders.
    67  	SelectUserOrderStatuses = `SELECT oid, status FROM %s WHERE account_id = $1;`
    68  
    69  	// SelectUserOrderStatusesByID retrieves the order IDs and statuses of the
    70  	// orders with the provided order IDs for the given account ID. Only applies
    71  	// to market and limit orders.
    72  	SelectUserOrderStatusesByID = `SELECT oid, status FROM %s WHERE account_id = $1 AND oid = ANY($2);`
    73  
    74  	// SelectCanceledUserOrders gets the ID of orders that were either canceled
    75  	// by the user or revoked/canceled by the server, but these statuses can be
    76  	// set by the caller. Note that revoked orders can be market or immediate
    77  	// limit orders that failed to swap.
    78  	SelectCanceledUserOrders = `SELECT oid, match_time
    79  		FROM %[1]s -- a archived orders table
    80  		JOIN %[2]s ON %[2]s.epoch_idx = %[1]s.epoch_idx AND %[2]s.epoch_dur = %[1]s.epoch_dur -- join on epochs table PK
    81  		WHERE account_id = $1 AND status = ANY($2) -- {orderStatusCanceled, orderStatusRevoked}
    82  		ORDER BY match_time DESC
    83  		LIMIT $3;` // The matchTime is when the order was booked, not canceled!!!
    84  
    85  	// SelectOrderByCommit retrieves the order ID for any order with the given
    86  	// commitment value. This applies to the cancel order tables as well.
    87  	SelectOrderByCommit = `SELECT oid FROM %s WHERE commit = $1;`
    88  
    89  	// SelectOrderPreimage retrieves the preimage for the order ID;
    90  	SelectOrderPreimage = `SELECT preimage FROM %s WHERE oid = $1;`
    91  
    92  	// SelectOrderCoinIDs retrieves the order id, sell flag, and coins for all
    93  	// orders in a certain table.
    94  	SelectOrderCoinIDs = `SELECT oid, sell, coins
    95  		FROM %s;`
    96  
    97  	SetOrderPreimage     = `UPDATE %s SET preimage = $1 WHERE oid = $2;`
    98  	SetOrderCompleteTime = `UPDATE %s SET complete_time = $1
    99  		WHERE oid = $2;`
   100  
   101  	RetrieveCompletedOrdersForAccount = `SELECT oid, account_id, complete_time
   102  		FROM %s
   103  		WHERE account_id = $1 AND complete_time IS NOT NULL
   104  		ORDER BY complete_time DESC
   105  		LIMIT $2;`
   106  
   107  	// UpdateOrderStatus sets the status of an order with the given order ID.
   108  	UpdateOrderStatus = `UPDATE %s SET status = $1 WHERE oid = $2;`
   109  	// UpdateOrderFilledAmt sets the filled amount of an order with the given
   110  	// order ID.
   111  	UpdateOrderFilledAmt = `UPDATE %s SET filled = $1 WHERE oid = $2;`
   112  	// UpdateOrderStatusAndFilledAmt sets the order status and filled amount of
   113  	// an order with the given order ID.
   114  	UpdateOrderStatusAndFilledAmt = `UPDATE %s SET status = $1, filled = $2 WHERE oid = $3;`
   115  
   116  	// OrderStatus retrieves the order type, status, and filled amount for an
   117  	// order with the given order ID. This only applies to market and limit
   118  	// orders. For cancel orders, which lack a type and filled column, use
   119  	// CancelOrderStatus.
   120  	OrderStatus = `SELECT type, status, filled FROM %s WHERE oid = $1;`
   121  
   122  	// MoveOrder moves an order row from one table to another (e.g.
   123  	// orders_active to orders_archived), while updating the order's status and
   124  	// filled amounts.
   125  	// For example,
   126  	//	WITH moved AS (                                 -- temporary table
   127  	//		DELETE FROM dcrdex.dcr_btc.orders_active    -- origin table (%s)
   128  	//		WHERE oid = '\xDEADBEEF'                    -- the order to move ($1)
   129  	//		RETURNING
   130  	//			oid,
   131  	//			type,
   132  	//			sell,
   133  	//			account_id,
   134  	//			address,
   135  	//			client_time,
   136  	//			server_time,
   137  	//			commit,
   138  	//			coins,
   139  	//			quantity,
   140  	//			rate,
   141  	//			force,
   142  	//			2,                                      -- new status (%d)
   143  	//			123456789,                              -- new filled (%d)
   144  	//          epoch_idx, epoch_dur, preimage, complete_time
   145  	//		)
   146  	//		INSERT INTO dcrdex.dcr_btc.orders_archived  -- destination table (%s)
   147  	//		SELECT * FROM moved;
   148  	MoveOrder = `WITH moved AS (
   149  		DELETE FROM %s
   150  		WHERE oid = $1
   151  		RETURNING oid, type, sell, account_id, address,
   152  			client_time, server_time, commit, coins, quantity,
   153  			rate, force, %d, %d,
   154  			epoch_idx, epoch_dur, preimage, complete_time
   155  	)
   156  	INSERT INTO %s
   157  	SELECT * FROM moved;`
   158  	// TODO: consider a MoveOrderSameFilled query
   159  
   160  	PurgeBook = `WITH moved AS (
   161  		DELETE FROM %s       -- active orders table for market X
   162  		WHERE status = $1    -- booked status code
   163  		RETURNING oid, type, sell, account_id, address,
   164  			client_time, server_time, commit, coins, quantity,
   165  			rate, force, %d, filled, -- revoked status code
   166  			epoch_idx, epoch_dur, preimage, complete_time
   167  	)
   168  	INSERT INTO %s -- archived orders table for market X
   169  	SELECT * FROM moved
   170  	RETURNING oid, sell, account_id;`
   171  
   172  	// CreateCancelOrdersTable creates a table specified via the %s printf
   173  	// specifier for cancel orders.
   174  	CreateCancelOrdersTable = `CREATE TABLE IF NOT EXISTS %s (
   175  		oid BYTEA PRIMARY KEY, -- UNIQUE INDEX
   176  		account_id BYTEA,      -- TODO: INDEX
   177  		client_time TIMESTAMPTZ,
   178  		server_time TIMESTAMPTZ,
   179  		commit BYTEA UNIQUE,   -- null for server-generated cancels (order revocations)
   180  		target_order BYTEA,    -- cancel orders ref another order
   181  		status INT2,
   182  		epoch_idx INT8, epoch_dur INT4, -- 0 for rule-based revocations, -1 for exempt (e.g. book purge)
   183  		epoch_gap INT4 DEFAULT -1, -- epochs between order and cancel order. -1 for revocations
   184  		preimage BYTEA UNIQUE  -- null before preimage collection, and all server-generated cancels (revocations)
   185  	);`
   186  
   187  	SelectCancelOrder = `SELECT oid, account_id, client_time, server_time,
   188  		commit, target_order, status
   189  	FROM %s WHERE oid = $1;`
   190  
   191  	SelectCancelOrdersByStatus = `SELECT account_id, client_time, server_time,
   192  		commit, target_order
   193  	FROM %s WHERE status = $1;`
   194  
   195  	CancelPreimageResultsLastN = `SELECT oid, (preimage IS NULL AND status=$3) AS preimageMiss,  -- orderStatusRevoked
   196  		(epoch_idx+1) * epoch_dur AS epochCloseTime   -- when preimages are requested
   197  	FROM %s -- e.g. dcr_btc.cancels_archived
   198  	WHERE account_id = $1
   199  		AND commit IS NOT NULL  -- commit NOT NULL to exclude server-generated cancels
   200  		AND status >= 0         -- not forgiven
   201  	ORDER BY epochCloseTime DESC
   202  	LIMIT $2` // no ;
   203  
   204  	// SelectRevokeCancels retrieves server-initiated cancels (revokes).
   205  	SelectRevokeCancels = `SELECT oid, target_order, server_time, epoch_idx
   206  		FROM %s
   207  		WHERE account_id = $1 AND status = $2 -- use orderStatusRevoked
   208  		ORDER BY server_time DESC
   209  		LIMIT $3;`
   210  
   211  	// RetrieveCancelsForUserByStatus gets matched cancel orders by user and
   212  	// status, where status should be orderStatusExecuted. This query may be
   213  	// followed by a SELECT of match_time from the epochs table for the epoch
   214  	// IDs (idx:dur) returned by this query. In general, this query will be used
   215  	// on a market's archived cancels table, which includes matched cancels.
   216  	RetrieveCancelsForUserByStatus = `SELECT oid, target_order, epoch_idx, epoch_dur
   217  		FROM %s
   218  		WHERE account_id = $1 AND status = $2
   219  		ORDER BY epoch_idx * epoch_dur DESC;`
   220  	// RetrieveCancelTimesForUserByStatus is similar to
   221  	// RetrieveCancelsForUserByStatus, but it joins on an epochs table to get
   222  	// the match_time directly instead of the epoch_idx and epoch_dur. The
   223  	// cancels table, with full market schema, is %[1]s, while the epochs table
   224  	// is %[2]s.
   225  	RetrieveCancelTimesForUserByStatus = `SELECT oid, target_order, epoch_gap, match_time
   226  		FROM %[1]s -- a cancels table
   227  		JOIN %[2]s ON %[2]s.epoch_idx = %[1]s.epoch_idx AND %[2]s.epoch_dur = %[1]s.epoch_dur -- join on epochs table PK
   228  		WHERE account_id = $1 AND status = $2
   229  		ORDER BY match_time DESC
   230  		LIMIT $3;` // NOTE: find revoked orders via SelectRevokeCancels
   231  
   232  	// InsertCancelOrder inserts a cancel order row into the specified table.
   233  	InsertCancelOrder = `INSERT INTO %s (oid, account_id, client_time, server_time,
   234  			commit, target_order, status, epoch_idx, epoch_dur, epoch_gap)
   235  		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);`
   236  
   237  	// CancelOrderStatus retrieves an order's status
   238  	CancelOrderStatus = `SELECT status FROM %s WHERE oid = $1;`
   239  
   240  	// MoveCancelOrder, like MoveOrder, moves an order row from one table to
   241  	// another. However, for a cancel order, only status column is updated.
   242  	MoveCancelOrder = `WITH moved AS (
   243  		DELETE FROM %s
   244  		WHERE oid = $1
   245  		RETURNING oid, account_id, client_time, server_time, commit, target_order, %d, epoch_idx, epoch_dur, epoch_gap, preimage
   246  	)
   247  	INSERT INTO %s (oid, account_id, client_time, server_time, commit, target_order, status, epoch_idx, epoch_dur, epoch_gap, preimage)
   248  	SELECT * FROM moved;`
   249  )