mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-22 20:26:50 +00:00
Asset trading: refund saving due to price improvement back to initiator
Added test case to cover the above. Also improve test harness to properly check balances after orphan back to genesis.
This commit is contained in:
@@ -410,12 +410,20 @@ public class Order {
|
||||
throw new DataException(message);
|
||||
}
|
||||
|
||||
// Construct trade
|
||||
BigDecimal tradedWantAmount = (isOurOrderNewPricing && wantAssetId < haveAssetId) ? returnAmountTraded : matchedAmount;
|
||||
BigDecimal tradedWantAmount = (isOurOrderNewPricing && haveAssetId > wantAssetId) ? returnAmountTraded : matchedAmount;
|
||||
BigDecimal tradedHaveAmount = (isOurOrderNewPricing && haveAssetId > wantAssetId) ? matchedAmount : returnAmountTraded;
|
||||
|
||||
TradeData tradeData = new TradeData(this.orderData.getOrderId(), theirOrderData.getOrderId(), tradedWantAmount, tradedHaveAmount,
|
||||
this.orderData.getTimestamp());
|
||||
// We also need to know how much have-asset to refund based on price improvement ('new' pricing only)
|
||||
BigDecimal haveAssetRefund = !isOurOrderNewPricing ? BigDecimal.ZERO : ourPrice.subtract(theirPrice).abs().multiply(tradedWantAmount).setScale(8, RoundingMode.DOWN);
|
||||
|
||||
LOGGER.trace(String.format("We traded %s %s (have-asset) for %s %s (want-asset), saving %s %s (have-asset)",
|
||||
tradedHaveAmount.toPlainString(), haveAssetData.getName(),
|
||||
tradedWantAmount.toPlainString(), wantAssetData.getName(),
|
||||
haveAssetRefund.toPlainString(), haveAssetData.getName()));
|
||||
|
||||
// Construct trade
|
||||
TradeData tradeData = new TradeData(this.orderData.getOrderId(), theirOrderData.getOrderId(),
|
||||
tradedWantAmount, tradedHaveAmount, haveAssetRefund, this.orderData.getTimestamp());
|
||||
// Process trade, updating corresponding orders in repository
|
||||
Trade trade = new Trade(this.repository, tradeData);
|
||||
trade.process();
|
||||
|
@@ -17,36 +17,54 @@ public class Trade {
|
||||
private Repository repository;
|
||||
private TradeData tradeData;
|
||||
|
||||
private boolean isNewPricing;
|
||||
private AssetRepository assetRepository;
|
||||
|
||||
private OrderData initiatingOrder;
|
||||
private OrderData targetOrder;
|
||||
private BigDecimal newPricingFulfilled;
|
||||
|
||||
// Constructors
|
||||
|
||||
public Trade(Repository repository, TradeData tradeData) {
|
||||
this.repository = repository;
|
||||
this.tradeData = tradeData;
|
||||
|
||||
this.isNewPricing = this.tradeData.getTimestamp() > BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
this.assetRepository = this.repository.getAssetRepository();
|
||||
}
|
||||
|
||||
// Processing
|
||||
|
||||
public void process() throws DataException {
|
||||
AssetRepository assetRepository = this.repository.getAssetRepository();
|
||||
private void commonPrep() throws DataException {
|
||||
this.initiatingOrder = assetRepository.fromOrderId(this.tradeData.getInitiator());
|
||||
this.targetOrder = assetRepository.fromOrderId(this.tradeData.getTarget());
|
||||
|
||||
// Note: targetAmount is amount traded FROM target order
|
||||
// Note: initiatorAmount is amount traded FROM initiating order
|
||||
|
||||
// Under 'new' pricing scheme, "amount" and "fulfilled" are the same asset for both orders
|
||||
// which is the matchedAmount in asset with highest assetID
|
||||
this.newPricingFulfilled = (initiatingOrder.getHaveAssetId() < initiatingOrder.getWantAssetId()) ? this.tradeData.getTargetAmount() : this.tradeData.getInitiatorAmount();
|
||||
}
|
||||
|
||||
public void process() throws DataException {
|
||||
// Save trade into repository
|
||||
assetRepository.save(tradeData);
|
||||
|
||||
// Note: targetAmount is amount traded FROM target order
|
||||
// Note: initiatorAmount is amount traded FROM initiating order
|
||||
|
||||
// Update corresponding Orders on both sides of trade
|
||||
OrderData initiatingOrder = assetRepository.fromOrderId(this.tradeData.getInitiator());
|
||||
OrderData targetOrder = assetRepository.fromOrderId(this.tradeData.getTarget());
|
||||
commonPrep();
|
||||
|
||||
// Under 'new' pricing scheme, "amount" and "fulfilled" are the same asset for both orders
|
||||
boolean isNewPricing = initiatingOrder.getTimestamp() > BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
BigDecimal newPricingAmount = (initiatingOrder.getHaveAssetId() < initiatingOrder.getWantAssetId()) ? this.tradeData.getTargetAmount() : this.tradeData.getInitiatorAmount();
|
||||
|
||||
initiatingOrder.setFulfilled(initiatingOrder.getFulfilled().add(isNewPricing ? newPricingAmount : tradeData.getInitiatorAmount()));
|
||||
initiatingOrder.setFulfilled(initiatingOrder.getFulfilled().add(isNewPricing ? newPricingFulfilled : tradeData.getInitiatorAmount()));
|
||||
initiatingOrder.setIsFulfilled(Order.isFulfilled(initiatingOrder));
|
||||
// Set isClosed to true if isFulfilled now true
|
||||
initiatingOrder.setIsClosed(initiatingOrder.getIsFulfilled());
|
||||
assetRepository.save(initiatingOrder);
|
||||
|
||||
targetOrder.setFulfilled(targetOrder.getFulfilled().add(isNewPricing ? newPricingAmount : tradeData.getTargetAmount()));
|
||||
targetOrder.setFulfilled(targetOrder.getFulfilled().add(isNewPricing ? newPricingFulfilled : tradeData.getTargetAmount()));
|
||||
targetOrder.setIsFulfilled(Order.isFulfilled(targetOrder));
|
||||
// Set isClosed to true if isFulfilled now true
|
||||
targetOrder.setIsClosed(targetOrder.getIsFulfilled());
|
||||
@@ -54,32 +72,33 @@ public class Trade {
|
||||
|
||||
// Actually transfer asset balances
|
||||
Account initiatingCreator = new PublicKeyAccount(this.repository, initiatingOrder.getCreatorPublicKey());
|
||||
initiatingCreator.setConfirmedBalance(initiatingOrder.getWantAssetId(),
|
||||
initiatingCreator.getConfirmedBalance(initiatingOrder.getWantAssetId()).add(tradeData.getTargetAmount()));
|
||||
initiatingCreator.setConfirmedBalance(initiatingOrder.getWantAssetId(), initiatingCreator.getConfirmedBalance(initiatingOrder.getWantAssetId()).add(tradeData.getTargetAmount()));
|
||||
|
||||
Account targetCreator = new PublicKeyAccount(this.repository, targetOrder.getCreatorPublicKey());
|
||||
targetCreator.setConfirmedBalance(targetOrder.getWantAssetId(),
|
||||
targetCreator.getConfirmedBalance(targetOrder.getWantAssetId()).add(tradeData.getInitiatorAmount()));
|
||||
targetCreator.setConfirmedBalance(targetOrder.getWantAssetId(), targetCreator.getConfirmedBalance(targetOrder.getWantAssetId()).add(tradeData.getInitiatorAmount()));
|
||||
|
||||
// Possible partial saving to refund to initiator
|
||||
BigDecimal initiatorSaving = this.tradeData.getInitiatorSaving();
|
||||
if (initiatorSaving.compareTo(BigDecimal.ZERO) > 0)
|
||||
initiatingCreator.setConfirmedBalance(initiatingOrder.getHaveAssetId(), initiatingCreator.getConfirmedBalance(initiatingOrder.getHaveAssetId()).add(initiatorSaving));
|
||||
}
|
||||
|
||||
public void orphan() throws DataException {
|
||||
AssetRepository assetRepository = this.repository.getAssetRepository();
|
||||
|
||||
// Note: targetAmount is amount traded FROM target order
|
||||
// Note: initiatorAmount is amount traded FROM initiating order
|
||||
|
||||
// Revert corresponding Orders on both sides of trade
|
||||
OrderData initiatingOrder = assetRepository.fromOrderId(this.tradeData.getInitiator());
|
||||
OrderData targetOrder = assetRepository.fromOrderId(this.tradeData.getTarget());
|
||||
commonPrep();
|
||||
|
||||
// Under 'new' pricing scheme, "amount" and "fulfilled" are the same asset for both orders
|
||||
boolean isNewPricing = initiatingOrder.getTimestamp() > BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
BigDecimal newPricingAmount = (initiatingOrder.getHaveAssetId() < initiatingOrder.getWantAssetId()) ? this.tradeData.getTargetAmount() : this.tradeData.getInitiatorAmount();
|
||||
|
||||
initiatingOrder.setFulfilled(initiatingOrder.getFulfilled().subtract(isNewPricing ? newPricingAmount : tradeData.getInitiatorAmount()));
|
||||
initiatingOrder.setFulfilled(initiatingOrder.getFulfilled().subtract(isNewPricing ? newPricingFulfilled : tradeData.getInitiatorAmount()));
|
||||
initiatingOrder.setIsFulfilled(Order.isFulfilled(initiatingOrder));
|
||||
// Set isClosed to false if isFulfilled now false
|
||||
initiatingOrder.setIsClosed(initiatingOrder.getIsFulfilled());
|
||||
assetRepository.save(initiatingOrder);
|
||||
|
||||
targetOrder.setFulfilled(targetOrder.getFulfilled().subtract(isNewPricing ? newPricingAmount : tradeData.getTargetAmount()));
|
||||
targetOrder.setFulfilled(targetOrder.getFulfilled().subtract(isNewPricing ? newPricingFulfilled : tradeData.getTargetAmount()));
|
||||
targetOrder.setIsFulfilled(Order.isFulfilled(targetOrder));
|
||||
// Set isClosed to false if isFulfilled now false
|
||||
targetOrder.setIsClosed(targetOrder.getIsFulfilled());
|
||||
@@ -87,12 +106,15 @@ public class Trade {
|
||||
|
||||
// Reverse asset transfers
|
||||
Account initiatingCreator = new PublicKeyAccount(this.repository, initiatingOrder.getCreatorPublicKey());
|
||||
initiatingCreator.setConfirmedBalance(initiatingOrder.getWantAssetId(),
|
||||
initiatingCreator.getConfirmedBalance(initiatingOrder.getWantAssetId()).subtract(tradeData.getTargetAmount()));
|
||||
initiatingCreator.setConfirmedBalance(initiatingOrder.getWantAssetId(), initiatingCreator.getConfirmedBalance(initiatingOrder.getWantAssetId()).subtract(tradeData.getTargetAmount()));
|
||||
|
||||
Account targetCreator = new PublicKeyAccount(this.repository, targetOrder.getCreatorPublicKey());
|
||||
targetCreator.setConfirmedBalance(targetOrder.getWantAssetId(),
|
||||
targetCreator.getConfirmedBalance(targetOrder.getWantAssetId()).subtract(tradeData.getInitiatorAmount()));
|
||||
targetCreator.setConfirmedBalance(targetOrder.getWantAssetId(), targetCreator.getConfirmedBalance(targetOrder.getWantAssetId()).subtract(tradeData.getInitiatorAmount()));
|
||||
|
||||
// Possible partial saving to claw back from initiator
|
||||
BigDecimal initiatorSaving = this.tradeData.getInitiatorSaving();
|
||||
if (initiatorSaving.compareTo(BigDecimal.ZERO) > 0)
|
||||
initiatingCreator.setConfirmedBalance(initiatingOrder.getHaveAssetId(), initiatingCreator.getConfirmedBalance(initiatingOrder.getHaveAssetId()).subtract(initiatorSaving));
|
||||
|
||||
// Remove trade from repository
|
||||
assetRepository.delete(tradeData);
|
||||
|
@@ -2,13 +2,16 @@ package org.qora.data.asset;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
|
||||
|
||||
// All properties to be converted to JSON via JAX-RS
|
||||
// All properties to be converted to JSON via JAXB
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class TradeData {
|
||||
|
||||
@@ -21,29 +24,94 @@ public class TradeData {
|
||||
@XmlElement(name = "targetOrderId")
|
||||
private byte[] target;
|
||||
|
||||
@Schema(name = "targetAmount", description = "amount traded from target order")
|
||||
@Schema(name = "targetAmount", description = "amount traded from target")
|
||||
@XmlElement(name = "targetAmount")
|
||||
private BigDecimal targetAmount;
|
||||
|
||||
@Schema(name = "initiatorAmount", description = "amount traded from initiating order")
|
||||
@Schema(name = "initiatorAmount", description = "amount traded from initiator")
|
||||
@XmlElement(name = "initiatorAmount")
|
||||
private BigDecimal initiatorAmount;
|
||||
|
||||
@Schema(name = "initiatorSaving", description = "amount refunded to initiator due to price improvement")
|
||||
@XmlElement(name = "initiatorSaving")
|
||||
private BigDecimal initiatorSaving;
|
||||
|
||||
@Schema(description = "when trade happened")
|
||||
private long timestamp;
|
||||
|
||||
// Used by API - not always present
|
||||
@Schema(hidden = true)
|
||||
@XmlTransient
|
||||
private Long haveAssetId;
|
||||
|
||||
@Schema(hidden = true)
|
||||
@XmlTransient
|
||||
private String haveAssetName;
|
||||
|
||||
@Schema(hidden = true)
|
||||
@XmlTransient
|
||||
private Long wantAssetId;
|
||||
|
||||
@Schema(hidden = true)
|
||||
@XmlTransient
|
||||
private String wantAssetName;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private Long targetAmountAssetId;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String targetAmountAssetName;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private Long initiatorAmountAssetId;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String initiatorAmountAssetName;
|
||||
|
||||
// Constructors
|
||||
|
||||
// necessary for JAX-RS serialization
|
||||
// Necessary for JAXB
|
||||
protected TradeData() {
|
||||
}
|
||||
|
||||
public TradeData(byte[] initiator, byte[] target, BigDecimal targetAmount, BigDecimal initiatorAmount, long timestamp) {
|
||||
// Called before converting to JSON for API
|
||||
public void beforeMarshal(Marshaller m) {
|
||||
// If we don't have the extra asset name fields then we can't fill in the others
|
||||
if (this.haveAssetName == null)
|
||||
return;
|
||||
|
||||
// have-asset and want-asset are from the viewpoint of the initiator
|
||||
// and amounts are FROM initiator/target
|
||||
if (this.haveAssetId < this.wantAssetId) {
|
||||
this.initiatorAmountAssetId = this.haveAssetId;
|
||||
this.initiatorAmountAssetName = this.haveAssetName;
|
||||
this.targetAmountAssetId = this.wantAssetId;
|
||||
this.targetAmountAssetName = this.wantAssetName;
|
||||
} else {
|
||||
this.initiatorAmountAssetId = this.wantAssetId;
|
||||
this.initiatorAmountAssetName = this.wantAssetName;
|
||||
this.targetAmountAssetId = this.haveAssetId;
|
||||
this.targetAmountAssetName = this.haveAssetName;
|
||||
}
|
||||
}
|
||||
|
||||
public TradeData(byte[] initiator, byte[] target, BigDecimal targetAmount, BigDecimal initiatorAmount, BigDecimal initiatorSaving, long timestamp,
|
||||
Long haveAssetId, String haveAssetName, Long wantAssetId, String wantAssetName) {
|
||||
this.initiator = initiator;
|
||||
this.target = target;
|
||||
this.targetAmount = targetAmount;
|
||||
this.initiatorAmount = initiatorAmount;
|
||||
this.initiatorSaving = initiatorSaving;
|
||||
this.timestamp = timestamp;
|
||||
|
||||
this.haveAssetId = haveAssetId;
|
||||
this.haveAssetName = haveAssetName;
|
||||
this.wantAssetId = wantAssetId;
|
||||
this.wantAssetName = wantAssetName;
|
||||
}
|
||||
|
||||
public TradeData(byte[] initiator, byte[] target, BigDecimal targetAmount, BigDecimal initiatorAmount, BigDecimal initiatorSaving, long timestamp) {
|
||||
this(initiator, target, targetAmount, initiatorAmount, initiatorSaving, timestamp, null, null, null, null);
|
||||
}
|
||||
|
||||
// Getters/setters
|
||||
@@ -64,6 +132,10 @@ public class TradeData {
|
||||
return this.initiatorAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getInitiatorSaving() {
|
||||
return this.initiatorSaving;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
@@ -510,14 +510,26 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
@Override
|
||||
public List<TradeData> getTrades(long haveAssetId, long wantAssetId, Integer limit, Integer offset, Boolean reverse)
|
||||
throws DataException {
|
||||
String sql = "SELECT initiating_order_id, target_order_id, AssetTrades.target_amount, AssetTrades.initiator_amount, traded "
|
||||
List<TradeData> trades = new ArrayList<TradeData>();
|
||||
|
||||
// Cache have & want asset names for later use, which also saves a table join
|
||||
AssetData haveAssetData = this.fromAssetId(haveAssetId);
|
||||
if (haveAssetData == null)
|
||||
return trades;
|
||||
|
||||
AssetData wantAssetData = this.fromAssetId(wantAssetId);
|
||||
if (wantAssetData == null)
|
||||
return trades;
|
||||
|
||||
String sql = "SELECT initiating_order_id, target_order_id, target_amount, initiator_amount, initiator_saving, traded "
|
||||
+ "FROM AssetOrders JOIN AssetTrades ON initiating_order_id = asset_order_id "
|
||||
+ "WHERE have_asset_id = ? AND want_asset_id = ? ORDER BY traded";
|
||||
+ "WHERE have_asset_id = ? AND want_asset_id = ? ";
|
||||
|
||||
sql += "ORDER BY traded";
|
||||
if (reverse != null && reverse)
|
||||
sql += " DESC";
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
List<TradeData> trades = new ArrayList<TradeData>();
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, haveAssetId, wantAssetId)) {
|
||||
if (resultSet == null)
|
||||
@@ -528,10 +540,11 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
byte[] targetOrderId = resultSet.getBytes(2);
|
||||
BigDecimal targetAmount = resultSet.getBigDecimal(3);
|
||||
BigDecimal initiatorAmount = resultSet.getBigDecimal(4);
|
||||
long timestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
|
||||
BigDecimal initiatorSaving = resultSet.getBigDecimal(5);
|
||||
long timestamp = resultSet.getTimestamp(6, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
|
||||
|
||||
TradeData trade = new TradeData(initiatingOrderId, targetOrderId, targetAmount, initiatorAmount,
|
||||
timestamp);
|
||||
TradeData trade = new TradeData(initiatingOrderId, targetOrderId, targetAmount, initiatorAmount, initiatorSaving,
|
||||
timestamp, haveAssetId, haveAssetData.getName(), wantAssetId, wantAssetData.getName());
|
||||
trades.add(trade);
|
||||
} while (resultSet.next());
|
||||
|
||||
@@ -613,15 +626,23 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
@Override
|
||||
public List<TradeData> getOrdersTrades(byte[] orderId, Integer limit, Integer offset, Boolean reverse)
|
||||
throws DataException {
|
||||
String sql = "SELECT initiating_order_id, target_order_id, target_amount, initiator_amount, traded "
|
||||
+ "FROM AssetTrades WHERE initiating_order_id = ? OR target_order_id = ? ORDER BY traded";
|
||||
String sql = "SELECT initiating_order_id, target_order_id, target_amount, initiator_amount, initiator_saving, traded, "
|
||||
+ "have_asset_id, HaveAsset.asset_name, want_asset_id, WantAsset.asset_name "
|
||||
+ "FROM AssetTrades "
|
||||
+ "JOIN AssetOrders ON asset_order_id = initiating_order_id "
|
||||
+ "JOIN Assets AS HaveAsset ON HaveAsset.asset_id = have_asset_id "
|
||||
+ "JOIN Assets AS WantAsset ON WantAsset.asset_id = want_asset_id "
|
||||
+ "WHERE ? IN (initiating_order_id, target_order_id)";
|
||||
|
||||
sql += "ORDER BY traded";
|
||||
if (reverse != null && reverse)
|
||||
sql += " DESC";
|
||||
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
List<TradeData> trades = new ArrayList<TradeData>();
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, orderId, orderId)) {
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, orderId)) {
|
||||
if (resultSet == null)
|
||||
return trades;
|
||||
|
||||
@@ -630,10 +651,16 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
byte[] targetOrderId = resultSet.getBytes(2);
|
||||
BigDecimal targetAmount = resultSet.getBigDecimal(3);
|
||||
BigDecimal initiatorAmount = resultSet.getBigDecimal(4);
|
||||
long timestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
|
||||
BigDecimal initiatorSaving = resultSet.getBigDecimal(5);
|
||||
long timestamp = resultSet.getTimestamp(6, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
|
||||
|
||||
TradeData trade = new TradeData(initiatingOrderId, targetOrderId, targetAmount, initiatorAmount,
|
||||
timestamp);
|
||||
long haveAssetId = resultSet.getLong(7);
|
||||
String haveAssetName = resultSet.getString(8);
|
||||
long wantAssetId = resultSet.getLong(9);
|
||||
String wantAssetName = resultSet.getString(10);
|
||||
|
||||
TradeData trade = new TradeData(initiatingOrderId, targetOrderId, targetAmount, initiatorAmount, initiatorSaving, timestamp,
|
||||
haveAssetId, haveAssetName, wantAssetId, wantAssetName);
|
||||
trades.add(trade);
|
||||
} while (resultSet.next());
|
||||
|
||||
@@ -648,9 +675,8 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
HSQLDBSaver saveHelper = new HSQLDBSaver("AssetTrades");
|
||||
|
||||
saveHelper.bind("initiating_order_id", tradeData.getInitiator()).bind("target_order_id", tradeData.getTarget())
|
||||
.bind("target_amount", tradeData.getTargetAmount())
|
||||
.bind("initiator_amount", tradeData.getInitiatorAmount())
|
||||
.bind("traded", new Timestamp(tradeData.getTimestamp()));
|
||||
.bind("target_amount", tradeData.getTargetAmount()).bind("initiator_amount", tradeData.getInitiatorAmount())
|
||||
.bind("initiator_saving", tradeData.getInitiatorSaving()).bind("traded", new Timestamp(tradeData.getTimestamp()));
|
||||
|
||||
try {
|
||||
saveHelper.execute(this.repository);
|
||||
|
@@ -685,6 +685,11 @@ public class HSQLDBDatabaseUpdates {
|
||||
stmt.execute("SET TIME ZONE LOCAL");
|
||||
break;
|
||||
|
||||
case 43:
|
||||
// More work on 'new' asset pricing - refunds due to price improvement
|
||||
stmt.execute("ALTER TABLE AssetTrades ADD initiator_saving QoraAmount NOT NULL DEFAULT 0");
|
||||
break;
|
||||
|
||||
default:
|
||||
// nothing to do
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user