forked from Qortal/qortal
Don't allow more than one (active) trade-bot entry per trade-offer
This commit is contained in:
parent
3fdef9ea6d
commit
3ec307a2a1
@ -1,5 +1,7 @@
|
||||
package org.qortal.controller.tradebot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.qortal.api.model.crosschain.TradeBotCreateRequest;
|
||||
import org.qortal.crosschain.ACCT;
|
||||
import org.qortal.crosschain.ForeignBlockchainException;
|
||||
@ -11,7 +13,10 @@ import org.qortal.repository.Repository;
|
||||
|
||||
public interface AcctTradeBot {
|
||||
|
||||
public enum ResponseResult { OK, BALANCE_ISSUE, NETWORK_ISSUE }
|
||||
public enum ResponseResult { OK, BALANCE_ISSUE, NETWORK_ISSUE, TRADE_ALREADY_EXISTS }
|
||||
|
||||
/** Returns list of state names for trade-bot entries that have ended, e.g. redeemed, refunded or cancelled. */
|
||||
public List<String> getEndStates();
|
||||
|
||||
public byte[] createTrade(Repository repository, TradeBotCreateRequest tradeBotCreateRequest) throws DataException;
|
||||
|
||||
|
@ -6,6 +6,7 @@ import static java.util.stream.Collectors.toMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -110,6 +111,10 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
|
||||
|
||||
private static BitcoinACCTv1TradeBot instance;
|
||||
|
||||
private final List<String> endStates = Arrays.asList(State.BOB_DONE, State.BOB_REFUNDED, State.ALICE_DONE, State.ALICE_REFUNDING_A, State.ALICE_REFUNDING_B, State.ALICE_REFUNDED).stream()
|
||||
.map(State::name)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
|
||||
private BitcoinACCTv1TradeBot() {
|
||||
}
|
||||
|
||||
@ -120,6 +125,11 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getEndStates() {
|
||||
return this.endStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new trade-bot entry from the "Bob" viewpoint, i.e. OFFERing QORT in exchange for BTC.
|
||||
* <p>
|
||||
|
@ -3,8 +3,10 @@ package org.qortal.controller.tradebot;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -102,6 +104,10 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
||||
|
||||
private static LitecoinACCTv1TradeBot instance;
|
||||
|
||||
private final List<String> endStates = Arrays.asList(State.BOB_DONE, State.BOB_REFUNDED, State.ALICE_DONE, State.ALICE_REFUNDING_A, State.ALICE_REFUNDED).stream()
|
||||
.map(State::name)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
|
||||
private LitecoinACCTv1TradeBot() {
|
||||
}
|
||||
|
||||
@ -112,6 +118,11 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getEndStates() {
|
||||
return this.endStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new trade-bot entry from the "Bob" viewpoint, i.e. OFFERing QORT in exchange for LTC.
|
||||
* <p>
|
||||
|
@ -176,6 +176,10 @@ public class TradeBot implements Listener {
|
||||
return ResponseResult.NETWORK_ISSUE;
|
||||
}
|
||||
|
||||
// Check Alice doesn't already have an existing, on-going trade-bot entry for this AT.
|
||||
if (repository.getCrossChainRepository().existsTradeWithAtExcludingStates(atData.getATAddress(), acctTradeBot.getEndStates()))
|
||||
return ResponseResult.TRADE_ALREADY_EXISTS;
|
||||
|
||||
return acctTradeBot.startResponse(repository, atData, acct, crossChainTradeData, foreignKey, receivingAddress);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,9 @@ public interface CrossChainRepository {
|
||||
|
||||
public TradeBotData getTradeBotData(byte[] tradePrivateKey) throws DataException;
|
||||
|
||||
/** Returns true if there is an existing trade-bot entry relating to given AT address, excluding trade-bot entries with given states. */
|
||||
public boolean existsTradeWithAtExcludingStates(String atAddress, List<String> excludeStates) throws DataException;
|
||||
|
||||
public List<TradeBotData> getAllTradeBotData() throws DataException;
|
||||
|
||||
public void save(TradeBotData tradeBotData) throws DataException;
|
||||
|
@ -3,6 +3,7 @@ package org.qortal.repository.hsqldb;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.qortal.data.crosschain.TradeBotData;
|
||||
@ -68,6 +69,36 @@ public class HSQLDBCrossChainRepository implements CrossChainRepository {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsTradeWithAtExcludingStates(String atAddress, List<String> excludeStates) throws DataException {
|
||||
if (excludeStates == null)
|
||||
excludeStates = Collections.emptyList();
|
||||
|
||||
StringBuilder whereClause = new StringBuilder(256);
|
||||
whereClause.append("at_address = ?");
|
||||
|
||||
Object[] bindParams = new Object[1 + excludeStates.size()];
|
||||
bindParams[0] = atAddress;
|
||||
|
||||
if (!excludeStates.isEmpty()) {
|
||||
whereClause.append(" AND trade_state NOT IN (?");
|
||||
bindParams[1] = excludeStates.get(0);
|
||||
|
||||
for (int i = 1; i < excludeStates.size(); ++i) {
|
||||
whereClause.append(", ?");
|
||||
bindParams[1 + i] = excludeStates.get(i);
|
||||
}
|
||||
|
||||
whereClause.append(")");
|
||||
}
|
||||
|
||||
try {
|
||||
return this.repository.exists("TradeBotStates", whereClause.toString(), bindParams);
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Unable to check for trade-bot state in repository", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TradeBotData> getAllTradeBotData() throws DataException {
|
||||
String sql = "SELECT trade_private_key, acct_name, trade_state, trade_state_value, "
|
||||
|
Loading…
x
Reference in New Issue
Block a user