Merge branch 'offerlist' into DAO

# Conflicts:
#	core/src/main/java/io/bisq/core/trade/TradableList.java
#	core/src/main/java/io/bisq/core/trade/protocol/ProcessModel.java
#	core/src/test/java/io/bisq/core/util/ProtoBufferUtilitiesTest.java
This commit is contained in:
Manfred Karrer 2017-05-14 14:48:20 +02:00
commit f7ef638b1c
39 changed files with 930 additions and 660 deletions

View file

@ -3,9 +3,17 @@
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<JavaCodeStyleSettings>
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
</JavaCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="JAVA">
<option name="METHOD_ANNOTATION_WRAP" value="0" />
<option name="CLASS_ANNOTATION_WRAP" value="0" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
</codeStyleSettings>
</value>
</option>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />

View file

@ -38,8 +38,7 @@ public class KeyRing {
// We generate by default a PGP keypair but the user can set his own if he prefers.
// Not impl. yet but prepared in data structure
@Setter
@Nullable
@Nullable @Setter
// TODO remove Nullable once impl.
private PGPKeyPair pgpKeyPair;

View file

@ -190,13 +190,13 @@ public class FileManager<T extends PersistableEnvelope> {
PrintWriter printWriter = null;
log.error("persistable.class " + persistable.getClass().getSimpleName());
// log.error("persistable " + persistable);
log.error("persistable " + persistable);
PB.PersistableEnvelope protoPersistable = null;
try {
protoPersistable = (PB.PersistableEnvelope) persistable.toProtoMessage();
//log.error("protoPersistable " + protoPersistable);
log.error("protoPersistable " + protoPersistable);
} catch (Throwable e) {
log.debug("Not protobufferable: {}, {}, {}", persistable.getClass().getSimpleName(), storageFile, e.getStackTrace());
log.error("Not protobufferable: {}, {}, {}", persistable.getClass().getSimpleName(), storageFile, e.getStackTrace());
}
try {

View file

@ -491,8 +491,9 @@ message MailboxStoragePayload {
message OfferPayload {
enum Direction {
BUY = 0;
SELL = 1;
PB_ERROR = 0;
BUY = 1;
SELL = 2;
}
Direction direction = 1;
@ -574,19 +575,20 @@ message Attachment {
message DisputeResult {
enum Winner {
BUYER = 0;
SELLER = 1;
PB_ERROR_WINNER = 0;
BUYER = 1;
SELLER = 2;
}
// only append new values as we use the ordinal value
enum Reason {
OTHER = 0;
BUG = 1;
USABILITY = 2;
SCAM = 3;
PROTOCOL_VIOLATION = 4;
NO_REPLY = 5;
BANK_PROBLEMS = 6;
PB_ERROR_REASON = 0;
OTHER = 1;
BUG = 2;
USABILITY = 3;
SCAM = 4;
PROTOCOL_VIOLATION = 5;
NO_REPLY = 6;
BANK_PROBLEMS = 7;
}
string trade_id = 1;
@ -641,14 +643,15 @@ message RawTransactionInput {
}
enum AvailabilityResult {
UNKNOWN_FAILURE = 0; // 0 is the default value when something goes wrong, map it to failure
AVAILABLE = 1;
OFFER_TAKEN = 2;
PRICE_OUT_OF_TOLERANCE = 3;
MARKET_PRICE_NOT_AVAILABLE = 4;
NO_ARBITRATORS = 5;
NO_MEDIATORS = 6;
USER_IGNORED = 7;
PB_ERROR = 0;
UNKNOWN_FAILURE = 1;
AVAILABLE = 2;
OFFER_TAKEN = 3;
PRICE_OUT_OF_TOLERANCE = 4;
MARKET_PRICE_NOT_AVAILABLE = 5;
NO_ARBITRATORS = 6;
NO_MEDIATORS = 7;
USER_IGNORED = 8;
}
@ -808,13 +811,17 @@ message PersistableEnvelope {
PersistedEntryMap persisted_entry_map = 8;
TradeStatisticsList trade_statistics_list = 9;
VoteItemsList vote_items_list = 10;
OpenOfferList open_offer_list = 11;
TradableList tradable_list = 11;
TradeList trade_list = 16;
OpenOfferList open_offer_list = 17;
//TODO
PendingTradeList pending_trade_list = 12;
ClosedTradeList closed_trade_list = 13;
FailedTradeList failed_trade_list = 14;
BsqChainState bsq_chain_state = 15;
// TODO remove
TradableList tradable_list = 16;
}
}
@ -886,12 +893,13 @@ message UserPayload {
message AddressEntry {
enum Context {
ARBITRATOR = 0;
AVAILABLE = 1;
OFFER_FUNDING = 2;
RESERVED_FOR_TRADE = 3;
MULTI_SIG = 4;
TRADE_PAYOUT = 5;
PB_ERROR = 0;
ARBITRATOR = 1;
AVAILABLE = 2;
OFFER_FUNDING = 3;
RESERVED_FOR_TRADE = 4;
MULTI_SIG = 5;
TRADE_PAYOUT = 6;
}
string offer_id = 7;
@ -912,12 +920,13 @@ message AddressEntryList {
message Offer {
enum State {
UNDEFINED = 0;
OFFER_FEE_PAID = 1;
AVAILABLE = 2;
NOT_AVAILABLE = 3;
REMOVED = 4;
MAKER_OFFLINE = 5;
PB_ERROR = 0;
UNKNOWN = 1;
OFFER_FEE_PAID = 2;
AVAILABLE = 3;
NOT_AVAILABLE = 4;
REMOVED = 5;
MAKER_OFFLINE = 6;
}
OfferPayload offer_payload = 1;
@ -925,7 +934,7 @@ message Offer {
message OpenOffer {
enum State {
UNKNOWN_FAILURE = 0;
PB_ERROR = 0;
AVAILABLE = 1;
RESERVED = 2;
CLOSED = 3;
@ -950,61 +959,76 @@ message TradableList {
repeated Tradable tradable = 1;
}
message OpenOfferList {
repeated OpenOffer open_offer = 1;
}
message TradeList {
repeated Trade trade = 1;
}
message Trade {
enum State {
UNKNOWN_FAILURE = 0;
PB_ERROR_STATE = 0;
PREPARATION = 1;
TAKER_FEE_PAID = 2;
OFFERER_SENT_PUBLISH_DEPOSIT_TX_REQUEST = 3;
TAKER_PUBLISHED_DEPOSIT_TX = 4;
DEPOSIT_SEEN_IN_NETWORK = 5;
TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG = 6;
OFFERER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG = 7;
DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN = 8;
BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED = 9;
BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG = 10;
SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG = 11;
SELLER_CONFIRMED_FIAT_PAYMENT_RECEIPT = 12;
SELLER_SENT_FIAT_PAYMENT_RECEIPT_MSG = 13;
BUYER_RECEIVED_FIAT_PAYMENT_RECEIPT_MSG = 14;
BUYER_COMMITTED_PAYOUT_TX = 15;
BUYER_STARTED_SEND_PAYOUT_TX = 16;
SELLER_RECEIVED_AND_COMMITTED_PAYOUT_TX = 17;
PAYOUT_BROAD_CASTED = 18;
WITHDRAW_COMPLETED = 19;
TAKER_PUBLISHED_TAKER_FEE_TX = 2;
MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST = 3;
MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST = 4;
MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST = 5;
MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST = 6;
TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST = 7;
TAKER_PUBLISHED_DEPOSIT_TX = 8;
TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG = 9;
TAKER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG = 10;
TAKER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG = 11;
TAKER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG = 12;
MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG = 13;
MAKER_SAW_DEPOSIT_TX_IN_NETWORK = 14;
DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN = 15;
BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED = 16;
BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG = 17;
BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG = 18;
BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG = 19;
BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG = 20;
SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG = 21;
SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT = 22;
SELLER_PUBLISHED_PAYOUT_TX = 23;
SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG = 24;
SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG = 25;
SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG = 26;
SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG = 27;
BUYER_RECEIVED_PAYOUT_TX_PUBLISHED_MSG = 28;
BUYER_SAW_PAYOUT_TX_IN_NETWORK = 29;
WITHDRAW_COMPLETED = 30;
}
enum Phase {
PHASE_UNKNOWN_FAILURE = 0;
PHASE_PREPARATION = 1;
PHASE_TAKER_FEE_PAID = 2;
DEPOSIT_REQUESTED = 3;
DEPOSIT_PAID = 4;
PB_ERROR_PHASE = 0;
INIT = 1;
TAKER_FEE_PUBLISHED = 2;
DEPOSIT_PUBLISHED = 3;
DEPOSIT_CONFIRMED = 4;
FIAT_SENT = 5;
FIAT_RECEIVED = 6;
PAYOUT_PAID = 7;
PAYOUT_PUBLISHED = 7;
WITHDRAWN = 8;
DISPUT = 9;
}
enum DisputeState {
TRADED_DISPUTE_STATE_UNKNOWN_FAILURE = 0;
NONE = 1;
PB_ERROR_DISPUTE_STATE = 0;
NO_DISPUTE = 1;
DISPUTE_REQUESTED = 2;
DISPUTE_STARTED_BY_PEER = 3;
DISPUTE_CLOSE = 4;
DISPUTE_CLOSED = 4;
}
enum TradePeriodState {
TRADE_PERIOD_STATE_UNKNOWN_FAILURE = 0;
NORMAL = 1;
HALF_REACHED = 2;
PB_ERROR_TRADE_PERIOD_STATE = 0;
FIRST_HALF = 1;
SECOND_HALF = 2;
TRADE_PERIOD_OVER = 3;
}
Offer offer = 1;
ProcessModel process_model = 2;
string taker_fee_tx_id = 3;
@ -1089,20 +1113,16 @@ message TradeStatisticsList {
repeated TradeStatistics trade_statistics = 1;
}
message OpenOfferList {
repeated OpenOffer open_offer = 1;
}
message PendingTradeList {
repeated PendingTradeList trade = 1;
repeated Trade trade = 1;
}
message ClosedTradeList {
repeated ClosedTradeList trade = 1;
repeated Trade trade = 1;
}
message FailedTradeList {
repeated FailedTradeList trade = 1;
repeated Trade trade = 1;
}
@ -1116,11 +1136,11 @@ message BsqChainState {
message VoteItem {
enum VotingType {
UNKNOWN_FAILURE = 0;
CREATE_OFFER_FEE_IN_BTC = 1;
TAKE_OFFER_FEE_IN_BTC = 2;
CREATE_OFFER_FEE_IN_BSQ = 3;
TAKE_OFFER_FEE_IN_BSQ = 4;
PB_ERROR = 0;
MAKER_FEE_IN_BTC = 1;
TAKER_FEE_IN_BTC = 2;
MAKER_FEE_IN_BSQ = 3;
TAKER_FEE_IN_BSQ = 4;
CREATE_COMPENSATION_REQUEST_FEE_IN_BSQ = 5;
VOTING_FEE_IN_BSQ = 6;
COMPENSATION_REQUEST_PERIOD_IN_BLOCKS = 7;

View file

@ -9,4 +9,4 @@ public enum AvailabilityResult {
NO_ARBITRATORS,
NO_MEDIATORS,
USER_IGNORED
}
}

View file

@ -45,7 +45,7 @@ public class Offer implements NetworkPayload, PersistablePayload {
///////////////////////////////////////////////////////////////////////////////////////////
public enum State {
UNDEFINED,
UNKNOWN,
OFFER_FEE_PAID,
AVAILABLE,
NOT_AVAILABLE,
@ -60,9 +60,7 @@ public class Offer implements NetworkPayload, PersistablePayload {
@Getter
private final OfferPayload offerPayload;
@JsonExclude
transient private Offer.State state = Offer.State.UNDEFINED;
// Those state properties are transient and only used at runtime!
// don't access directly as it might be null; use getStateProperty() which creates an object if not instantiated
transient private Offer.State state = Offer.State.UNKNOWN;
@JsonExclude
@Getter
transient private ObjectProperty<Offer.State> stateProperty = new SimpleObjectProperty<>(state);
@ -73,8 +71,7 @@ public class Offer implements NetworkPayload, PersistablePayload {
@Getter
transient private StringProperty errorMessageProperty = new SimpleStringProperty();
@JsonExclude
@Setter
@Nullable
@Nullable @Setter
transient private PriceFeedService priceFeedService;
@ -205,7 +202,7 @@ public class Offer implements NetworkPayload, PersistablePayload {
}
public void resetState() {
setState(Offer.State.UNDEFINED);
setState(Offer.State.UNKNOWN);
}

View file

@ -21,6 +21,7 @@ import io.bisq.common.Timer;
import io.bisq.common.UserThread;
import io.bisq.common.storage.Storage;
import io.bisq.core.trade.Tradable;
import io.bisq.core.trade.TradableList;
import io.bisq.generated.protobuffer.PB;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@ -47,9 +48,9 @@ public final class OpenOffer implements Tradable {
@Getter
private State state = State.AVAILABLE;
transient private Storage<OpenOfferList> storage;
transient private Storage<TradableList<OpenOffer>> storage;
public OpenOffer(Offer offer, Storage<OpenOfferList> storage) {
public OpenOffer(Offer offer, Storage<TradableList<OpenOffer>> storage) {
this.offer = offer;
this.storage = storage;
}
@ -84,6 +85,7 @@ public final class OpenOffer implements Tradable {
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public Date getDate() {
return offer.getDate();
}
@ -98,7 +100,7 @@ public final class OpenOffer implements Tradable {
return offer.getShortId();
}
public void setStorage(Storage<OpenOfferList> storage) {
public void setStorage(Storage<TradableList<OpenOffer>> storage) {
this.storage = storage;
}

View file

@ -39,6 +39,7 @@ import io.bisq.core.offer.messages.OfferAvailabilityResponse;
import io.bisq.core.offer.placeoffer.PlaceOfferModel;
import io.bisq.core.offer.placeoffer.PlaceOfferProtocol;
import io.bisq.core.provider.price.PriceFeedService;
import io.bisq.core.trade.TradableList;
import io.bisq.core.trade.closed.ClosedTradableManager;
import io.bisq.core.trade.handlers.TransactionResultHandler;
import io.bisq.core.user.Preferences;
@ -46,7 +47,6 @@ import io.bisq.core.user.User;
import io.bisq.core.util.Validator;
import io.bisq.network.p2p.*;
import io.bisq.network.p2p.peers.PeerManager;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import org.bitcoinj.core.Coin;
import org.slf4j.Logger;
@ -81,12 +81,10 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
private final ClosedTradableManager closedTradableManager;
private final PriceFeedService priceFeedService;
private final Preferences preferences;
private final Storage<OpenOfferList> openOffersStorage;
private final Storage<TradableList<OpenOffer>> openOffersStorage;
private boolean stopped;
private Timer periodicRepublishOffersTimer, periodicRefreshOffersTimer, retryRepublishOffersTimer;
private final OpenOfferList openOfferList = new OpenOfferList();
private ObservableList<OpenOffer> observableList;
private TradableList<OpenOffer> openOfferList;
///////////////////////////////////////////////////////////////////////////////////////////
@ -127,12 +125,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
@Override
public void readPersisted() {
OpenOfferList persisted = openOffersStorage.initAndGetPersisted(openOfferList);
if (persisted != null)
openOfferList.addAll(persisted.getList());
observableList = FXCollections.observableArrayList(openOfferList.getList());
observableList.forEach(e -> e.getOffer().setPriceFeedService(priceFeedService));
openOfferList = new TradableList<>(openOffersStorage, "OpenOffers");
openOfferList.forEach(e -> e.getOffer().setPriceFeedService(priceFeedService));
}
public void onAllServicesInitialized() {
@ -168,9 +162,9 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
// we remove own offers from offerbook when we go offline
// Normally we use a delay for broadcasting to the peers, but at shut down we want to get it fast out
final int size = observableList.size();
final int size = openOfferList.size();
if (offerBookService.isBootstrapped()) {
observableList.forEach(openOffer -> offerBookService.removeOfferAtShutDown(openOffer.getOffer().getOfferPayload()));
openOfferList.forEach(openOffer -> offerBookService.removeOfferAtShutDown(openOffer.getOffer().getOfferPayload()));
if (completeHandler != null)
UserThread.runAfter(completeHandler::run, size * 200 + 500, TimeUnit.MILLISECONDS);
} else {
@ -359,15 +353,15 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
}
public ObservableList<OpenOffer> getObservableList() {
return observableList;
return openOfferList.getObservableList();
}
public Optional<OpenOffer> findOpenOffer(String offerId) {
return observableList.stream().filter(openOffer -> openOffer.getId().equals(offerId)).findAny();
return openOfferList.stream().filter(openOffer -> openOffer.getId().equals(offerId)).findAny();
}
public Optional<OpenOffer> getOpenOfferById(String offerId) {
return observableList.stream().filter(e -> e.getId().equals(offerId)).findFirst();
return openOfferList.stream().filter(e -> e.getId().equals(offerId)).findFirst();
}
@ -457,8 +451,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
///////////////////////////////////////////////////////////////////////////////////////////
private void republishOffers() {
int size = observableList.size();
final ArrayList<OpenOffer> openOffersList = new ArrayList<>(observableList);
int size = openOfferList.size();
final ArrayList<OpenOffer> openOffersList = new ArrayList<>(openOfferList.getList());
Log.traceCall("Number of offer for republish: " + size);
if (!stopped) {
stopPeriodicRefreshOffersTimer();
@ -470,7 +464,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
final long maxDelay = (i + 2) * delay;
final OpenOffer openOffer = openOffersList.get(i);
UserThread.runAfterRandomDelay(() -> {
if (observableList.contains(openOffer)) {
if (openOfferList.contains(openOffer)) {
// The openOffer.getId().contains("_") check is because there was once a version
// where we encoded the version nr in the offer id with a "_" as separator.
// That caused several issues and was reverted. So if there are still old offers out with that
@ -540,11 +534,11 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
if (periodicRefreshOffersTimer == null)
periodicRefreshOffersTimer = UserThread.runPeriodically(() -> {
if (!stopped) {
int size = observableList.size();
int size = openOfferList.size();
Log.traceCall("Number of offer for refresh: " + size);
//we clone our list as openOffers might change during our delayed call
final ArrayList<OpenOffer> openOffersList = new ArrayList<>(observableList);
final ArrayList<OpenOffer> openOffersList = new ArrayList<>(openOfferList.getList());
for (int i = 0; i < size; i++) {
// we delay to avoid reaching throttle limits
// roughly 4 offers per second
@ -555,7 +549,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
final OpenOffer openOffer = openOffersList.get(i);
UserThread.runAfterRandomDelay(() -> {
// we need to check if in the meantime the offer has been removed
if (observableList.contains(openOffer))
if (openOfferList.contains(openOffer))
refreshOffer(openOffer);
}, minDelay, maxDelay, TimeUnit.MILLISECONDS);
}

View file

@ -82,7 +82,7 @@ public class OfferAvailabilityProtocol {
public void sendOfferAvailabilityRequest() {
// reset
model.offer.setState(Offer.State.UNDEFINED);
model.offer.setState(Offer.State.UNKNOWN);
model.p2PService.addDecryptedDirectMessageListener(decryptedDirectMessageListener);
model.setPeerNodeAddress(model.offer.getMakerNodeAddress());

View file

@ -18,10 +18,20 @@
package io.bisq.core.proto;
import io.bisq.common.locale.CurrencyUtil;
import io.bisq.core.arbitration.DisputeResult;
import io.bisq.core.btc.AddressEntry;
import io.bisq.core.dao.vote.VotingType;
import io.bisq.core.offer.AvailabilityResult;
import io.bisq.core.offer.Offer;
import io.bisq.core.offer.OfferPayload;
import io.bisq.core.offer.OpenOffer;
import io.bisq.core.payment.payload.BankAccountPayload;
import io.bisq.core.payment.payload.CountryBasedPaymentAccountPayload;
import io.bisq.core.trade.Trade;
import io.bisq.generated.protobuffer.PB;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ProtoCoreUtil {
@ -48,4 +58,153 @@ public class ProtoCoreUtil {
CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload) {
countryBasedPaymentAccountPayload.setCountryCode(protoEntry.getCountryBasedPaymentAccountPayload().getCountryCode());
}
// Util for auto generating enum values used in pb definition
public static void printAllEnumsForPB() {
StringBuilder sb = new StringBuilder("\n enum State {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < Trade.State.values().length; i++) {
Trade.State s = Trade.State.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n");
sb.append(" enum Phase {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < Trade.Phase.values().length; i++) {
Trade.Phase s = Trade.Phase.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum DisputeState {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < Trade.DisputeState.values().length; i++) {
Trade.DisputeState s = Trade.DisputeState.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum TradePeriodState {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < Trade.TradePeriodState.values().length; i++) {
Trade.TradePeriodState s = Trade.TradePeriodState.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum VotingType {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < VotingType.values().length; i++) {
VotingType s = VotingType.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum Direction {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < OfferPayload.Direction.values().length; i++) {
OfferPayload.Direction s = OfferPayload.Direction.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum Winner {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < DisputeResult.Winner.values().length; i++) {
DisputeResult.Winner s = DisputeResult.Winner.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum Reason {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < DisputeResult.Reason.values().length; i++) {
DisputeResult.Reason s = DisputeResult.Reason.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum AvailabilityResult {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < AvailabilityResult.values().length; i++) {
AvailabilityResult s = AvailabilityResult.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum Context {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < AddressEntry.Context.values().length; i++) {
AddressEntry.Context s = AddressEntry.Context.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum State {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < Offer.State.values().length; i++) {
Offer.State s = Offer.State.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
sb.append(" enum State {\n");
sb.append(" PB_ERROR = 0;\n");
for (int i = 0; i < OpenOffer.State.values().length; i++) {
OpenOffer.State s = OpenOffer.State.values()[i];
sb.append(" ");
sb.append(s.toString());
sb.append(" = ");
sb.append(s.ordinal() + 1);
sb.append(";\n");
}
sb.append(" }\n\n\n");
log.info(sb.toString());
}
}

View file

@ -11,7 +11,6 @@ import io.bisq.core.btc.AddressEntryList;
import io.bisq.core.btc.wallet.BtcWalletService;
import io.bisq.core.dao.compensation.CompensationRequestPayload;
import io.bisq.core.offer.OpenOffer;
import io.bisq.core.offer.OpenOfferList;
import io.bisq.core.payment.PaymentAccount;
import io.bisq.core.proto.CoreProtoResolver;
import io.bisq.core.trade.*;
@ -63,9 +62,16 @@ public class CorePersistenceProtoResolver extends CoreProtoResolver implements P
case VIEW_PATH_AS_STRING:
return PersistableViewPath.fromProto(proto.getViewPathAsString());
case OPEN_OFFER_LIST:
return OpenOfferList.fromProto(proto.getOpenOfferList());
return TradableList.fromProto(proto.getOpenOfferList(), openOfferStorage);
case TRADABLE_LIST:
return getTradableList(proto.getTradableList());
return TradableList.fromProto(proto.getTradableList(),
this,
openOfferStorage,
buyerAsMakerTradeStorage,
buyerAsTakerTradeStorage,
sellerAsMakerTradeStorage,
sellerAsTakerTradeStorage,
btcWalletService.get());
case PEER_LIST:
return PeerList.fromProto(proto.getPeerList());
case COMPENSATION_REQUEST_PAYLOAD:
@ -84,11 +90,27 @@ public class CorePersistenceProtoResolver extends CoreProtoResolver implements P
}
}
// @Override
public Tradable fromProto(PB.Tradable proto, Storage<TradableList<SellerAsMakerTrade>> storage) {
log.error("Convert protobuffer disk proto: {}", proto.getMessageCase());
private PersistableEnvelope getTradableList(PB.TradableList tradableList) {
return TradableList.fromProto(tradableList, openOfferStorage, buyerAsMakerTradeStorage, buyerAsTakerTradeStorage, sellerAsMakerTradeStorage, sellerAsTakerTradeStorage, btcWalletService.get());
switch (proto.getMessageCase()) {
case OPEN_OFFER:
return OpenOffer.fromProto(proto.getOpenOffer());
case BUYER_AS_MAKER_TRADE:
return BuyerAsMakerTrade.fromProto(proto.getBuyerAsMakerTrade(), storage, btcWalletService.get());
case BUYER_AS_TAKER_TRADE:
return BuyerAsTakerTrade.fromProto(proto.getBuyerAsTakerTrade(), storage, btcWalletService.get());
case SELLER_AS_MAKER_TRADE:
return SellerAsMakerTrade.fromProto(proto.getSellerAsMakerTrade(), storage, btcWalletService.get());
case SELLER_AS_TAKER_TRADE:
return SellerAsTakerTrade.fromProto(proto.getSellerAsTakerTrade(), storage, btcWalletService.get());
default:
throw new ProtobufferException("Unknown proto message case. messageCase=" + proto.getMessageCase());
}
}
private Preferences fillPreferences(PB.PersistableEnvelope envelope, Preferences preferences) {
final PB.Preferences env = envelope.getPreferences();
preferences.setUserLanguage(env.getUserLanguage());

View file

@ -52,14 +52,9 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade {
///////////////////////////////////////////////////////////////////////////////////////////
// API
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleTakeOfferRequest(TradeMessage message, NodeAddress taker) {
((MakerProtocol) tradeProtocol).handleTakeOfferRequest(message, taker);
}
@Override
public PB.Tradable toProtoMessage() {
return PB.Tradable.newBuilder()
@ -73,4 +68,14 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade {
Coin.valueOf(proto.getTrade().getTakerFeeAsLong()),
proto.getTrade().getIsCurrencyForTakerFeeBtc(), storage, btcWalletService);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleTakeOfferRequest(TradeMessage message, NodeAddress taker) {
((MakerProtocol) tradeProtocol).handleTakeOfferRequest(message, taker);
}
}

View file

@ -56,15 +56,9 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade {
///////////////////////////////////////////////////////////////////////////////////////////
// API
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void takeAvailableOffer() {
checkArgument(tradeProtocol instanceof TakerProtocol, "tradeProtocol NOT instanceof TakerProtocol");
((TakerProtocol) tradeProtocol).takeAvailableOffer();
}
@Override
public PB.Tradable toProtoMessage() {
return PB.Tradable.newBuilder()
@ -81,4 +75,15 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade {
NodeAddress.fromProto(trade.getTradingPeerNodeAddress()), storage,
btcWalletService);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void takeAvailableOffer() {
checkArgument(tradeProtocol instanceof TakerProtocol, "tradeProtocol NOT instanceof TakerProtocol");
((TakerProtocol) tradeProtocol).takeAvailableOffer();
}
}

View file

@ -207,30 +207,29 @@ public final class Contract implements NetworkPayload {
return Price.valueOf(offerPayload.getCurrencyCode(), tradePrice);
}
@Override
public String toString() {
@Override public String toString() {
return "Contract{" +
"\n\toffer=" + offerPayload +
"\n\ttradeAmount=" + tradeAmount +
"\n\ttradePrice=" + tradePrice +
"\n\ttakerFeeTxID='" + takerFeeTxID + '\'' +
"\n\tarbitratorAddress=" + arbitratorNodeAddress +
"\n\tmediatorNodeAddress=" + mediatorNodeAddress +
"\n\tisBuyerMakerAndSellerTaker=" + isBuyerMakerAndSellerTaker +
"\n\tmakerAccountId='" + makerAccountId + '\'' +
"\n\ttakerAccountId='" + takerAccountId + '\'' +
"\n\tmakerPaymentAccountPayload=" + makerPaymentAccountPayload +
"\n\ttakerPaymentAccountPayload=" + takerPaymentAccountPayload +
"\n\tmakerPubKeyRing=" + makerPubKeyRing +
"\n\ttakerPubKeyRing=" + takerPubKeyRing +
"\n\tbuyerAddress=" + buyerNodeAddress +
"\n\tsellerAddress=" + sellerNodeAddress +
"\n\tmakerPayoutAddressString='" + makerPayoutAddressString + '\'' +
"\n\ttakerPayoutAddressString='" + takerPayoutAddressString + '\'' +
"\n\tmakerMultiSigPubKey=" + Hex.toHexString(makerMultiSigPubKey) +
"\n\ttakerMultiSigPubKey=" + Hex.toHexString(takerMultiSigPubKey) +
"\n\tBuyerMultiSigPubKey=" + Hex.toHexString(getBuyerMultiSigPubKey()) +
"\n\tSellerMultiSigPubKey=" + Hex.toHexString(getSellerMultiSigPubKey()) +
'}';
"\n offerPayload=" + offerPayload +
",\n tradeAmount=" + tradeAmount +
",\n tradePrice=" + tradePrice +
",\n takerFeeTxID='" + takerFeeTxID + '\'' +
",\n buyerNodeAddress=" + buyerNodeAddress +
",\n sellerNodeAddress=" + sellerNodeAddress +
",\n arbitratorNodeAddress=" + arbitratorNodeAddress +
",\n mediatorNodeAddress=" + mediatorNodeAddress +
",\n isBuyerMakerAndSellerTaker=" + isBuyerMakerAndSellerTaker +
",\n makerAccountId='" + makerAccountId + '\'' +
",\n takerAccountId='" + takerAccountId + '\'' +
",\n makerPaymentAccountPayload=" + makerPaymentAccountPayload +
",\n takerPaymentAccountPayload=" + takerPaymentAccountPayload +
",\n makerPubKeyRing=" + makerPubKeyRing +
",\n takerPubKeyRing=" + takerPubKeyRing +
",\n makerPayoutAddressString='" + makerPayoutAddressString + '\'' +
",\n takerPayoutAddressString='" + takerPayoutAddressString + '\'' +
",\n makerMultiSigPubKey=" + Hex.toHexString(makerMultiSigPubKey) +
",\n takerMultiSigPubKey=" + Hex.toHexString(takerMultiSigPubKey) +
",\n BuyerMultiSigPubKey=" + Hex.toHexString(getBuyerMultiSigPubKey()) +
",\n SellerMultiSigPubKey=" + Hex.toHexString(getSellerMultiSigPubKey()) +
"\n}";
}
}

View file

@ -15,40 +15,36 @@
* along with bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bisq.core.offer;
package io.bisq.core.trade;
import com.google.protobuf.Message;
import io.bisq.common.proto.persistable.PersistableEnvelope;
import io.bisq.generated.protobuffer.PB;
import lombok.Getter;
import lombok.experimental.Delegate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class OpenOfferList implements PersistableEnvelope {
public class PendingTradeList /*implements PersistableEnvelope */ {
@Getter
@Delegate
private List<OpenOffer> list = new ArrayList<>();
private List<Trade> list = new ArrayList<>();
public OpenOfferList() {
public PendingTradeList() {
}
public OpenOfferList(List<OpenOffer> list) {
public PendingTradeList(List<Trade> list) {
this.list = list;
}
@Override
/* @Override
public Message toProtoMessage() {
return PB.PersistableEnvelope.newBuilder()
.setOpenOfferList(PB.OpenOfferList.newBuilder()
.addAllOpenOffer(getList().stream().map(OpenOffer::toProtoMessage).collect(Collectors.toList())))
.setPendingTradeList(PB.PendingTradeList.newBuilder()
.addAllTrade(getList().stream().map(Trade::toProtoMessage).collect(Collectors.toList())))
.build();
}
}*/
public static PersistableEnvelope fromProto(PB.OpenOfferList proto) {
return new OpenOfferList(proto.getOpenOfferList().stream().map(OpenOffer::fromProto)
/* public static PersistableEnvelope fromProto(PB.PendingTradeList proto) {
return new PendingTradeList(proto.getTradeList().stream().map(Trade::fromProto)
.collect(Collectors.toList()));
}
}*/
}

View file

@ -51,14 +51,9 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade
///////////////////////////////////////////////////////////////////////////////////////////
// API
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleTakeOfferRequest(TradeMessage message, NodeAddress taker) {
((MakerProtocol) tradeProtocol).handleTakeOfferRequest(message, taker);
}
@Override
public PB.Tradable toProtoMessage() {
return PB.Tradable.newBuilder()
@ -72,4 +67,14 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade
Coin.valueOf(trade.getTxFeeAsLong()), Coin.valueOf(trade.getTakerFeeAsLong()),
trade.getIsCurrencyForTakerFeeBtc(), storage, btcWalletService);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleTakeOfferRequest(TradeMessage message, NodeAddress taker) {
((MakerProtocol) tradeProtocol).handleTakeOfferRequest(message, taker);
}
}

View file

@ -56,16 +56,9 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade
///////////////////////////////////////////////////////////////////////////////////////////
// API
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void takeAvailableOffer() {
checkArgument(tradeProtocol instanceof TakerProtocol, "tradeProtocol NOT instanceof TakerProtocol");
((TakerProtocol) tradeProtocol).takeAvailableOffer();
}
@Override
public PB.Tradable toProtoMessage() {
return PB.Tradable.newBuilder()
@ -80,4 +73,15 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade
trade.getIsCurrencyForTakerFeeBtc(), trade.getTradePrice(),
NodeAddress.fromProto(trade.getTradingPeerNodeAddress()), storage, btcWalletService);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void takeAvailableOffer() {
checkArgument(tradeProtocol instanceof TakerProtocol, "tradeProtocol NOT instanceof TakerProtocol");
((TakerProtocol) tradeProtocol).takeAvailableOffer();
}
}

View file

@ -18,11 +18,12 @@
package io.bisq.core.trade;
import com.google.protobuf.Message;
import io.bisq.common.proto.ProtoUtil;
import io.bisq.common.proto.ProtoCollectionUtil;
import io.bisq.common.proto.persistable.PersistableEnvelope;
import io.bisq.common.storage.Storage;
import io.bisq.core.btc.wallet.BtcWalletService;
import io.bisq.core.offer.OpenOffer;
import io.bisq.core.proto.persistable.CorePersistenceProtoResolver;
import io.bisq.generated.protobuffer.PB;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@ -51,10 +52,9 @@ public final class TradableList<T extends Tradable> implements PersistableEnvelo
public TradableList(Storage<TradableList<T>> storage, String fileName) {
this.storage = storage;
// TradableList<T> persisted = storage.initAndGetPersisted(this, fileName);
TradableList<T> persisted = storage.initAndGetPersistedWithFileName(fileName);
TradableList<T> persisted = storage.initAndGetPersisted(this, fileName);
if (persisted != null)
list.addAll(persisted.getList());
list = persisted.getList();
}
@ -70,20 +70,23 @@ public final class TradableList<T extends Tradable> implements PersistableEnvelo
@Override
public Message toProtoMessage() {
return PB.PersistableEnvelope.newBuilder().setTradableList(PB.TradableList.newBuilder()
.addAllTradable(ProtoUtil.collectionToProto(list))).build();
.addAllTradable(ProtoCollectionUtil.collectionToProto(list))).build();
}
public static TradableList fromProto(PB.TradableList proto,
CorePersistenceProtoResolver corePersistenceProtoResolver,
Storage<TradableList<OpenOffer>> openOfferStorage,
Storage<TradableList<BuyerAsMakerTrade>> buyerAsMakerTradeStorage,
Storage<TradableList<BuyerAsTakerTrade>> buyerAsTakerTradeStorage,
Storage<TradableList<SellerAsMakerTrade>> sellerAsMakerTradeStorage,
Storage<TradableList<SellerAsTakerTrade>> sellerAsTakerTradeStorage,
BtcWalletService btcWalletService) {
log.error("fromProto " + proto);
List list = proto.getTradableList().stream().map(tradable -> {
log.error("tradable.getMessageCase() " + tradable.getMessageCase());
switch (tradable.getMessageCase()) {
/* case OPEN_OFFER:
return OpenOffer.fromProto(tradable.getOpenOffer(), openOfferStorage);*/
case OPEN_OFFER:
return OpenOffer.fromProto(tradable.getOpenOffer());
case BUYER_AS_MAKER_TRADE:
return BuyerAsMakerTrade.fromProto(tradable.getBuyerAsMakerTrade(), buyerAsMakerTradeStorage, btcWalletService);
case BUYER_AS_TAKER_TRADE:
@ -112,6 +115,58 @@ public final class TradableList<T extends Tradable> implements PersistableEnvelo
return null;
}
/* public static TradableList fromProto(PB.TradeList proto,
CorePersistenceProtoResolver corePersistenceProtoResolver,
Storage<TradableList<BuyerAsMakerTrade>> buyerAsMakerTradeStorage,
Storage<TradableList<BuyerAsTakerTrade>> buyerAsTakerTradeStorage,
Storage<TradableList<SellerAsMakerTrade>> sellerAsMakerTradeStorage,
Storage<TradableList<SellerAsTakerTrade>> sellerAsTakerTradeStorage,
BtcWalletService btcWalletService) {
log.error("fromProto " + proto);
List list = proto.getTradeList().stream().map(trade -> {
// corePersistenceProtoResolver.fromProto(trade, st)
switch (trade.getMessageCase()) {
case OPEN_OFFER:
return OpenOffer.fromProto(trade.getOpenOffer());
case BUYER_AS_MAKER_TRADE:
return BuyerAsMakerTrade.fromProto(trade.getBuyerAsMakerTrade(), buyerAsMakerTradeStorage, btcWalletService);
case BUYER_AS_TAKER_TRADE:
return BuyerAsTakerTrade.fromProto(trade.getBuyerAsTakerTrade(), buyerAsTakerTradeStorage, btcWalletService);
case SELLER_AS_MAKER_TRADE:
return SellerAsMakerTrade.fromProto(trade.getSellerAsMakerTrade(), sellerAsMakerTradeStorage, btcWalletService);
case SELLER_AS_TAKER_TRADE:
return SellerAsTakerTrade.fromProto(trade.getSellerAsTakerTrade(), sellerAsTakerTradeStorage, btcWalletService);
}
return null;
}).collect(Collectors.toList());
switch (list.get(0).getClass().getSimpleName()) {
case "OpenOffer":
return new TradableList<OpenOffer>(openOfferStorage, list);
case "BuyerAsMakerTrade":
return new TradableList<BuyerAsMakerTrade>(buyerAsMakerTradeStorage, list);
case "BuyerAsTakerTrade":
return new TradableList<BuyerAsTakerTrade>(buyerAsTakerTradeStorage, list);
case "SellerAsMakerTrade":
return new TradableList<SellerAsMakerTrade>(sellerAsMakerTradeStorage, list);
case "SellerAsTakerTrade":
return new TradableList<SellerAsTakerTrade>(sellerAsTakerTradeStorage, list);
}
return null;
}*/
public static TradableList fromProto(PB.OpenOfferList proto,
Storage<TradableList<OpenOffer>> openOfferStorage) {
return new TradableList<>(openOfferStorage,
proto.getOpenOfferList().stream()
.map(OpenOffer::fromProto)
.collect(Collectors.toList())
);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API

View file

@ -46,17 +46,20 @@ import io.bisq.network.p2p.DecryptedMessageWithPubKey;
import io.bisq.network.p2p.NodeAddress;
import io.bisq.network.p2p.P2PService;
import javafx.beans.property.*;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
import org.bouncycastle.util.encoders.Hex;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.util.Date;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
@ -65,13 +68,17 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Holds all data which are relevant to the trade, but not those which are only needed in the trade process as shared data between tasks. Those data are
* stored in the task model.
*/
@Slf4j
public abstract class Trade implements Tradable, Model {
private static final Logger log = LoggerFactory.getLogger(Trade.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Enums
///////////////////////////////////////////////////////////////////////////////////////////
public enum State {
// #################### Phase PREPARATION
// When trade protocol starts no funds are on stake
PREPARATION(Phase.PREPARATION),
PREPARATION(Phase.INIT),
// At first part maker/taker have different roles
// taker perspective
@ -140,6 +147,7 @@ public abstract class Trade implements Tradable, Model {
// #################### Phase WITHDRAWN
WITHDRAW_COMPLETED(Phase.WITHDRAWN);
@NotNull
public Phase getPhase() {
return phase;
}
@ -153,7 +161,7 @@ public abstract class Trade implements Tradable, Model {
}
public enum Phase {
PREPARATION,
INIT,
TAKER_FEE_PUBLISHED,
DEPOSIT_PUBLISHED,
DEPOSIT_CONFIRMED,
@ -164,15 +172,15 @@ public abstract class Trade implements Tradable, Model {
}
public enum DisputeState {
NONE,
NO_DISPUTE,
DISPUTE_REQUESTED,
DISPUTE_STARTED_BY_PEER,
DISPUTE_CLOSED
}
public enum TradePeriodState {
NORMAL,
HALF_REACHED,
FIRST_HALF,
SECOND_HALF,
TRADE_PERIOD_OVER
}
@ -181,57 +189,89 @@ public abstract class Trade implements Tradable, Model {
// Fields
///////////////////////////////////////////////////////////////////////////////////////////
// Persistable
// Immutable
@Getter
private final Offer offer;
@Getter
private final boolean isCurrencyForTakerFeeBtc;
@Getter
private final long txFeeAsLong;
@Getter
private final long takerFeeAsLong;
private final long takeOfferDate;
@Getter
private final ProcessModel processModel;
@Nullable
// Mutable
@Nullable @Getter @Setter
private String takerFeeTxId;
@Nullable
@Nullable @Getter @Setter
private String depositTxId;
@Nullable
@Nullable @Getter @Setter
private String payoutTxId;
@Getter @Setter
private long tradeAmountAsLong;
private long txFeeAsLong;
private long takerFeeAsLong;
private long takeOfferDate;
private boolean isCurrencyForTakerFeeBtc;
@Setter
private long tradePrice;
@Nullable @Getter
private NodeAddress tradingPeerNodeAddress;
private State state;
private DisputeState disputeState;
private TradePeriodState tradePeriodState;
@Getter
private State state = State.PREPARATION;
@Getter
private DisputeState disputeState = DisputeState.NO_DISPUTE;
@Getter
private TradePeriodState tradePeriodState = TradePeriodState.FIRST_HALF;
@Nullable @Getter @Setter
private Contract contract;
@Nullable @Getter @Setter
private String contractAsJson;
@Nullable @Getter @Setter
private byte[] contractHash;
@Nullable @Getter @Setter
private String takerContractSignature;
@Nullable @Getter @Setter
private String makerContractSignature;
@Nullable @Getter
private NodeAddress arbitratorNodeAddress;
@Nullable @Getter
private NodeAddress mediatorNodeAddress;
@Nullable @Setter
private byte[] arbitratorBtcPubKey;
@Nullable @Getter @Setter
private String takerPaymentAccountId;
@Nullable
private String errorMessage;
// Transient
// Immutable
@Getter
transient final private Coin txFee;
@Getter
transient final private Coin takerFee;
@Getter // to set in constructor so not final but set at init
transient private Storage<? extends TradableList> storage;
@Getter // to set in constructor so not final but set at init
transient private BtcWalletService btcWalletService;
transient final private ObjectProperty<State> stateProperty = new SimpleObjectProperty<>(state);
transient final private ObjectProperty<Phase> statePhaseProperty = new SimpleObjectProperty<>(state.phase);
transient final private ObjectProperty<DisputeState> disputeStateProperty = new SimpleObjectProperty<>(disputeState);
transient final private ObjectProperty<TradePeriodState> tradePeriodStateProperty = new SimpleObjectProperty<>(tradePeriodState);
transient final private StringProperty errorMessageProperty = new SimpleStringProperty(errorMessage);
// Mutable
transient protected TradeProtocol tradeProtocol;
@Nullable @Setter
transient private Date maxTradePeriodDate, halfTradePeriodDate;
@Nullable
transient private Transaction payoutTx;
@Nullable
transient private Transaction depositTx;
@Nullable
transient private Coin tradeAmount;
transient private Coin txFee;
transient private Coin takerFee;
transient private ObjectProperty<State> stateProperty;
transient private ObjectProperty<Phase> statePhaseProperty;
transient private ObjectProperty<DisputeState> disputeStateProperty;
transient private ObjectProperty<TradePeriodState> tradePeriodStateProperty;
transient private StringProperty errorMessageProperty;
transient private ObjectProperty<Coin> tradeAmountProperty;
transient private ObjectProperty<Volume> tradeVolumeProperty;
transient private Set<DecryptedMessageWithPubKey> decryptedMessageWithPubKeySet = new HashSet<>();
@ -254,13 +294,14 @@ public abstract class Trade implements Tradable, Model {
this.isCurrencyForTakerFeeBtc = isCurrencyForTakerFeeBtc;
this.storage = storage;
this.btcWalletService = btcWalletService;
this.txFeeAsLong = txFee.value;
this.takerFeeAsLong = takerFee.value;
this.setTakeOfferDate(new Date());
txFeeAsLong = txFee.value;
takerFeeAsLong = takerFee.value;
takeOfferDate = new Date().getTime();
processModel = new ProcessModel();
}
// taker
protected Trade(Offer offer,
Coin tradeAmount,
@ -275,12 +316,53 @@ public abstract class Trade implements Tradable, Model {
this(offer, txFee, takerFee, isCurrencyForTakerFeeBtc, storage, btcWalletService);
this.tradePrice = tradePrice;
this.tradingPeerNodeAddress = tradingPeerNodeAddress;
this.setTradeAmount(tradeAmount);
getTradeAmountProperty().set(tradeAmount);
getTradeVolumeProperty().set(getTradeVolume());
this.setTakeOfferDate(new Date());
setTradeAmount(tradeAmount);
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public Message toProtoMessage() {
final PB.Trade.Builder builder = PB.Trade.newBuilder()
.setOffer(offer.toProtoMessage())
.setIsCurrencyForTakerFeeBtc(isCurrencyForTakerFeeBtc)
.setTxFeeAsLong(txFeeAsLong)
.setTakerFeeAsLong(takerFeeAsLong)
.setTakeOfferDate(takeOfferDate)
.setTradeAmountAsLong(tradeAmountAsLong)
.setTradePrice(tradePrice)
.setProcessModel(processModel.toProtoMessage())
.setState(PB.Trade.State.valueOf(state.name()))
.setDisputeState(PB.Trade.DisputeState.valueOf(disputeState.name()))
.setTradePeriodState(PB.Trade.TradePeriodState.valueOf(tradePeriodState.name()));
Optional.ofNullable(takerFeeTxId).ifPresent(builder::setTakerFeeTxId);
Optional.ofNullable(depositTxId).ifPresent(builder::setDepositTxId);
Optional.ofNullable(payoutTxId).ifPresent(builder::setPayoutTxId);
Optional.ofNullable(tradingPeerNodeAddress).ifPresent(e -> builder.setTradingPeerNodeAddress(tradingPeerNodeAddress.toProtoMessage()));
Optional.ofNullable(contract).ifPresent(e -> builder.setContract(contract.toProtoMessage()));
Optional.ofNullable(contractAsJson).ifPresent(builder::setContractAsJson);
Optional.ofNullable(contractHash).ifPresent(e -> builder.setContractHash(ByteString.copyFrom(contractHash)));
Optional.ofNullable(takerContractSignature).ifPresent(builder::setTakerContractSignature);
Optional.ofNullable(makerContractSignature).ifPresent(builder::setMakerContractSignature);
Optional.ofNullable(arbitratorNodeAddress).ifPresent(e -> builder.setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage()));
Optional.ofNullable(mediatorNodeAddress).ifPresent(e -> builder.setMediatorNodeAddress(mediatorNodeAddress.toProtoMessage()));
Optional.ofNullable(arbitratorBtcPubKey).ifPresent(e -> builder.setArbitratorBtcPubKey(ByteString.copyFrom(arbitratorBtcPubKey)));
Optional.ofNullable(takerPaymentAccountId).ifPresent(builder::setTakerPaymentAccountId);
Optional.ofNullable(errorMessage).ifPresent(builder::setErrorMessage);
return builder.build();
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void setTransientFields(Storage<? extends TradableList> storage, BtcWalletService btcWalletService) {
this.storage = storage;
this.btcWalletService = btcWalletService;
@ -316,8 +398,7 @@ public abstract class Trade implements Tradable, Model {
// if we have already received a msg we apply it.
// removeDecryptedMsgWithPubKey will be called synchronous after apply. We don't have threaded context
// or async calls there.
log.trace("init: getMailboxMessageSet() = " + getDecryptedMessageWithPubKeySet());
getDecryptedMessageWithPubKeySet().stream()
decryptedMessageWithPubKeySet.stream()
.forEach(msg -> tradeProtocol.applyMailboxMessage(msg, this));
}
@ -352,8 +433,8 @@ public abstract class Trade implements Tradable, Model {
// received the msb but before the init is called.
public void addDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey) {
log.trace("addDecryptedMessageWithPubKey decryptedMessageWithPubKey=" + decryptedMessageWithPubKey);
if (!getDecryptedMessageWithPubKeySet().contains(decryptedMessageWithPubKey)) {
getDecryptedMessageWithPubKeySet().add(decryptedMessageWithPubKey);
if (!decryptedMessageWithPubKeySet.contains(decryptedMessageWithPubKey)) {
decryptedMessageWithPubKeySet.add(decryptedMessageWithPubKey);
// If we have already initialized we apply.
// removeDecryptedMsgWithPubKey will be called synchronous after apply. We don't have threaded context
@ -365,13 +446,39 @@ public abstract class Trade implements Tradable, Model {
public void removeDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey) {
log.trace("removeDecryptedMessageWithPubKey decryptedMessageWithPubKey=" + decryptedMessageWithPubKey);
if (getDecryptedMessageWithPubKeySet().contains(decryptedMessageWithPubKey))
getDecryptedMessageWithPubKeySet().remove(decryptedMessageWithPubKey);
if (decryptedMessageWithPubKeySet.contains(decryptedMessageWithPubKey))
decryptedMessageWithPubKeySet.remove(decryptedMessageWithPubKey);
}
///////////////////////////////////////////////////////////////////////////////////////////
// States
// Model implementation
///////////////////////////////////////////////////////////////////////////////////////////
// Get called from taskRunner after each completed task
@Override
public void persist() {
if (storage != null)
storage.queueUpForSave();
}
@Override
public void onComplete() {
persist();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Abstract
///////////////////////////////////////////////////////////////////////////////////////////
abstract protected void createTradeProtocol();
abstract public Coin getPayoutAmount();
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setState(State state) {
@ -379,8 +486,8 @@ public abstract class Trade implements Tradable, Model {
if (state.getPhase().ordinal() >= this.state.getPhase().ordinal()) {
boolean changed = this.state != state;
this.state = state;
getStateProperty().set(state);
getStatePhaseProperty().set(state.getPhase());
stateProperty.set(state);
statePhaseProperty.set(state.getPhase());
if (state == State.WITHDRAW_COMPLETED && tradeProtocol != null)
tradeProtocol.completed();
@ -400,33 +507,98 @@ public abstract class Trade implements Tradable, Model {
Log.traceCall("disputeState=" + disputeState + "\n\ttrade=" + this);
boolean changed = this.disputeState != disputeState;
this.disputeState = disputeState;
getDisputeStateProperty().set(disputeState);
disputeStateProperty.set(disputeState);
if (changed)
persist();
}
public DisputeState getDisputeState() {
if (disputeState == null)
disputeState = DisputeState.NONE;
return disputeState;
}
public void setTradePeriodState(TradePeriodState tradePeriodState) {
boolean changed = this.tradePeriodState != tradePeriodState;
this.tradePeriodState = tradePeriodState;
getTradePeriodStateProperty().set(tradePeriodState);
tradePeriodStateProperty.set(tradePeriodState);
if (changed)
persist();
}
public TradePeriodState getTradePeriodState() {
if (tradePeriodState == null)
tradePeriodState = TradePeriodState.NORMAL;
return tradePeriodState;
public void setTradingPeerNodeAddress(NodeAddress tradingPeerNodeAddress) {
if (tradingPeerNodeAddress == null)
log.error("tradingPeerAddress=null");
else
this.tradingPeerNodeAddress = tradingPeerNodeAddress;
}
public void setTradeAmount(Coin tradeAmount) {
this.tradeAmount = tradeAmount;
tradeAmountAsLong = tradeAmount.value;
getTradeAmountProperty().set(tradeAmount);
getTradeVolumeProperty().set(getTradeVolume());
}
public void setPayoutTx(Transaction payoutTx) {
this.payoutTx = payoutTx;
payoutTxId = payoutTx.getHashAsString();
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
errorMessageProperty.set(errorMessage);
}
public void setArbitratorNodeAddress(NodeAddress arbitratorNodeAddress) {
this.arbitratorNodeAddress = arbitratorNodeAddress;
Arbitrator arbitrator = processModel.getUser().getAcceptedArbitratorByAddress(arbitratorNodeAddress);
checkNotNull(arbitrator, "arbitrator must not be null");
arbitratorBtcPubKey = arbitrator.getBtcPubKey();
}
public void setMediatorNodeAddress(NodeAddress mediatorNodeAddress) {
this.mediatorNodeAddress = mediatorNodeAddress;
Mediator mediator = processModel.getUser().getAcceptedMediatorByAddress(mediatorNodeAddress);
checkNotNull(mediator, "mediator must not be null");
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter
///////////////////////////////////////////////////////////////////////////////////////////
public Date getTakeOfferDate() {
return new Date(takeOfferDate);
}
@Nullable
public Volume getTradeVolume() {
if (getTradeAmount() != null && getTradePrice() != null)
return getTradePrice().getVolumeByAmount(getTradeAmount());
else
return null;
}
@Nullable
public Date getMaxTradePeriodDate() {
if (maxTradePeriodDate == null && getTakeOfferDate() != null)
maxTradePeriodDate = new Date(getTakeOfferDate().getTime() + getOffer().getPaymentMethod().getMaxTradePeriod());
return maxTradePeriodDate;
}
@Nullable
public Date getHalfTradePeriodDate() {
if (halfTradePeriodDate == null && getTakeOfferDate() != null)
halfTradePeriodDate = new Date(getTakeOfferDate().getTime() + getOffer().getPaymentMethod().getMaxTradePeriod() / 2);
return halfTradePeriodDate;
}
public boolean hasFailed() {
return errorMessageProperty().get() != null;
}
public boolean isInPreparation() {
return getState().getPhase().ordinal() == Phase.PREPARATION.ordinal();
return getState().getPhase().ordinal() == Phase.INIT.ordinal();
}
public boolean isTakerFeePublished() {
@ -457,193 +629,47 @@ public abstract class Trade implements Tradable, Model {
return getState().getPhase().ordinal() == Phase.WITHDRAWN.ordinal();
}
public State getState() {
if (state == null)
state = State.PREPARATION;
return state;
}
public StringProperty getErrorMessageProperty() {
if (errorMessageProperty == null)
errorMessageProperty = new SimpleStringProperty(errorMessage);
return errorMessageProperty;
}
//TODO can be removed after PB is applied. mailboxMessageSet can be used then instead of getMailboxMessageSet().
private Set<DecryptedMessageWithPubKey> getDecryptedMessageWithPubKeySet() {
if (decryptedMessageWithPubKeySet == null)
decryptedMessageWithPubKeySet = new HashSet<>();
return decryptedMessageWithPubKeySet;
}
public ObjectProperty<Coin> getTradeAmountProperty() {
if (tradeAmountProperty == null)
tradeAmountProperty = getTradeAmount() != null ? new SimpleObjectProperty<>(getTradeAmount()) : new SimpleObjectProperty<>();
return tradeAmountProperty;
}
public ObjectProperty<Volume> getTradeVolumeProperty() {
if (tradeVolumeProperty == null)
tradeVolumeProperty = getTradeVolume() != null ? new SimpleObjectProperty<>(getTradeVolume()) : new SimpleObjectProperty<>();
return tradeVolumeProperty;
}
public Date getTakeOfferDate() {
return new Date(takeOfferDate);
}
public void setTakeOfferDate(Date takeOfferDate) {
this.takeOfferDate = takeOfferDate.getTime();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Model implementation
///////////////////////////////////////////////////////////////////////////////////////////
// Get called from taskRunner after each completed task
@Override
public void persist() {
if (storage != null)
storage.queueUpForSave();
}
@Override
public void onComplete() {
persist();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter only
///////////////////////////////////////////////////////////////////////////////////////////
public String getId() {
return offer.getId();
}
public String getShortId() {
return offer.getShortId();
}
public Offer getOffer() {
return offer;
}
abstract public Coin getPayoutAmount();
public ProcessModel getProcessModel() {
return processModel;
}
@Nullable
public Volume getTradeVolume() {
if (getTradeAmount() != null && getTradePrice() != null)
return getTradePrice().getVolumeByAmount(getTradeAmount());
else
return null;
}
@Nullable
public Date getMaxTradePeriodDate() {
if (maxTradePeriodDate == null && getTakeOfferDate() != null)
maxTradePeriodDate = new Date(getTakeOfferDate().getTime() + getOffer().getPaymentMethod().getMaxTradePeriod());
return maxTradePeriodDate;
}
@Nullable
public Date getHalfTradePeriodDate() {
if (halfTradePeriodDate == null && getTakeOfferDate() != null)
halfTradePeriodDate = new Date(getTakeOfferDate().getTime() + getOffer().getPaymentMethod().getMaxTradePeriod() / 2);
return halfTradePeriodDate;
}
public boolean hasFailed() {
return errorMessageProperty().get() != null;
}
private ObjectProperty<State> getStateProperty() {
if (stateProperty == null)
stateProperty = new SimpleObjectProperty<>(getState());
public ReadOnlyObjectProperty<State> stateProperty() {
return stateProperty;
}
private ObjectProperty<Phase> getStatePhaseProperty() {
if (statePhaseProperty == null)
statePhaseProperty = new SimpleObjectProperty<>(getState().phase);
public ReadOnlyObjectProperty<Phase> statePhaseProperty() {
return statePhaseProperty;
}
private ObjectProperty<DisputeState> getDisputeStateProperty() {
if (disputeStateProperty == null)
disputeStateProperty = new SimpleObjectProperty<>(getDisputeState());
public ReadOnlyObjectProperty<DisputeState> disputeStateProperty() {
return disputeStateProperty;
}
private ObjectProperty<TradePeriodState> getTradePeriodStateProperty() {
if (tradePeriodStateProperty == null)
tradePeriodStateProperty = new SimpleObjectProperty<>(getTradePeriodState());
public ReadOnlyObjectProperty<TradePeriodState> tradePeriodStateProperty() {
return tradePeriodStateProperty;
}
public ReadOnlyObjectProperty<State> stateProperty() {
return getStateProperty();
}
public ReadOnlyObjectProperty<Phase> statePhaseProperty() {
return getStatePhaseProperty();
}
public ReadOnlyObjectProperty<DisputeState> disputeStateProperty() {
return getDisputeStateProperty();
}
public ReadOnlyObjectProperty<TradePeriodState> tradePeriodStateProperty() {
return getTradePeriodStateProperty();
}
public ReadOnlyObjectProperty<Coin> tradeAmountProperty() {
return getTradeAmountProperty();
return tradeAmountProperty;
}
public ReadOnlyObjectProperty<Volume> tradeVolumeProperty() {
return getTradeVolumeProperty();
return tradeVolumeProperty;
}
public ReadOnlyStringProperty errorMessageProperty() {
return errorMessageProperty;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter/Setter for Mutable objects
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public Date getDate() {
return getTakeOfferDate();
}
public void setTradingPeerNodeAddress(NodeAddress tradingPeerNodeAddress) {
if (tradingPeerNodeAddress == null)
log.error("tradingPeerAddress=null");
else
this.tradingPeerNodeAddress = tradingPeerNodeAddress;
@Override
public String getId() {
return offer.getId();
}
@Nullable
public NodeAddress getTradingPeerNodeAddress() {
return tradingPeerNodeAddress;
}
public void setTradeAmount(Coin tradeAmount) {
this.tradeAmount = tradeAmount;
tradeAmountAsLong = tradeAmount.value;
getTradeAmountProperty().set(tradeAmount);
getTradeVolumeProperty().set(getTradeVolume());
}
public void setTradePrice(long tradePrice) {
this.tradePrice = tradePrice;
@Override
public String getShortId() {
return offer.getShortId();
}
public Price getTradePrice() {
@ -657,59 +683,6 @@ public abstract class Trade implements Tradable, Model {
return tradeAmount;
}
public Coin getTxFee() {
if (txFee == null)
txFee = Coin.valueOf(txFeeAsLong);
return txFee;
}
public Coin getTakerFee() {
if (takerFee == null)
takerFee = Coin.valueOf(takerFeeAsLong);
return takerFee;
}
public void setTakerContractSignature(String takerSignature) {
this.takerContractSignature = takerSignature;
}
@Nullable
public String getTakerContractSignature() {
return takerContractSignature;
}
public void setMakerContractSignature(String makerContractSignature) {
this.makerContractSignature = makerContractSignature;
}
@Nullable
public String getMakerContractSignature() {
return makerContractSignature;
}
public void setContractAsJson(String contractAsJson) {
this.contractAsJson = contractAsJson;
}
@Nullable
public String getContractAsJson() {
return contractAsJson;
}
public void setContract(Contract contract) {
this.contract = contract;
}
@Nullable
public Contract getContract() {
return contract;
}
public void setPayoutTx(Transaction payoutTx) {
this.payoutTx = payoutTx;
payoutTxId = payoutTx.getHashAsString();
}
@Nullable
public Transaction getPayoutTx() {
if (payoutTx == null)
@ -717,29 +690,8 @@ public abstract class Trade implements Tradable, Model {
return payoutTx;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
getErrorMessageProperty().set(errorMessage);
}
public ReadOnlyStringProperty errorMessageProperty() {
return getErrorMessageProperty();
}
public String getErrorMessage() {
return getErrorMessageProperty().get();
}
public NodeAddress getArbitratorNodeAddress() {
return arbitratorNodeAddress;
}
public void applyArbitratorNodeAddress(NodeAddress arbitratorNodeAddress) {
this.arbitratorNodeAddress = arbitratorNodeAddress;
Arbitrator arbitrator = processModel.getUser().getAcceptedArbitratorByAddress(arbitratorNodeAddress);
checkNotNull(arbitrator, "arbitrator must not be null");
arbitratorBtcPubKey = arbitrator.getBtcPubKey();
return errorMessageProperty.get();
}
public byte[] getArbitratorBtcPubKey() {
@ -751,58 +703,29 @@ public abstract class Trade implements Tradable, Model {
return arbitratorBtcPubKey;
}
public NodeAddress getMediatorNodeAddress() {
return mediatorNodeAddress;
}
public void applyMediatorNodeAddress(NodeAddress mediatorNodeAddress) {
this.mediatorNodeAddress = mediatorNodeAddress;
Mediator mediator = processModel.getUser().getAcceptedMediatorByAddress(mediatorNodeAddress);
checkNotNull(mediator, "mediator must not be null");
}
public String getTakerPaymentAccountId() {
return takerPaymentAccountId;
}
public void setTakerPaymentAccountId(String takerPaymentAccountId) {
this.takerPaymentAccountId = takerPaymentAccountId;
}
public void setContractHash(byte[] contractHash) {
this.contractHash = contractHash;
}
public byte[] getContractHash() {
return contractHash;
}
public void setTakerFeeTxId(String takerFeeTxId) {
this.takerFeeTxId = takerFeeTxId;
}
@org.jetbrains.annotations.Nullable
public String getTakerFeeTxId() {
return takerFeeTxId;
}
public boolean isCurrencyForTakerFeeBtc() {
return isCurrencyForTakerFeeBtc;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
// lazy initialization
private ObjectProperty<Coin> getTradeAmountProperty() {
if (tradeAmountProperty == null)
tradeAmountProperty = getTradeAmount() != null ? new SimpleObjectProperty<>(getTradeAmount()) : new SimpleObjectProperty<>();
return tradeAmountProperty;
}
// lazy initialization
private ObjectProperty<Volume> getTradeVolumeProperty() {
if (tradeVolumeProperty == null)
tradeVolumeProperty = getTradeVolume() != null ? new SimpleObjectProperty<>(getTradeVolume()) : new SimpleObjectProperty<>();
return tradeVolumeProperty;
}
private void setupConfidenceListener() {
log.debug("setupConfidenceListener");
if (getDepositTx() != null) {
TransactionConfidence transactionConfidence = getDepositTx().getConfidence();
log.debug("transactionConfidence " + transactionConfidence.getDepthInBlocks());
if (transactionConfidence.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
setConfirmedState();
} else {
@ -810,8 +733,6 @@ public abstract class Trade implements Tradable, Model {
Futures.addCallback(future, new FutureCallback<TransactionConfidence>() {
@Override
public void onSuccess(TransactionConfidence result) {
log.debug("transactionConfidence " + transactionConfidence.getDepthInBlocks());
log.debug("state " + getState());
setConfirmedState();
}
@ -828,46 +749,61 @@ public abstract class Trade implements Tradable, Model {
}
}
abstract protected void createTradeProtocol();
private void setConfirmedState() {
// we only apply the state if we are not already further in the process
if (!isDepositConfirmed())
setState(State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN);
}
@Override
public Message toProtoMessage() {
return PB.Trade.newBuilder()
.setOffer(offer.toProtoMessage())
.setProcessModel((PB.ProcessModel) processModel.toProtoMessage())
.setTakerFeeTxId(takerFeeTxId)
.setDepositTxId(depositTxId)
.setPayoutTxId(payoutTxId)
.setTradeAmountAsLong(tradeAmountAsLong)
.setTxFeeAsLong(txFeeAsLong)
.setTakerFeeAsLong(takerFeeAsLong)
.setTakeOfferDate(takeOfferDate)
.setIsCurrencyForTakerFeeBtc(isCurrencyForTakerFeeBtc)
.setTradePrice(tradePrice)
.setTradingPeerNodeAddress(tradingPeerNodeAddress.toProtoMessage())
.setState(PB.Trade.State.valueOf(state.name()))
.setDisputeState(PB.Trade.DisputeState.valueOf(disputeState.name()))
.setTradePeriodState(PB.Trade.TradePeriodState.valueOf(tradePeriodState.name()))
.setContract(contract.toProtoMessage())
.setContractAsJson(contractAsJson)
.setContractHash(ByteString.copyFrom(contractHash))
.setTakerContractSignature(takerContractSignature)
.setMakerContractSignature(makerContractSignature)
.setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage())
.setMediatorNodeAddress(mediatorNodeAddress.toProtoMessage())
.setArbitratorBtcPubKey(ByteString.copyFrom(arbitratorBtcPubKey))
.setTakerPaymentAccountId(takerPaymentAccountId)
.setErrorMessage(errorMessage)
.build();
@Override public String toString() {
return "Trade{" +
"\n offer=" + offer +
",\n isCurrencyForTakerFeeBtc=" + isCurrencyForTakerFeeBtc +
",\n txFeeAsLong=" + txFeeAsLong +
",\n takerFeeAsLong=" + takerFeeAsLong +
",\n takeOfferDate=" + getTakeOfferDate() +
",\n processModel=" + processModel +
",\n takerFeeTxId='" + takerFeeTxId + '\'' +
",\n depositTxId='" + depositTxId + '\'' +
",\n payoutTxId='" + payoutTxId + '\'' +
",\n tradeAmountAsLong=" + tradeAmountAsLong +
",\n tradePrice=" + tradePrice +
",\n tradingPeerNodeAddress=" + tradingPeerNodeAddress +
",\n state=" + state +
",\n disputeState=" + disputeState +
",\n tradePeriodState=" + tradePeriodState +
",\n contract=" + contract +
",\n contractAsJson='" + contractAsJson + '\'' +
",\n contractHash=" + Hex.toHexString(contractHash) +
",\n takerContractSignature='" + takerContractSignature + '\'' +
",\n makerContractSignature='" + makerContractSignature + '\'' +
",\n arbitratorNodeAddress=" + arbitratorNodeAddress +
",\n mediatorNodeAddress=" + mediatorNodeAddress +
",\n arbitratorBtcPubKey=" + Hex.toHexString(arbitratorBtcPubKey) +
",\n takerPaymentAccountId='" + takerPaymentAccountId + '\'' +
",\n errorMessage='" + errorMessage + '\'' +
",\n txFee=" + txFee +
",\n takerFee=" + takerFee +
",\n storage=" + storage +
",\n btcWalletService=" + btcWalletService +
",\n stateProperty=" + stateProperty +
",\n statePhaseProperty=" + statePhaseProperty +
",\n disputeStateProperty=" + disputeStateProperty +
",\n tradePeriodStateProperty=" + tradePeriodStateProperty +
",\n errorMessageProperty=" + errorMessageProperty +
",\n tradeProtocol=" + tradeProtocol +
",\n maxTradePeriodDate=" + maxTradePeriodDate +
",\n halfTradePeriodDate=" + halfTradePeriodDate +
",\n payoutTx=" + payoutTx +
",\n depositTx=" + depositTx +
",\n tradeAmount=" + tradeAmount +
",\n tradeAmountProperty=" + tradeAmountProperty +
",\n tradeVolumeProperty=" + tradeVolumeProperty +
",\n decryptedMessageWithPubKeySet=" + decryptedMessageWithPubKeySet +
"\n}";
}
@Override
/* @Override
public String toString() {
return "Trade{" +
"\n\ttradeAmount=" + getTradeAmount() +
@ -875,7 +811,7 @@ public abstract class Trade implements Tradable, Model {
"\n\ttradeVolume=" + getTradeVolumeProperty().get() +
"\n\toffer=" + offer +
"\n\tprocessModel=" + processModel +
"\n\tdecryptedMsgWithPubKeySet=" + getDecryptedMessageWithPubKeySet() +
"\n\tdecryptedMsgWithPubKeySet=" + decryptedMessageWithPubKeySet +
"\n\ttakeOfferDate=" + getTakeOfferDate() +
"\n\tstate=" + getState() +
"\n\tdisputeState=" + getDisputeState() +
@ -895,5 +831,5 @@ public abstract class Trade implements Tradable, Model {
"\n\ttakeOfferFee='" + getTakerFee().toFriendlyString() + '\'' +
"\n\terrorMessage='" + errorMessage + '\'' +
'}';
}
}*/
}

View file

@ -25,6 +25,7 @@ import io.bisq.common.handlers.ErrorMessageHandler;
import io.bisq.common.handlers.FaultHandler;
import io.bisq.common.handlers.ResultHandler;
import io.bisq.common.proto.network.NetworkEnvelope;
import io.bisq.common.proto.persistable.PersistedDataHost;
import io.bisq.common.proto.persistable.PersistenceProtoResolver;
import io.bisq.common.storage.Storage;
import io.bisq.core.btc.AddressEntry;
@ -75,7 +76,7 @@ import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkArgument;
public class TradeManager {
public class TradeManager implements PersistedDataHost {
private static final Logger log = LoggerFactory.getLogger(TradeManager.class);
private final User user;
@ -167,6 +168,16 @@ public class TradeManager {
});
}
@Override
public void readPersisted() {
/* OpenOfferList persisted = openOffersStorage.initAndGetPersisted(openOfferList);
if (persisted != null)
openOfferList.addAll(persisted.getList());
observableList = FXCollections.observableArrayList(openOfferList.getList());
observableList.forEach(e -> e.getOffer().setPriceFeedService(priceFeedService));*/
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle

View file

@ -19,6 +19,7 @@ package io.bisq.core.trade.closed;
import com.google.inject.Inject;
import io.bisq.common.crypto.KeyRing;
import io.bisq.common.proto.persistable.PersistedDataHost;
import io.bisq.common.proto.persistable.PersistenceProtoResolver;
import io.bisq.common.storage.Storage;
import io.bisq.core.btc.wallet.BtcWalletService;
@ -35,7 +36,7 @@ import javax.inject.Named;
import java.io.File;
import java.util.Optional;
public class ClosedTradableManager {
public class ClosedTradableManager implements PersistedDataHost {
private static final Logger log = LoggerFactory.getLogger(ClosedTradableManager.class);
private final TradableList<Tradable> closedTrades;
private final KeyRing keyRing;
@ -59,6 +60,10 @@ public class ClosedTradableManager {
});
}
@Override
public void readPersisted() {
}
public void add(Tradable tradable) {
closedTrades.add(tradable);
}

View file

@ -19,6 +19,7 @@ package io.bisq.core.trade.failed;
import com.google.inject.Inject;
import io.bisq.common.crypto.KeyRing;
import io.bisq.common.proto.persistable.PersistedDataHost;
import io.bisq.common.proto.persistable.PersistenceProtoResolver;
import io.bisq.common.storage.Storage;
import io.bisq.core.btc.wallet.BtcWalletService;
@ -34,7 +35,7 @@ import javax.inject.Named;
import java.io.File;
import java.util.Optional;
public class FailedTradesManager {
public class FailedTradesManager implements PersistedDataHost {
private static final Logger log = LoggerFactory.getLogger(FailedTradesManager.class);
private final TradableList<Trade> failedTrades;
private final KeyRing keyRing;
@ -54,6 +55,9 @@ public class FailedTradesManager {
});
}
@Override
public void readPersisted() {
}
public void add(Trade trade) {
if (!failedTrades.contains(trade))
failedTrades.add(trade);

View file

@ -58,7 +58,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
handleTaskRunnerSuccess("MakerSetupDepositTxListener");
processModel.onComplete();
},
this::handleTaskRunnerFault);
@ -68,7 +67,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
handleTaskRunnerSuccess("BuyerSetupPayoutTxListener");
processModel.onComplete();
},
this::handleTaskRunnerFault);
@ -194,7 +192,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade,
() -> {
handleTaskRunnerSuccess("handle PayoutTxPublishedMessage");
processModel.onComplete();
},
this::handleTaskRunnerFault);

View file

@ -58,7 +58,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
handleTaskRunnerSuccess("BuyerSetupPayoutTxListener");
processModel.onComplete();
},
this::handleTaskRunnerFault);
@ -179,7 +178,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
() -> {
handleTaskRunnerSuccess("handle PayoutTxPublishedMessage");
processModel.onComplete();
},
this::handleTaskRunnerFault);

View file

@ -18,10 +18,9 @@
package io.bisq.core.trade.protocol;
import com.google.protobuf.ByteString;
import com.google.protobuf.Message;
import io.bisq.common.crypto.KeyRing;
import io.bisq.common.crypto.PubKeyRing;
import io.bisq.common.proto.ProtoUtil;
import io.bisq.common.proto.ProtoCollectionUtil;
import io.bisq.common.proto.persistable.PersistablePayload;
import io.bisq.common.taskrunner.Model;
import io.bisq.core.btc.data.RawTransactionInput;
@ -47,6 +46,7 @@ import io.bisq.network.p2p.P2PService;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.NotImplementedException;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
@ -55,33 +55,23 @@ import javax.annotation.Nullable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Getter
@Slf4j
public class ProcessModel implements Model, PersistablePayload {
// Transient/Immutable
@Getter
// Transient/Immutable (net set in constructor so they are not final, but at init)
transient private TradeManager tradeManager;
@Getter
transient private OpenOfferManager openOfferManager;
transient private BtcWalletService btcWalletService;
transient private BsqWalletService bsqWalletService;
transient private TradeWalletService tradeWalletService;
transient private Offer offer;
@Getter
transient private User user;
transient private FilterManager filterManager;
@Getter
transient private KeyRing keyRing;
@Getter
transient private P2PService p2PService;
// Immutable
private final TradingPeer tradingPeer = new TradingPeer();
private String offerId;
private String accountId;
private PubKeyRing pubKeyRing;
// Transient/Mutable
transient private Transaction takeOfferFeeTx;
@Setter
@ -89,38 +79,76 @@ public class ProcessModel implements Model, PersistablePayload {
@Setter
transient private DecryptedMessageWithPubKey decryptedMessageWithPubKey;
// Mutable
// Persistable Immutable
private final TradingPeer tradingPeer = new TradingPeer();
private String offerId;
private String accountId;
private PubKeyRing pubKeyRing;
// Persistable Mutable
@Nullable
private String takeOfferFeeTxId;
@Setter
@Nullable @Setter
private byte[] payoutTxSignature;
@Setter
@Nullable @Setter
private List<NodeAddress> takerAcceptedArbitratorNodeAddresses;
@Setter
@Nullable @Setter
private List<NodeAddress> takerAcceptedMediatorNodeAddresses;
@Setter
@Nullable @Setter
private byte[] preparedDepositTx;
@Setter
@Nullable @Setter
private ArrayList<RawTransactionInput> rawTransactionInputs;
@Setter
private long changeOutputValue;
@Nullable
@Setter
@Nullable @Setter
private String changeOutputAddress;
@Setter
private boolean useSavingsWallet;
@Setter
private long fundsNeededForTradeAsLong;
@Setter
@Nullable @Setter
private byte[] myMultiSigPubKey;
// that is used to store temp. the peers address when we get an incoming message before the message is verified.
// After successful verified we copy that over to the trade.tradingPeerAddress
@Setter
@Nullable @Setter
private NodeAddress tempTradingPeerNodeAddress;
public ProcessModel() {
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public PB.ProcessModel toProtoMessage() {
final PB.ProcessModel.Builder builder = PB.ProcessModel.newBuilder()
.setTradingPeer((PB.TradingPeer) tradingPeer.toProtoMessage())
.setOfferId(offerId)
.setAccountId(accountId)
.setPubKeyRing(pubKeyRing.toProtoMessage())
.setChangeOutputValue(changeOutputValue)
.setFundsNeededForTradeAsLong(fundsNeededForTradeAsLong)
.setUseSavingsWallet(useSavingsWallet);
Optional.ofNullable(takeOfferFeeTxId).ifPresent(builder::setTakeOfferFeeTxId);
Optional.ofNullable(payoutTxSignature).ifPresent(e -> builder.setPayoutTxSignature(ByteString.copyFrom(payoutTxSignature)));
Optional.ofNullable(takerAcceptedArbitratorNodeAddresses).ifPresent(e -> builder.addAllTakerAcceptedArbitratorNodeAddresses(ProtoCollectionUtil.collectionToProto(takerAcceptedArbitratorNodeAddresses)));
Optional.ofNullable(takerAcceptedMediatorNodeAddresses).ifPresent(e -> builder.addAllTakerAcceptedMediatorNodeAddresses(ProtoCollectionUtil.collectionToProto(takerAcceptedMediatorNodeAddresses)));
Optional.ofNullable(preparedDepositTx).ifPresent(e -> builder.setPreparedDepositTx(ByteString.copyFrom(preparedDepositTx)));
Optional.ofNullable(rawTransactionInputs).ifPresent(e -> builder.addAllRawTransactionInputs(ProtoCollectionUtil.collectionToProto(rawTransactionInputs)));
Optional.ofNullable(changeOutputAddress).ifPresent(builder::setChangeOutputAddress);
Optional.ofNullable(myMultiSigPubKey).ifPresent(e -> builder.setMyMultiSigPubKey(ByteString.copyFrom(myMultiSigPubKey)));
Optional.ofNullable(tempTradingPeerNodeAddress).ifPresent(e -> builder.setTempTradingPeerNodeAddress(tempTradingPeerNodeAddress.toProtoMessage()));
return builder.build();
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void onAllServicesInitialized(Offer offer,
TradeManager tradeManager,
OpenOfferManager openOfferManager,
@ -144,23 +172,36 @@ public class ProcessModel implements Model, PersistablePayload {
this.keyRing = keyRing;
this.p2PService = p2PService;
this.useSavingsWallet = useSavingsWallet;
fundsNeededForTradeAsLong = fundsNeededForTrade.value;
offerId = offer.getId();
accountId = user.getAccountId();
pubKeyRing = keyRing.getPubKeyRing();
}
// TODO need lazy access?
public NodeAddress getMyNodeAddress() {
return p2PService.getAddress();
public void removeMailboxMessageAfterProcessing(Trade trade) {
if (tradeMessage instanceof MailboxMessage &&
decryptedMessageWithPubKey != null &&
decryptedMessageWithPubKey.getWireEnvelope().equals(tradeMessage)) {
log.debug("Remove decryptedMsgWithPubKey from P2P network. decryptedMsgWithPubKey = " + decryptedMessageWithPubKey);
p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey);
trade.removeDecryptedMessageWithPubKey(decryptedMessageWithPubKey);
}
}
@Override
public void persist() {
throw new NotImplementedException("persist is not implemented in that class");
}
@Override
public void onComplete() {
throw new NotImplementedException("persist is not implemented in that class");
}
public void setTakeOfferFeeTx(Transaction takeOfferFeeTx) {
this.takeOfferFeeTx = takeOfferFeeTx;
takeOfferFeeTxId = takeOfferFeeTx.getHashAsString();
}
@Nullable
@ -222,10 +263,10 @@ public class ProcessModel implements Model, PersistablePayload {
.setPubKeyRing(pubKeyRing.toProtoMessage())
.setTakeOfferFeeTxId(takeOfferFeeTxId)
.setPayoutTxSignature(ByteString.copyFrom(payoutTxSignature))
.addAllTakerAcceptedArbitratorNodeAddresses(ProtoUtil.collectionToProto(takerAcceptedArbitratorNodeAddresses))
.addAllTakerAcceptedMediatorNodeAddresses(ProtoUtil.collectionToProto(takerAcceptedMediatorNodeAddresses))
.addAllTakerAcceptedArbitratorNodeAddresses(ProtoCollectionUtil.collectionToProto(takerAcceptedArbitratorNodeAddresses))
.addAllTakerAcceptedMediatorNodeAddresses(ProtoCollectionUtil.collectionToProto(takerAcceptedMediatorNodeAddresses))
.setPreparedDepositTx(ByteString.copyFrom(preparedDepositTx))
.addAllRawTransactionInputs(ProtoUtil.collectionToProto(rawTransactionInputs))
.addAllRawTransactionInputs(ProtoCollectionUtil.collectionToProto(rawTransactionInputs))
.setChangeOutputValue(changeOutputValue)
.setChangeOutputAddress(changeOutputAddress)
.setUseSavingsWallet(useSavingsWallet)

View file

@ -59,7 +59,6 @@ public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtoc
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
handleTaskRunnerSuccess("MakerSetupDepositTxListener");
processModel.onComplete();
},
this::handleTaskRunnerFault);

View file

@ -17,8 +17,10 @@
package io.bisq.core.trade.protocol;
import com.google.protobuf.ByteString;
import com.google.protobuf.Message;
import io.bisq.common.crypto.PubKeyRing;
import io.bisq.common.proto.ProtoCollectionUtil;
import io.bisq.common.proto.persistable.PersistablePayload;
import io.bisq.core.btc.data.RawTransactionInput;
import io.bisq.core.payment.payload.PaymentAccountPayload;
@ -29,21 +31,29 @@ import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
@Slf4j
@Getter
@Setter
public final class TradingPeer implements PersistablePayload {
@Nullable
private String accountId;
@Nullable
private PaymentAccountPayload paymentAccountPayload;
// private Coin payoutAmount;
@Nullable
private String payoutAddressString;
// private byte[] signature;
@Nullable
private String contractAsJson;
@Nullable
private String contractSignature;
@Nullable
private byte[] signature;
@Nullable
private PubKeyRing pubKeyRing;
@Nullable
private byte[] multiSigPubKey;
@Nullable
private List<RawTransactionInput> rawTransactionInputs;
private long changeOutputValue;
@Nullable
@ -54,25 +64,18 @@ public final class TradingPeer implements PersistablePayload {
@Override
public Message toProtoMessage() {
// TODO
// nullable
// changeOutputAddress
// .setRawTransactionInputs(rawTransactionInputs)
// .setPaymentAccountPayload(paymentAccountPayload.toProto())
// .setSignature(signature)
// .setMultiSigPubKey(multiSigPubKey)
return PB.TradingPeer.newBuilder()
.setAccountId(accountId)
/* .setPaymentAccountPayload(paymentAccountPayload.toProto())*/
.setPayoutAddressString(payoutAddressString)
.setContractAsJson(contractAsJson)
.setContractSignature(contractSignature)
/* .setSignature(signature)*/
.setPubKeyRing(pubKeyRing.toProtoMessage())
/* .setMultiSigPubKey(multiSigPubKey)*/
/*.setRawTransactionInputs(rawTransactionInputs)*/
.setChangeOutputValue(changeOutputValue)
/* .setChangeOutputAddress(changeOutputAddress)*/
.build();
final PB.TradingPeer.Builder builder = PB.TradingPeer.newBuilder()
.setChangeOutputValue(changeOutputValue);
Optional.ofNullable(accountId).ifPresent(builder::setAccountId);
Optional.ofNullable(paymentAccountPayload).ifPresent(e -> builder.setPaymentAccountPayload((PB.PaymentAccountPayload) paymentAccountPayload.toProtoMessage()));
Optional.ofNullable(payoutAddressString).ifPresent(builder::setPayoutAddressString);
Optional.ofNullable(contractAsJson).ifPresent(builder::setContractAsJson);
Optional.ofNullable(contractSignature).ifPresent(builder::setContractSignature);
Optional.ofNullable(signature).ifPresent(e -> builder.setSignature(ByteString.copyFrom(signature)));
Optional.ofNullable(pubKeyRing).ifPresent(e -> builder.setPubKeyRing(pubKeyRing.toProtoMessage()));
Optional.ofNullable(multiSigPubKey).ifPresent(e -> builder.setMultiSigPubKey(ByteString.copyFrom(multiSigPubKey)));
Optional.ofNullable(rawTransactionInputs).ifPresent(e -> builder.addAllRawTransactionInputs(ProtoCollectionUtil.collectionToProto(rawTransactionInputs)));
Optional.ofNullable(changeOutputAddress).ifPresent(builder::setChangeOutputAddress);
return builder.build();
}
}

View file

@ -74,8 +74,8 @@ public class MakerProcessPayDepositRequest extends TradeTask {
processModel.setTakerAcceptedMediatorNodeAddresses(checkNotNull(payDepositRequest.getAcceptedMediatorNodeAddresses()));
if (payDepositRequest.getAcceptedArbitratorNodeAddresses().isEmpty())
failed("acceptedArbitratorNames must not be empty");
trade.applyArbitratorNodeAddress(checkNotNull(payDepositRequest.getArbitratorNodeAddress()));
trade.applyMediatorNodeAddress(checkNotNull(payDepositRequest.getMediatorNodeAddress()));
trade.setArbitratorNodeAddress(checkNotNull(payDepositRequest.getArbitratorNodeAddress()));
trade.setMediatorNodeAddress(checkNotNull(payDepositRequest.getMediatorNodeAddress()));
try {
long takersTradePrice = payDepositRequest.getTradePrice();

View file

@ -35,7 +35,7 @@ public class TakerSelectArbitrator extends TradeTask {
try {
runInterceptHook();
trade.applyArbitratorNodeAddress(ArbitratorSelectionRule.select(processModel.getUser().getAcceptedArbitratorAddresses(), processModel.getOffer()));
trade.setArbitratorNodeAddress(ArbitratorSelectionRule.select(processModel.getUser().getAcceptedArbitratorAddresses(), processModel.getOffer()));
complete();
} catch (Throwable t) {

View file

@ -35,7 +35,7 @@ public class TakerSelectMediator extends TradeTask {
try {
runInterceptHook();
trade.applyMediatorNodeAddress(MediatorSelectionRule.select(processModel.getUser().getAcceptedMediatorAddresses(),
trade.setMediatorNodeAddress(MediatorSelectionRule.select(processModel.getUser().getAcceptedMediatorAddresses(),
processModel.getOffer()));
complete();

View file

@ -45,7 +45,7 @@ public class ProtoBufferUtilitiesTest {
@Test
public void testUnknownEnum() {
PB.OpenOffer.State result = PB.OpenOffer.State.UNKNOWN_FAILURE;
PB.OpenOffer.State result = PB.OpenOffer.State.PB_ERROR;
try {
OpenOffer.State finalResult = OpenOffer.State.valueOf(result.name());
fail();

View file

@ -43,6 +43,8 @@ import io.bisq.core.dao.blockchain.json.JsonChainStateExporter;
import io.bisq.core.filter.FilterManager;
import io.bisq.core.offer.OpenOfferManager;
import io.bisq.core.trade.TradeManager;
import io.bisq.core.trade.closed.ClosedTradableManager;
import io.bisq.core.trade.failed.FailedTradesManager;
import io.bisq.core.trade.statistics.TradeStatisticsManager;
import io.bisq.core.user.Preferences;
import io.bisq.core.user.User;
@ -177,14 +179,18 @@ public class BisqApp extends Application {
User user = injector.getInstance(User.class);
user.init();
// All classes which are persisting objects need to be added here
ArrayList<PersistedDataHost> persistedDataHosts = new ArrayList<>();
persistedDataHosts.add(injector.getInstance(Navigation.class));
persistedDataHosts.add(injector.getInstance(AddressEntryList.class));
persistedDataHosts.add(injector.getInstance(TradeStatisticsManager.class));
persistedDataHosts.add(injector.getInstance(OpenOfferManager.class));
persistedDataHosts.add(injector.getInstance(TradeManager.class));
persistedDataHosts.add(injector.getInstance(ClosedTradableManager.class));
persistedDataHosts.add(injector.getInstance(FailedTradesManager.class));
// we apply at startup the reading of persisted data but don't want to get it triggered in the constructor
persistedDataHosts.stream().forEach(PersistedDataHost::readPersisted);
Version.setBtcNetworkId(injector.getInstance(BisqEnvironment.class).getBitcoinNetwork().ordinal());
Version.printVersion();

View file

@ -721,13 +721,13 @@ public class MainViewModel implements ViewModel {
if (now.after(maxTradePeriodDate))
trade.setTradePeriodState(Trade.TradePeriodState.TRADE_PERIOD_OVER);
else if (now.after(halfTradePeriodDate))
trade.setTradePeriodState(Trade.TradePeriodState.HALF_REACHED);
trade.setTradePeriodState(Trade.TradePeriodState.SECOND_HALF);
String key;
switch (trade.getTradePeriodState()) {
case NORMAL:
case FIRST_HALF:
break;
case HALF_REACHED:
case SECOND_HALF:
key = "displayHalfTradePeriodOver" + trade.getId();
if (DontShowAgainLookup.showAgain(key)) {
DontShowAgainLookup.dontShowAgain(key, true);

View file

@ -181,7 +181,7 @@ class TransactionsListItem {
} else if (trade.getPayoutTx() != null &&
trade.getPayoutTx().getHashAsString().equals(txId)) {
details = Res.get("funds.tx.multiSigPayout", id);
} else if (trade.getDisputeState() != Trade.DisputeState.NONE) {
} else if (trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE) {
if (valueSentToMe.isPositive()) {
details = Res.get("funds.tx.disputePayout", id);
} else {

View file

@ -120,7 +120,7 @@ class TakeOfferDataModel extends ActivatableDataModel {
@Override
protected void activate() {
// when leaving screen we reset state
offer.setState(Offer.State.UNDEFINED);
offer.setState(Offer.State.UNKNOWN);
addBindings();
addListeners();

View file

@ -293,7 +293,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
// 2. Before actually taking the offer in the take offer screen, we check again the availability as some time might have passed in the meantime
// So we use the takeOfferRequested flag to display different network_messages depending on the context.
switch (state) {
case UNDEFINED:
case UNKNOWN:
break;
case OFFER_FEE_PAID:
// irrelevant for taker
@ -336,7 +336,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
if (errorMessage != null) {
String appendMsg = "";
switch (trade.getState().getPhase()) {
case PREPARATION:
case INIT:
appendMsg = Res.get("takeOffer.error.noFundsLost");
break;
case TAKER_FEE_PUBLISHED:

View file

@ -202,7 +202,7 @@ public class NotificationCenter {
Res.get("shared.supportTicket") :
Res.get("shared.dispute");
switch (disputeState) {
case NONE:
case NO_DISPUTE:
break;
case DISPUTE_REQUESTED:
break;

View file

@ -144,14 +144,14 @@ public class PendingTradesDataModel extends ActivatableDataModel {
public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
checkNotNull(getTrade(), "trade must not be null");
checkArgument(getTrade() instanceof BuyerTrade, "Check failed: trade instanceof BuyerTrade");
checkArgument(getTrade().getDisputeState() == Trade.DisputeState.NONE, "Check failed: trade.getDisputeState() == Trade.DisputeState.NONE");
checkArgument(getTrade().getDisputeState() == Trade.DisputeState.NO_DISPUTE, "Check failed: trade.getDisputeState() == Trade.DisputeState.NONE");
((BuyerTrade) getTrade()).onFiatPaymentStarted(resultHandler, errorMessageHandler);
}
public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
checkNotNull(getTrade(), "trade must not be null");
checkArgument(getTrade() instanceof SellerTrade, "Check failed: trade not instanceof SellerTrade");
if (getTrade().getDisputeState() == Trade.DisputeState.NONE)
if (getTrade().getDisputeState() == Trade.DisputeState.NO_DISPUTE)
((SellerTrade) getTrade()).onFiatPaymentReceived(resultHandler, errorMessageHandler);
}

View file

@ -361,7 +361,7 @@ public abstract class TradeStepView extends AnchorPane {
private void updateDisputeState(Trade.DisputeState disputeState) {
Optional<Dispute> ownDispute;
switch (disputeState) {
case NONE:
case NO_DISPUTE:
break;
case DISPUTE_REQUESTED:
onDisputeOpened();
@ -405,9 +405,9 @@ public abstract class TradeStepView extends AnchorPane {
if (trade.getDisputeState() != Trade.DisputeState.DISPUTE_REQUESTED &&
trade.getDisputeState() != Trade.DisputeState.DISPUTE_STARTED_BY_PEER) {
switch (tradePeriodState) {
case NORMAL:
case FIRST_HALF:
break;
case HALF_REACHED:
case SECOND_HALF:
if (!trade.isFiatReceived())
showWarning();
else