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;
|
package org.qortal.controller.tradebot;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.qortal.api.model.crosschain.TradeBotCreateRequest;
|
import org.qortal.api.model.crosschain.TradeBotCreateRequest;
|
||||||
import org.qortal.crosschain.ACCT;
|
import org.qortal.crosschain.ACCT;
|
||||||
import org.qortal.crosschain.ForeignBlockchainException;
|
import org.qortal.crosschain.ForeignBlockchainException;
|
||||||
@ -11,7 +13,10 @@ import org.qortal.repository.Repository;
|
|||||||
|
|
||||||
public interface AcctTradeBot {
|
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;
|
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.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -110,6 +111,10 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
|
|
||||||
private static BitcoinACCTv1TradeBot instance;
|
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() {
|
private BitcoinACCTv1TradeBot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +125,11 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
return instance;
|
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.
|
* Creates a new trade-bot entry from the "Bob" viewpoint, i.e. OFFERing QORT in exchange for BTC.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -3,8 +3,10 @@ package org.qortal.controller.tradebot;
|
|||||||
import static java.util.Arrays.stream;
|
import static java.util.Arrays.stream;
|
||||||
import static java.util.stream.Collectors.toMap;
|
import static java.util.stream.Collectors.toMap;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -102,6 +104,10 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
|
|
||||||
private static LitecoinACCTv1TradeBot instance;
|
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() {
|
private LitecoinACCTv1TradeBot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +118,11 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
return instance;
|
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.
|
* Creates a new trade-bot entry from the "Bob" viewpoint, i.e. OFFERing QORT in exchange for LTC.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -176,6 +176,10 @@ public class TradeBot implements Listener {
|
|||||||
return ResponseResult.NETWORK_ISSUE;
|
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);
|
return acctTradeBot.startResponse(repository, atData, acct, crossChainTradeData, foreignKey, receivingAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,9 @@ public interface CrossChainRepository {
|
|||||||
|
|
||||||
public TradeBotData getTradeBotData(byte[] tradePrivateKey) throws DataException;
|
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 List<TradeBotData> getAllTradeBotData() throws DataException;
|
||||||
|
|
||||||
public void save(TradeBotData tradeBotData) 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.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.qortal.data.crosschain.TradeBotData;
|
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
|
@Override
|
||||||
public List<TradeBotData> getAllTradeBotData() throws DataException {
|
public List<TradeBotData> getAllTradeBotData() throws DataException {
|
||||||
String sql = "SELECT trade_private_key, acct_name, trade_state, trade_state_value, "
|
String sql = "SELECT trade_private_key, acct_name, trade_state, trade_state_value, "
|
||||||
|
Loading…
x
Reference in New Issue
Block a user