3
0
mirror of https://github.com/Qortal/qortal.git synced 2025-02-11 17:55:50 +00:00

Merge remote-tracking branch 'origin/master'

This commit is contained in:
kennycud 2024-12-30 16:06:24 -08:00
commit 950c4a5b35
8 changed files with 54 additions and 17 deletions

View File

@ -52,6 +52,8 @@ import java.util.*;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Path("/crosschain") @Path("/crosschain")
@Tag(name = "Cross-Chain") @Tag(name = "Cross-Chain")
public class CrossChainResource { public class CrossChainResource {
@ -255,6 +257,12 @@ public class CrossChainResource {
description = "Only return trades that completed on/after this timestamp (milliseconds since epoch)", description = "Only return trades that completed on/after this timestamp (milliseconds since epoch)",
example = "1597310000000" example = "1597310000000"
) @QueryParam("minimumTimestamp") Long minimumTimestamp, ) @QueryParam("minimumTimestamp") Long minimumTimestamp,
@Parameter(
description = "Optionally filter by buyer Qortal address"
) @QueryParam("buyerAddress") String buyerAddress,
@Parameter(
description = "Optionally filter by seller Qortal address"
) @QueryParam("sellerAddress") String sellerAddress,
@Parameter( ref = "limit") @QueryParam("limit") Integer limit, @Parameter( ref = "limit") @QueryParam("limit") Integer limit,
@Parameter( ref = "offset" ) @QueryParam("offset") Integer offset, @Parameter( ref = "offset" ) @QueryParam("offset") Integer offset,
@Parameter( ref = "reverse" ) @QueryParam("reverse") Boolean reverse) { @Parameter( ref = "reverse" ) @QueryParam("reverse") Boolean reverse) {
@ -296,7 +304,7 @@ public class CrossChainResource {
byte[] codeHash = acctInfo.getKey().value; byte[] codeHash = acctInfo.getKey().value;
ACCT acct = acctInfo.getValue().get(); ACCT acct = acctInfo.getValue().get();
List<ATStateData> atStates = repository.getATRepository().getMatchingFinalATStates(codeHash, List<ATStateData> atStates = repository.getATRepository().getMatchingFinalATStates(codeHash, buyerAddress, sellerAddress,
isFinished, acct.getModeByteOffset(), (long) AcctMode.REDEEMED.value, minimumFinalHeight, isFinished, acct.getModeByteOffset(), (long) AcctMode.REDEEMED.value, minimumFinalHeight,
limit, offset, reverse); limit, offset, reverse);

View File

@ -98,7 +98,7 @@ public class TradeOffersWebSocket extends ApiWebSocket implements Listener {
byte[] codeHash = acctInfo.getKey().value; byte[] codeHash = acctInfo.getKey().value;
ACCT acct = acctInfo.getValue().get(); ACCT acct = acctInfo.getValue().get();
List<ATStateData> atStates = repository.getATRepository().getMatchingFinalATStates(codeHash, List<ATStateData> atStates = repository.getATRepository().getMatchingFinalATStates(codeHash, null, null,
isFinished, dataByteOffset, expectedValue, minimumFinalHeight, isFinished, dataByteOffset, expectedValue, minimumFinalHeight,
null, null, null); null, null, null);
@ -259,7 +259,7 @@ public class TradeOffersWebSocket extends ApiWebSocket implements Listener {
ACCT acct = acctInfo.getValue().get(); ACCT acct = acctInfo.getValue().get();
Integer dataByteOffset = acct.getModeByteOffset(); Integer dataByteOffset = acct.getModeByteOffset();
List<ATStateData> initialAtStates = repository.getATRepository().getMatchingFinalATStates(codeHash, List<ATStateData> initialAtStates = repository.getATRepository().getMatchingFinalATStates(codeHash, null, null,
isFinished, dataByteOffset, expectedValue, minimumFinalHeight, isFinished, dataByteOffset, expectedValue, minimumFinalHeight,
null, null, null); null, null, null);
@ -298,7 +298,7 @@ public class TradeOffersWebSocket extends ApiWebSocket implements Listener {
byte[] codeHash = acctInfo.getKey().value; byte[] codeHash = acctInfo.getKey().value;
ACCT acct = acctInfo.getValue().get(); ACCT acct = acctInfo.getValue().get();
List<ATStateData> historicAtStates = repository.getATRepository().getMatchingFinalATStates(codeHash, List<ATStateData> historicAtStates = repository.getATRepository().getMatchingFinalATStates(codeHash, null, null,
isFinished, dataByteOffset, expectedValue, minimumFinalHeight, isFinished, dataByteOffset, expectedValue, minimumFinalHeight,
null, null, null); null, null, null);

View File

@ -76,7 +76,7 @@ public interface ATRepository {
* Although <tt>expectedValue</tt>, if provided, is natively an unsigned long, * Although <tt>expectedValue</tt>, if provided, is natively an unsigned long,
* the data segment comparison is done via unsigned hex string. * the data segment comparison is done via unsigned hex string.
*/ */
public List<ATStateData> getMatchingFinalATStates(byte[] codeHash, Boolean isFinished, public List<ATStateData> getMatchingFinalATStates(byte[] codeHash, String buyerAddress, String sellerAddress, Boolean isFinished,
Integer dataByteOffset, Long expectedValue, Integer minimumFinalHeight, Integer dataByteOffset, Long expectedValue, Integer minimumFinalHeight,
Integer limit, Integer offset, Boolean reverse) throws DataException; Integer limit, Integer offset, Boolean reverse) throws DataException;

View File

@ -1,6 +1,7 @@
package org.qortal.repository.hsqldb; package org.qortal.repository.hsqldb;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.qortal.controller.Controller; import org.qortal.controller.Controller;
@ -16,6 +17,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.qortal.data.account.AccountData;
public class HSQLDBATRepository implements ATRepository { public class HSQLDBATRepository implements ATRepository {
private static final Logger LOGGER = LogManager.getLogger(HSQLDBATRepository.class); private static final Logger LOGGER = LogManager.getLogger(HSQLDBATRepository.class);
@ -400,7 +403,7 @@ public class HSQLDBATRepository implements ATRepository {
} }
@Override @Override
public List<ATStateData> getMatchingFinalATStates(byte[] codeHash, Boolean isFinished, public List<ATStateData> getMatchingFinalATStates(byte[] codeHash, String buyerAddress, String sellerAddress, Boolean isFinished,
Integer dataByteOffset, Long expectedValue, Integer minimumFinalHeight, Integer dataByteOffset, Long expectedValue, Integer minimumFinalHeight,
Integer limit, Integer offset, Boolean reverse) throws DataException { Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(1024); StringBuilder sql = new StringBuilder(1024);
@ -421,10 +424,14 @@ public class HSQLDBATRepository implements ATRepository {
// Order by AT_address and height to use compound primary key as index // Order by AT_address and height to use compound primary key as index
// Both must be the same direction (DESC) also // Both must be the same direction (DESC) also
sql.append("ORDER BY ATStates.AT_address DESC, ATStates.height DESC " sql.append("ORDER BY ATStates.height DESC LIMIT 1) AS FinalATStates ");
+ "LIMIT 1 "
+ ") AS FinalATStates " // Optional LEFT JOIN with ATTRANSACTIONS for buyerAddress
+ "WHERE code_hash = ? "); if (buyerAddress != null && !buyerAddress.isEmpty()) {
sql.append("LEFT JOIN ATTRANSACTIONS tx ON tx.at_address = ATs.AT_address ");
}
sql.append("WHERE ATs.code_hash = ? ");
bindParams.add(codeHash); bindParams.add(codeHash);
if (isFinished != null) { if (isFinished != null) {
@ -443,6 +450,20 @@ public class HSQLDBATRepository implements ATRepository {
bindParams.add(rawExpectedValue); bindParams.add(rawExpectedValue);
} }
if (buyerAddress != null && !buyerAddress.isEmpty()) {
sql.append("AND tx.recipient = ? ");
bindParams.add(buyerAddress);
}
if (sellerAddress != null && !sellerAddress.isEmpty()) {
// Convert sellerAddress to publicKey (method depends on your implementation)
AccountData accountData = this.repository.getAccountRepository().getAccount(sellerAddress);
byte[] publicKey = accountData.getPublicKey();
sql.append("AND ATs.creator = ? ");
bindParams.add(publicKey);
}
sql.append(" ORDER BY FinalATStates.height "); sql.append(" ORDER BY FinalATStates.height ");
if (reverse != null && reverse) if (reverse != null && reverse)
sql.append("DESC"); sql.append("DESC");
@ -483,7 +504,7 @@ public class HSQLDBATRepository implements ATRepository {
Integer dataByteOffset, Long expectedValue, Integer dataByteOffset, Long expectedValue,
int minimumCount, int maximumCount, long minimumPeriod) throws DataException { int minimumCount, int maximumCount, long minimumPeriod) throws DataException {
// We need most recent entry first so we can use its timestamp to slice further results // We need most recent entry first so we can use its timestamp to slice further results
List<ATStateData> mostRecentStates = this.getMatchingFinalATStates(codeHash, isFinished, List<ATStateData> mostRecentStates = this.getMatchingFinalATStates(codeHash, null, null, isFinished,
dataByteOffset, expectedValue, null, dataByteOffset, expectedValue, null,
1, 0, true); 1, 0, true);

View File

@ -20,17 +20,21 @@
width: 100%; width: 100%;
text-align: center; text-align: center;
z-index: 1000; z-index: 1000;
top: 45%; top: 50%;
-ms-transform: translateY(-50%); -ms-transform: translateY(-50%);
transform: translateY(-50%); transform: translate(-50% , -50%);
left: 50%;
} }
#panel { #panel {
text-align: center; text-align: center;
background: white; background: white;
word-wrap: break-word;
width: 350px; width: 350px;
max-width: 100%;
margin: auto; margin: auto;
padding: 25px; padding: 25px;
border-radius: 30px; border-radius: 30px;
box-sizing: border-box;
} }
#status { #status {
color: #03a9f4; color: #03a9f4;

View File

@ -405,7 +405,7 @@ public class RepositoryTests extends Common {
Integer offset = null; Integer offset = null;
Boolean reverse = null; Boolean reverse = null;
hsqldb.getATRepository().getMatchingFinalATStates(codeHash, isFinished, dataByteOffset, expectedValue, minimumFinalHeight, limit, offset, reverse); hsqldb.getATRepository().getMatchingFinalATStates(codeHash,null, null, isFinished, dataByteOffset, expectedValue, minimumFinalHeight, limit, offset, reverse);
} catch (DataException e) { } catch (DataException e) {
fail("HSQLDB bug #1580"); fail("HSQLDB bug #1580");
} }

View File

@ -26,7 +26,7 @@ public class CrossChainApiTests extends ApiCommon {
@Test @Test
public void testGetCompletedTrades() { public void testGetCompletedTrades() {
long minimumTimestamp = System.currentTimeMillis(); long minimumTimestamp = System.currentTimeMillis();
assertNoApiError((limit, offset, reverse) -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, minimumTimestamp, limit, offset, reverse)); assertNoApiError((limit, offset, reverse) -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, minimumTimestamp, null, null, limit, offset, reverse));
} }
@Test @Test
@ -35,8 +35,8 @@ public class CrossChainApiTests extends ApiCommon {
Integer offset = null; Integer offset = null;
Boolean reverse = null; Boolean reverse = null;
assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, -1L /*minimumTimestamp*/, limit, offset, reverse)); assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, -1L /*minimumTimestamp*/, null, null, limit, offset, reverse));
assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, 0L /*minimumTimestamp*/, limit, offset, reverse)); assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, 0L /*minimumTimestamp*/, null, null, limit, offset, reverse));
} }
} }

View File

@ -218,6 +218,8 @@ public class AtRepositoryTests extends Common {
List<ATStateData> atStates = repository.getATRepository().getMatchingFinalATStates( List<ATStateData> atStates = repository.getATRepository().getMatchingFinalATStates(
codeHash, codeHash,
null,
null,
isFinished, isFinished,
dataByteOffset, dataByteOffset,
expectedValue, expectedValue,
@ -264,6 +266,8 @@ public class AtRepositoryTests extends Common {
List<ATStateData> atStates = repository.getATRepository().getMatchingFinalATStates( List<ATStateData> atStates = repository.getATRepository().getMatchingFinalATStates(
codeHash, codeHash,
null,
null,
isFinished, isFinished,
dataByteOffset, dataByteOffset,
expectedValue, expectedValue,