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

     1  package internal
     2  
     3  const (
     4  	// CreateMatchesTable creates the matches table for storing data related to
     5  	// a match and the related swap. This only includes trade matches, not
     6  	// cancel order matches that just remove one order from the book (and change
     7  	// the target order status in the orders table).
     8  	//
     9  	// The takerSell column indicates the asset of the address and coinID
    10  	// columns for both maker and taker. Sell refers to sell of the base asset,
    11  	// and the opposite is implied for the counterparty (makerSell = !takerSell)
    12  	//
    13  	//   takerSell   | takerAddress | aContractCoinID | aRedeemCoinID ||  (makerSell)  | makerAddress | bContractCoinID | bRedeemCoinID
    14  	// ---------------------------------------------------------------------------------------------------------------------------------
    15  	//  true (B->Q)  |    quote     |      base       |     quote     ||  false (Q->B) |     base     |      quote      |     base
    16  	//  false (Q->B) |    base      |      quote      |     base      ||  true (B->Q)  |     quote    |      base       |     quote
    17  	CreateMatchesTable = `CREATE TABLE IF NOT EXISTS %s (
    18  		matchid BYTEA PRIMARY KEY,
    19  		active BOOL DEFAULT TRUE,    -- negotiation active, where FALSE includes failure, successful completion, or a taker cancel order
    20  		takerSell BOOL,        -- to identify asset of address and coinIDs, NULL for cancel orders
    21  		takerOrder BYTEA,      -- INDEX this
    22  		takerAccount BYTEA,    -- INDEX this
    23  		takerAddress TEXT,     -- NULL for cancel orders
    24  		makerOrder BYTEA,      -- INDEX this
    25  		makerAccount BYTEA,    -- INDEX this
    26  		makerAddress TEXT,     -- NULL for cancel orders
    27  		epochIdx INT8,
    28  		epochDur INT8,
    29  		quantity INT8,
    30  		rate INT8,
    31  		baseRate INT8, quoteRate INT8, -- contract tx fee rates, NULL for cancel orders
    32  		status INT2,           -- also updated during swap negotiation, independent from active for failed swaps
    33  		forgiven BOOL,
    34  
    35  		-- The remaining columns are only set during swap negotiation.
    36  		sigMatchAckMaker BYTEA,   -- maker's ack of the match
    37  		sigMatchAckTaker BYTEA,   -- taker's ack of the match
    38  
    39  		-- initiator/A (maker) CONTRACT data
    40  		aContractCoinID BYTEA,    -- coinID (e.g. tx:vout) with the contract
    41  		aContract BYTEA,          -- includes secret hash, get with ExtractSwapDetails for DCR
    42  		aContractTime INT8,       -- server time stamp
    43  		bSigAckOfAContract BYTEA, -- counterparty's (participant) sig with ack of initiator CONTRACT data
    44  
    45  		-- participant/B (taker) CONTRACT data
    46  		bContractCoinID BYTEA,
    47  		bContract BYTEA,
    48  		bContractTime INT8,       -- server time stamp
    49  		aSigAckOfBContract BYTEA, -- counterparty's (initiator) sig with ack of participant CONTRACT data
    50  
    51  		-- initiator/A (maker) REDEEM data
    52  		aRedeemCoinID BYTEA,      -- the input spending the taker's contract output includes the secret
    53  		aRedeemSecret BYTEA,
    54  		aRedeemTime INT8,         -- server time stamp
    55  		bSigAckOfARedeem BYTEA,   -- counterparty's (participant) sig with ack of initiator REDEEM data
    56  
    57  		-- participant/B (taker) REDEEM data
    58  		bRedeemCoinID BYTEA,
    59  		bRedeemTime INT8          -- server time stamp
    60  	)`
    61  
    62  	RetrieveMatchStatsByEpoch = `SELECT quantity, rate, takerSell FROM %s
    63  		WHERE takerSell IS NOT NULL AND epochIdx = $1 AND epochDur = $2;`
    64  
    65  	RetrieveSwapData = `SELECT status, sigMatchAckMaker, sigMatchAckTaker,
    66  		aContractCoinID, aContract, aContractTime, bSigAckOfAContract,
    67  		bContractCoinID, bContract, bContractTime, aSigAckOfBContract,
    68  		aRedeemCoinID, aRedeemSecret, aRedeemTime, bSigAckOfARedeem,
    69  		bRedeemCoinID, bRedeemTime
    70  	FROM %s WHERE matchid = $1;`
    71  
    72  	InsertMatch = `INSERT INTO %s (matchid, takerSell,
    73  		takerOrder, takerAccount, takerAddress,
    74  		makerOrder, makerAccount, makerAddress,
    75  		epochIdx, epochDur,
    76  		quantity, rate, baseRate, quoteRate, status)
    77  	VALUES ($1, $2,
    78  		$3, $4, $5,
    79  		$6, $7, $8,
    80  		$9, $10,
    81  		$11, $12, $13, $14, $15) ` // do not terminate with ;
    82  
    83  	UpsertMatch = InsertMatch + ` ON CONFLICT (matchid) DO
    84  	UPDATE SET quantity = $11, status = $15;`
    85  
    86  	InsertCancelMatch = `INSERT INTO %s (matchid, active, -- omit takerSell
    87  			takerOrder, takerAccount, -- no taker address for a cancel order
    88  			makerOrder, makerAccount, -- omit maker's swap address too
    89  			epochIdx, epochDur,
    90  			quantity, rate, status) -- omit base and quote fee rates
    91  		VALUES ($1, FALSE, -- no active swap for a cancel
    92  			$2, $3,
    93  			$4, $5,
    94  			$6, $7,
    95  			$8, $9, $10) ` // status should be MatchComplete although there is no swap
    96  
    97  	UpsertCancelMatch = InsertCancelMatch + ` ON CONFLICT (matchid) DO NOTHING;`
    98  
    99  	RetrieveMatchByID = `SELECT matchid, active, takerSell,
   100  		takerOrder, takerAccount, takerAddress,
   101  		makerOrder, makerAccount, makerAddress,
   102  		epochIdx, epochDur, quantity, rate, baseRate, quoteRate, status
   103  	FROM %s WHERE matchid = $1;`
   104  
   105  	RetrieveUserMatches = `SELECT matchid, active, takerSell,
   106  		takerOrder, takerAccount, takerAddress,
   107  		makerOrder, makerAccount, makerAddress,
   108  		epochIdx, epochDur, quantity, rate, baseRate, quoteRate, status
   109  	FROM %s
   110  	WHERE takerAccount = $1 OR makerAccount = $1;`
   111  
   112  	RetrieveActiveUserMatches = `SELECT matchid, takerSell,
   113  		takerOrder, takerAccount, takerAddress,
   114  		makerOrder, makerAccount, makerAddress,
   115  		epochIdx, epochDur, quantity, rate, baseRate, quoteRate, status
   116  	FROM %s
   117  	WHERE (takerAccount = $1 OR makerAccount = $1)
   118  		AND active;`
   119  
   120  	RetrieveMarketMatches = `SELECT matchid, active, takerSell,
   121  		takerOrder, takerAccount, takerAddress,
   122  		makerOrder, makerAccount, makerAddress,
   123  		epochIdx, epochDur, quantity, rate, baseRate, quoteRate, status,
   124  		aContractCoinID, bContractCoinID, aRedeemCoinID, bRedeemCoinID
   125  	FROM %s
   126  	WHERE takerSell IS NOT NULL -- not a cancel order
   127  	ORDER BY epochIdx * epochDur DESC
   128  	LIMIT $1;`
   129  
   130  	RetrieveActiveMarketMatches = `SELECT matchid, takerSell,
   131  		takerOrder, takerAccount, takerAddress,
   132  		makerOrder, makerAccount, makerAddress,
   133  		epochIdx, epochDur, quantity, rate, baseRate, quoteRate, status,
   134  		aContractCoinID, bContractCoinID, aRedeemCoinID, bRedeemCoinID
   135  	FROM %s
   136  	WHERE takerSell IS NOT NULL -- not a cancel order
   137  		AND active
   138  	ORDER BY epochIdx * epochDur DESC;`
   139  
   140  	// RetrieveActiveMarketMatchesExtended combines RetrieveSwapData with
   141  	// RetrieveActiveMarketMatches.
   142  	RetrieveActiveMarketMatchesExtended = `SELECT matchid, takerSell,
   143  		takerOrder, takerAccount, takerAddress,
   144  		makerOrder, makerAccount, makerAddress,
   145  		epochIdx, epochDur, quantity, rate, baseRate, quoteRate, status,
   146  		sigMatchAckMaker, sigMatchAckTaker,
   147  		aContractCoinID, aContract, aContractTime, bSigAckOfAContract,
   148  		bContractCoinID, bContract, bContractTime, aSigAckOfBContract,
   149  		aRedeemCoinID, aRedeemSecret, aRedeemTime, bSigAckOfARedeem,
   150  		bRedeemCoinID, bRedeemTime
   151  	FROM %s
   152  	WHERE takerSell IS NOT NULL -- not a cancel order
   153  		AND active
   154  	ORDER BY epochIdx * epochDur DESC;`
   155  
   156  	// CompletedOrAtFaultMatchesLastN retrieves inactive matches for a user that
   157  	// are either successfully completed by the user (MatchComplete or
   158  	// MakerRedeemed with user as maker), or failed because of this user's
   159  	// inaction. Note that the literal status values used in this query MUST BE
   160  	// UPDATED if the order.OrderStatus enum is changed.
   161  	CompletedOrAtFaultMatchesLastN = `
   162  		WITH acct (aid) AS ( VALUES($1::BYTEA) )
   163  
   164  		SELECT matchid, status, quantity, (status=4 OR (status=3 AND makerAccount = aid AND takerAccount != aid)) AS success,
   165  			GREATEST((epochIdx+1)*epochDur, aContractTime, bContractTime, aRedeemTime, bRedeemTime) AS lastTime
   166  		FROM %s, acct
   167  		WHERE takerSell IS NOT NULL      -- exclude cancel order matches
   168  			AND (makerAccount = aid OR takerAccount = aid)
   169  			AND (
   170  				-- swap success for both
   171  				status=4                                       -- success for both
   172  				OR
   173  				-- swap success for maker unless maker==taker
   174  				(status=3 AND makerAccount = aid AND takerAccount != aid)
   175  				OR
   176  				( -- at-fault swap failures
   177  					NOT active -- failure means inactive/revoked
   178  					AND (forgiven IS NULL OR NOT forgiven)
   179  					AND (
   180  						(status=0 AND makerAccount = aid) OR   -- fault for maker
   181  						(status=1 AND takerAccount = aid) OR   -- fault for taker
   182  						(status=2 AND makerAccount = aid) OR   -- fault for maker
   183  						(status=3 AND takerAccount = aid)      -- fault for taker
   184  					)
   185  				)
   186  			)
   187  		ORDER BY lastTime DESC   -- last action time i.e. success or approx. when could have acted
   188  		LIMIT $2;`
   189  
   190  	UserMatchFails = `
   191  		WITH acct (aid) AS ( VALUES($1::BYTEA) )
   192  
   193  		SELECT matchid, status
   194  		FROM %s, acct
   195  		WHERE takerSell IS NOT NULL      -- exclude cancel order matches
   196  			AND (makerAccount = aid OR takerAccount = aid)
   197  			AND NOT active -- failure means inactive/revoked
   198  			AND (forgiven IS NULL OR NOT forgiven)
   199  			AND (
   200  				(status=0 AND makerAccount = aid) OR   -- fault for maker
   201  				(status=1 AND takerAccount = aid) OR   -- fault for taker
   202  				(status=2 AND makerAccount = aid) OR   -- fault for maker
   203  				(status=3 AND takerAccount = aid)      -- fault for taker
   204  			)
   205  		ORDER BY GREATEST((epochIdx+1)*epochDur, aContractTime, bContractTime, aRedeemTime, bRedeemTime) DESC   -- last action time i.e. success or approx. when could have acted
   206  		LIMIT $2;`
   207  
   208  	ForgiveMatchFail = `UPDATE %s SET forgiven = TRUE
   209  		WHERE matchid = $1 AND NOT active;`
   210  
   211  	SetMakerMatchAckSig = `UPDATE %s SET sigMatchAckMaker = $2 WHERE matchid = $1;`
   212  	SetTakerMatchAckSig = `UPDATE %s SET sigMatchAckTaker = $2 WHERE matchid = $1;`
   213  
   214  	SetInitiatorSwapData = `UPDATE %s SET status = $2,
   215  		aContractCoinID = $3, aContract = $4, aContractTime = $5
   216  	WHERE matchid = $1;`
   217  	SetParticipantSwapData = `UPDATE %s SET status = $2,
   218  		bContractCoinID = $3, bContract = $4, bContractTime = $5
   219  	WHERE matchid = $1;`
   220  
   221  	SetParticipantContractAuditSig = `UPDATE %s SET bSigAckOfAContract = $2 WHERE matchid = $1;`
   222  	SetInitiatorContractAuditSig   = `UPDATE %s SET aSigAckOfBContract = $2 WHERE matchid = $1;`
   223  
   224  	SetInitiatorRedeemData = `UPDATE %s SET status = $2,
   225  		aRedeemCoinID = $3, aRedeemSecret = $4, aRedeemTime = $5
   226  	WHERE matchid = $1;`
   227  	SetParticipantRedeemData = `UPDATE %s SET status = $2,
   228  		bRedeemCoinID = $3, bRedeemTime = $4, active = FALSE
   229  	WHERE matchid = $1;`
   230  
   231  	SetParticipantRedeemAckSig = `UPDATE %s
   232  		SET bSigAckOfARedeem = $2
   233  		WHERE matchid = $1;`
   234  
   235  	SetSwapDone = `UPDATE %s SET active = FALSE  -- leave forgiven NULL
   236  		WHERE matchid = $1;`
   237  
   238  	SetSwapDoneForgiven = `UPDATE %s SET active = FALSE, forgiven = TRUE
   239  		WHERE matchid = $1;`
   240  
   241  	SelectMatchStatuses = `SELECT takerSell, (takerAccount = $1) AS isTaker, (makerAccount = $1) AS isMaker, matchid, status, aContract, bContract, aContractCoinID,
   242  		bContractCoinID, aRedeemCoinID, bRedeemCoinID, aRedeemSecret, active
   243  		FROM %s
   244  		WHERE matchid = ANY($2)
   245  		AND (takerAccount = $1 OR makerAccount = $1);`
   246  )