mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-22 19:49:32 +00:00
seller publishes trade statistics if trade amount transferred
This commit is contained in:
parent
3e2206cf5e
commit
14d17023a8
3 changed files with 57 additions and 30 deletions
|
@ -424,6 +424,7 @@ public abstract class Trade implements Tradable, Model {
|
|||
transient private Subscription tradeStateSubscription;
|
||||
transient private Subscription tradePhaseSubscription;
|
||||
transient private Subscription payoutStateSubscription;
|
||||
transient private Subscription disputeStateSubscription;
|
||||
transient private TaskLooper pollLooper;
|
||||
transient private Long pollPeriodMs;
|
||||
transient private Long pollNormalStartTimeMs;
|
||||
|
@ -696,6 +697,9 @@ public abstract class Trade implements Tradable, Model {
|
|||
// auto complete arbitrator trade
|
||||
if (isArbitrator() && !isCompleted()) processModel.getTradeManager().onTradeCompleted(this);
|
||||
|
||||
// maybe publish trade statistic
|
||||
maybePublishTradeStatistics();
|
||||
|
||||
// reset address entries
|
||||
processModel.getXmrWalletService().resetAddressEntriesForTrade(getId());
|
||||
}
|
||||
|
@ -709,6 +713,16 @@ public abstract class Trade implements Tradable, Model {
|
|||
});
|
||||
});
|
||||
|
||||
// handle dispute events
|
||||
disputeStateSubscription = EasyBind.subscribe(disputeStateProperty, newValue -> {
|
||||
if (!isInitialized || isShutDownStarted) return;
|
||||
ThreadUtils.submitToPool(() -> {
|
||||
if (isDisputeClosed()) {
|
||||
maybePublishTradeStatistics();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// arbitrator syncs idle wallet when payout unlock expected
|
||||
if (this instanceof ArbitratorTrade) {
|
||||
idlePayoutSyncer = new IdlePayoutSyncer();
|
||||
|
@ -1422,6 +1436,7 @@ public abstract class Trade implements Tradable, Model {
|
|||
if (tradeStateSubscription != null) tradeStateSubscription.unsubscribe();
|
||||
if (tradePhaseSubscription != null) tradePhaseSubscription.unsubscribe();
|
||||
if (payoutStateSubscription != null) payoutStateSubscription.unsubscribe();
|
||||
if (disputeStateSubscription != null) disputeStateSubscription.unsubscribe();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1998,6 +2013,10 @@ public abstract class Trade implements Tradable, Model {
|
|||
return isArbitrator() ? getBuyer().getDisputeClosedMessage() != null || getSeller().getDisputeClosedMessage() != null : getArbitrator().getDisputeClosedMessage() != null;
|
||||
}
|
||||
|
||||
public boolean isDisputeClosed() {
|
||||
return getDisputeState().isClosed();
|
||||
}
|
||||
|
||||
public boolean isPaymentReceived() {
|
||||
return getState().getPhase().ordinal() >= Phase.PAYMENT_RECEIVED.ordinal();
|
||||
}
|
||||
|
@ -2149,6 +2168,39 @@ public abstract class Trade implements Tradable, Model {
|
|||
return Math.min(MAX_REPROCESS_DELAY_SECONDS, delay);
|
||||
}
|
||||
|
||||
public void maybePublishTradeStatistics() {
|
||||
if (shouldPublishTradeStatistics()) doPublishTradeStatistics();
|
||||
}
|
||||
|
||||
public boolean shouldPublishTradeStatistics() {
|
||||
if (!isSeller()) return false;
|
||||
return tradeAmountTransferred();
|
||||
}
|
||||
|
||||
private boolean tradeAmountTransferred() {
|
||||
return isPaymentReceived() || (getDisputeResult() != null && getDisputeResult().getWinner() == DisputeResult.Winner.SELLER);
|
||||
}
|
||||
|
||||
private void doPublishTradeStatistics() {
|
||||
processModel.getP2PService().findPeersCapabilities(getTradePeer().getNodeAddress())
|
||||
.filter(capabilities -> capabilities.containsAll(Capability.TRADE_STATISTICS_3))
|
||||
.ifPresentOrElse(capabilities -> {
|
||||
String referralId = processModel.getReferralIdService().getOptionalReferralId().orElse(null);
|
||||
boolean isTorNetworkNode = getProcessModel().getP2PService().getNetworkNode() instanceof TorNetworkNode;
|
||||
TradeStatistics3 tradeStatistics = TradeStatistics3.from(this, referralId, isTorNetworkNode);
|
||||
if (tradeStatistics.isValid()) {
|
||||
log.info("Publishing trade statistics");
|
||||
processModel.getP2PService().addPersistableNetworkPayload(tradeStatistics, true);
|
||||
} else {
|
||||
log.warn("Trade statistics are invalid. We do not publish. {}", tradeStatistics);
|
||||
}
|
||||
},
|
||||
() -> {
|
||||
log.info("Our peer does not has updated yet, so they will publish the trade statistics. " +
|
||||
"To avoid duplicates we do not publish from our side.");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
|
@ -2566,31 +2618,6 @@ public abstract class Trade implements Tradable, Model {
|
|||
} else {
|
||||
getXmrWalletService().resetAddressEntriesForOpenOffer(getId());
|
||||
}
|
||||
|
||||
// seller publishes trade statistics
|
||||
if (this instanceof SellerTrade) {
|
||||
checkNotNull(getSeller().getDepositTx());
|
||||
processModel.getP2PService().findPeersCapabilities(getTradePeer().getNodeAddress())
|
||||
.filter(capabilities -> capabilities.containsAll(Capability.TRADE_STATISTICS_3))
|
||||
.ifPresentOrElse(capabilities -> {
|
||||
|
||||
// Our peer has updated, so as we are the seller we will publish the trade statistics.
|
||||
// The peer as buyer does not publish anymore with v.1.4.0 (where Capability.TRADE_STATISTICS_3 was added)
|
||||
String referralId = processModel.getReferralIdService().getOptionalReferralId().orElse(null);
|
||||
boolean isTorNetworkNode = getProcessModel().getP2PService().getNetworkNode() instanceof TorNetworkNode;
|
||||
TradeStatistics3 tradeStatistics = TradeStatistics3.from(this, referralId, isTorNetworkNode);
|
||||
if (tradeStatistics.isValid()) {
|
||||
log.info("Publishing trade statistics");
|
||||
processModel.getP2PService().addPersistableNetworkPayload(tradeStatistics, true);
|
||||
} else {
|
||||
log.warn("Trade statistics are invalid. We do not publish. {}", tradeStatistics);
|
||||
}
|
||||
},
|
||||
() -> {
|
||||
log.info("Our peer does not has updated yet, so they will publish the trade statistics. " +
|
||||
"To avoid duplicates we do not publish from our side.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -103,6 +103,9 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
|||
for (Dispute dispute : trade.getDisputes()) dispute.setIsClosed();
|
||||
}
|
||||
|
||||
// advance state, arbitrator auto completes when payout published
|
||||
trade.advanceState(Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG);
|
||||
|
||||
// publish signed witness
|
||||
SignedWitness signedWitness = message.getBuyerSignedWitness();
|
||||
if (signedWitness != null && trade instanceof BuyerTrade) {
|
||||
|
@ -113,7 +116,6 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
|||
}
|
||||
|
||||
// complete
|
||||
trade.advanceState(Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG); // arbitrator auto completes when payout published
|
||||
trade.requestPersistence();
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -26,7 +26,6 @@ import haveno.core.locale.CurrencyTuple;
|
|||
import haveno.core.locale.CurrencyUtil;
|
||||
import haveno.core.locale.Res;
|
||||
import haveno.core.provider.price.PriceFeedService;
|
||||
import haveno.core.trade.SellerTrade;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.util.JsonUtil;
|
||||
import haveno.network.p2p.P2PService;
|
||||
|
@ -200,9 +199,8 @@ public class TradeStatisticsManager {
|
|||
long ts = System.currentTimeMillis();
|
||||
Set<P2PDataStorage.ByteArray> hashes = tradeStatistics3StorageService.getMapOfAllData().keySet();
|
||||
trades.forEach(trade -> {
|
||||
if (!(trade instanceof SellerTrade)) {
|
||||
log.debug("Trade: {} is not a seller trade, we only republish if we were seller",
|
||||
trade.getShortId());
|
||||
if (!trade.shouldPublishTradeStatistics()) {
|
||||
log.debug("Trade: {} should not publish trade statistics", trade.getShortId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue