Browse Source

Initial skeleton code for Trade Bot

pull/16/head
catbref 4 years ago
parent
commit
ead84d70d1
  1. 4
      src/main/java/org/qortal/controller/Controller.java
  2. 27
      src/main/java/org/qortal/controller/TradeBot.java
  3. 97
      src/main/java/org/qortal/data/crosschain/TradeBotData.java
  4. 11
      src/main/java/org/qortal/repository/CrossChainRepository.java
  5. 2
      src/main/java/org/qortal/repository/Repository.java
  6. 52
      src/main/java/org/qortal/repository/hsqldb/HSQLDBCrossChainRepository.java
  7. 7
      src/main/java/org/qortal/repository/hsqldb/HSQLDBDatabaseUpdates.java
  8. 6
      src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java

4
src/main/java/org/qortal/controller/Controller.java

@ -238,9 +238,11 @@ public class Controller extends Thread {
return this.chainTip;
}
/** Cache new blockchain tip. */
/** Cache new blockchain tip, maybe call trade-bot. */
public void setChainTip(BlockData blockData) {
this.chainTip = blockData;
TradeBot.getInstance().onChainTipChange();
}
public ReentrantLock getBlockchainLock() {

27
src/main/java/org/qortal/controller/TradeBot.java

@ -0,0 +1,27 @@
package org.qortal.controller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class TradeBot {
private static final Logger LOGGER = LogManager.getLogger(TradeBot.class);
private static TradeBot instance;
private TradeBot() {
}
public static synchronized TradeBot getInstance() {
if (instance == null)
instance = new TradeBot();
return instance;
}
public void onChainTipChange() {
// Get repo for trade situations
}
}

97
src/main/java/org/qortal/data/crosschain/TradeBotData.java

@ -0,0 +1,97 @@
package org.qortal.data.crosschain;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
import io.swagger.v3.oas.annotations.media.Schema;
// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
public class TradeBotData {
public enum State {
BOB_START(0), BOB_WAITING_FOR_P2SH_A(10), BOB_WAITING_FOR_P2SH_B(20), BOB_WAITING_FOR_AT_REDEEM(30),
ALICE_START(100), ALICE_WAITING_FOR_P2SH_A(110), ALICE_WAITING_FOR_AT_LOCK(120), ALICE_WATCH_P2SH_B(130);
public final int value;
private static final Map<Integer, State> map = stream(State.values()).collect(toMap(state -> state.value, state -> state));
State(int value) {
this.value = value;
}
public static State valueOf(int value) {
return map.get(value);
}
}
private State tradeState;
// Never expose this
@XmlTransient
@Schema(hidden = true)
private byte[] tradePrivateKey;
private byte[] secret;
private String atAddress;
private byte[] lastTransactionSignature;
public TradeBotData(byte[] tradePrivateKey, State tradeState, byte[] secret, String atAddress,
byte[] lastTransactionSignature) {
this.tradePrivateKey = tradePrivateKey;
this.tradeState = tradeState;
this.secret = secret;
this.atAddress = atAddress;
this.lastTransactionSignature = lastTransactionSignature;
}
public TradeBotData(byte[] tradePrivateKey, State tradeState) {
this.tradePrivateKey = tradePrivateKey;
this.tradeState = tradeState;
}
public State getState() {
return this.tradeState;
}
public void setState(State state) {
this.tradeState = state;
}
public byte[] getSecret() {
return this.secret;
}
public void setSecret(byte[] secret) {
this.secret = secret;
}
public byte[] getTradePrivateKey() {
return this.tradePrivateKey;
}
public String getAtAddress() {
return this.atAddress;
}
public void setAtAddress(String atAddress) {
this.atAddress = atAddress;
}
public byte[] getLastTransactionSignature() {
return this.lastTransactionSignature;
}
public void setLastTransactionSignature(byte[] lastTransactionSignature) {
this.lastTransactionSignature = lastTransactionSignature;
}
}

11
src/main/java/org/qortal/repository/CrossChainRepository.java

@ -0,0 +1,11 @@
package org.qortal.repository;
import java.util.List;
import org.qortal.data.crosschain.TradeBotData;
public interface CrossChainRepository {
public List<TradeBotData> getAllTradeBotData() throws DataException;
}

2
src/main/java/org/qortal/repository/Repository.java

@ -14,6 +14,8 @@ public interface Repository extends AutoCloseable {
public ChatRepository getChatRepository();
public CrossChainRepository getCrossChainRepository();
public GroupRepository getGroupRepository();
public NameRepository getNameRepository();

52
src/main/java/org/qortal/repository/hsqldb/HSQLDBCrossChainRepository.java

@ -0,0 +1,52 @@
package org.qortal.repository.hsqldb;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.qortal.data.crosschain.TradeBotData;
import org.qortal.repository.CrossChainRepository;
import org.qortal.repository.DataException;
public class HSQLDBCrossChainRepository implements CrossChainRepository {
protected HSQLDBRepository repository;
public HSQLDBCrossChainRepository(HSQLDBRepository repository) {
this.repository = repository;
}
@Override
public List<TradeBotData> getAllTradeBotData() throws DataException {
String sql = "SELECT trade_private_key, trade_state, secret, at_address, last_transaction_signature "
+ "FROM TradeBotStates";
List<TradeBotData> allTradeBotData = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql)) {
if (resultSet == null)
return allTradeBotData;
do {
byte[] tradePrivateKey = resultSet.getBytes(1);
int tradeStateValue = resultSet.getInt(2);
TradeBotData.State tradeState = TradeBotData.State.valueOf(tradeStateValue);
if (tradeState == null)
throw new DataException("Illegal trade-bot trade-state fetched from repository");
byte[] secret = resultSet.getBytes(3);
String atAddress = resultSet.getString(4);
byte[] lastTransactionSignature = resultSet.getBytes(5);
TradeBotData tradeBotData = new TradeBotData(tradePrivateKey, tradeState, secret, atAddress, lastTransactionSignature);
allTradeBotData.add(tradeBotData);
} while (resultSet.next());
return allTradeBotData;
} catch (SQLException e) {
throw new DataException("Unable to fetch trade-bot trading states from repository", e);
}
}
}

7
src/main/java/org/qortal/repository/hsqldb/HSQLDBDatabaseUpdates.java

@ -618,6 +618,13 @@ public class HSQLDBDatabaseUpdates {
stmt.execute("CREATE TABLE PublicizeTransactions (signature Signature, nonce INT NOT NULL, " + TRANSACTION_KEYS + ")");
break;
case 20:
// Trade bot
stmt.execute("CREATE TABLE TradeBotStates (trade_private_key QortalPrivateKey NOT NULL, trade_state TINYINT NOT NULL, "
+ "secret VARBINARY(32) NOT NULL, at_address QortalAddress, "
+ "last_transaction_signature Signature, PRIMARY KEY (trade_private_key)");
break;
default:
// nothing to do
return false;

6
src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java

@ -32,6 +32,7 @@ import org.qortal.repository.ArbitraryRepository;
import org.qortal.repository.AssetRepository;
import org.qortal.repository.BlockRepository;
import org.qortal.repository.ChatRepository;
import org.qortal.repository.CrossChainRepository;
import org.qortal.repository.DataException;
import org.qortal.repository.GroupRepository;
import org.qortal.repository.NameRepository;
@ -115,6 +116,11 @@ public class HSQLDBRepository implements Repository {
return new HSQLDBChatRepository(this);
}
@Override
public CrossChainRepository getCrossChainRepository() {
return new HSQLDBCrossChainRepository(this);
}
@Override
public GroupRepository getGroupRepository() {
return new HSQLDBGroupRepository(this);

Loading…
Cancel
Save