implement protocol v2

This commit is contained in:
woodser 2021-08-22 16:21:56 -04:00
parent 65bcd47446
commit 86f7d090b6
185 changed files with 5117 additions and 4010 deletions

View file

@ -327,7 +327,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
secondaryNav.setAlignment(Pos.CENTER);
HBox priceAndBalance = new HBox(marketPriceBox.second, getNavigationSeparator(), availableBalanceBox.second,
getNavigationSeparator(), reservedBalanceBox.second, getNavigationSeparator(), lockedBalanceBox.second);
getNavigationSeparator(), lockedBalanceBox.second, getNavigationSeparator(), reservedBalanceBox.second);
priceAndBalance.setMaxHeight(41);
priceAndBalance.setAlignment(Pos.CENTER);

View file

@ -24,9 +24,9 @@ import bisq.desktop.components.TitledGroupBg;
import bisq.core.offer.availability.tasks.ProcessOfferAvailabilityResponse;
import bisq.core.offer.availability.tasks.SendOfferAvailabilityRequest;
import bisq.core.offer.placeoffer.tasks.AddToOfferBook;
import bisq.core.offer.placeoffer.tasks.MakerReservesTradeFunds;
import bisq.core.offer.placeoffer.tasks.ValidateOffer;
import bisq.core.trade.protocol.tasks.ApplyFilter;
import bisq.core.trade.protocol.tasks.SetupDepositTxsListener;
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
import bisq.core.trade.protocol.tasks.buyer.BuyerCreateAndSignPayoutTx;
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
@ -43,12 +43,8 @@ import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerSendsInputsForD
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerCreatesDepositTxInputs;
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSendsDepositTxMessage;
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx;
import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract;
import bisq.core.trade.protocol.tasks.maker.MakerCreateFeeTx;
import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest;
import bisq.core.trade.protocol.tasks.maker.MakerRemovesOpenOffer;
import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime;
import bisq.core.trade.protocol.tasks.maker.MakerSetupDepositTxsListener;
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.seller.SellerFinalizesDelayedPayoutTx;
@ -67,11 +63,7 @@ import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerCreatesDeposi
import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerSignsDepositTx;
import bisq.core.trade.protocol.tasks.taker.TakerCreateFeeTx;
import bisq.core.trade.protocol.tasks.taker.TakerProcessesInputsForDepositTxResponse;
import bisq.core.trade.protocol.tasks.taker.TakerProcessesMakerDepositTxMessage;
import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx;
import bisq.core.trade.protocol.tasks.taker.TakerSendInputsForDepositTxRequest;
import bisq.core.trade.protocol.tasks.taker.TakerSetupDepositTxsListener;
import bisq.core.trade.protocol.tasks.taker.TakerVerifyAndSignContract;
import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment;
import bisq.common.taskrunner.Task;
@ -118,7 +110,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
addGroup("PlaceOfferProtocol",
FXCollections.observableArrayList(Arrays.asList(
ValidateOffer.class,
MakerCreateFeeTx.class,
MakerReservesTradeFunds.class,
AddToOfferBook.class)
));
@ -129,12 +121,10 @@ public class DebugView extends InitializableView<GridPane, Void> {
TakerVerifyMakerFeePayment.class,
TakerCreateFeeTx.class, // TODO (woodser): rename to TakerCreateFeeTx
SellerAsTakerCreatesDepositTxInputs.class,
TakerSendInputsForDepositTxRequest.class,
TakerProcessesInputsForDepositTxResponse.class,
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
TakerVerifyAndSignContract.class,
TakerPublishFeeTx.class,
SellerAsTakerSignsDepositTx.class,
SellerCreatesDelayedPayoutTx.class,
@ -144,7 +134,6 @@ public class DebugView extends InitializableView<GridPane, Void> {
SellerSignsDelayedPayoutTx.class,
SellerFinalizesDelayedPayoutTx.class,
//SellerSendsDepositTxAndDelayedPayoutTxMessage.class,
TakerProcessesMakerDepositTxMessage.class,
SellerPublishesDepositTx.class,
SellerPublishesTradeStatistics.class,
@ -162,14 +151,11 @@ public class DebugView extends InitializableView<GridPane, Void> {
));
addGroup("BuyerAsMakerProtocol",
FXCollections.observableArrayList(Arrays.asList(
MakerProcessesInputsForDepositTxRequest.class,
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
MakerVerifyTakerFeePayment.class,
MakerSetsLockTime.class,
MakerCreateAndSignContract.class,
BuyerAsMakerCreatesAndSignsDepositTx.class,
MakerSetupDepositTxsListener.class,
BuyerAsMakerSendsInputsForDepositTxResponse.class,
BuyerProcessDelayedPayoutTxSignatureRequest.class,
@ -198,15 +184,12 @@ public class DebugView extends InitializableView<GridPane, Void> {
TakerVerifyMakerFeePayment.class,
TakerCreateFeeTx.class,
BuyerAsTakerCreatesDepositTxInputs.class,
TakerSendInputsForDepositTxRequest.class,
TakerProcessesInputsForDepositTxResponse.class,
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
TakerVerifyAndSignContract.class,
TakerPublishFeeTx.class,
BuyerAsTakerSignsDepositTx.class,
TakerSetupDepositTxsListener.class,
BuyerAsTakerSendsDepositTxMessage.class,
BuyerProcessDelayedPayoutTxSignatureRequest.class,
@ -227,15 +210,12 @@ public class DebugView extends InitializableView<GridPane, Void> {
));
addGroup("SellerAsMakerProtocol",
FXCollections.observableArrayList(Arrays.asList(
MakerProcessesInputsForDepositTxRequest.class,
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
MakerVerifyTakerFeePayment.class,
MakerSetsLockTime.class,
MakerCreateAndSignContract.class,
SellerAsMakerCreatesUnsignedDepositTx.class,
SellerAsMakerSendsInputsForDepositTxResponse.class,
SetupDepositTxsListener.class,
//SellerAsMakerProcessDepositTxMessage.class,
MakerRemovesOpenOffer.class,

View file

@ -55,7 +55,7 @@ class WithdrawalListItem {
// balance
balanceLabel = new AutoTooltipLabel();
balanceListener = new XmrBalanceListener(addressEntry.getAccountIndex()) {
balanceListener = new XmrBalanceListener(addressEntry.getSubaddressIndex()) {
@Override
public void onBalanceChanged(BigInteger balance) {
updateBalance();
@ -71,7 +71,7 @@ class WithdrawalListItem {
}
private void updateBalance() {
balance = walletService.getBalanceForAccount(addressEntry.getAccountIndex());
balance = walletService.getBalanceForSubaddress(addressEntry.getSubaddressIndex());
if (balance != null)
balanceLabel.setText(formatter.formatCoin(this.balance));
}

View file

@ -188,7 +188,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
useMarketBasedPrice.set(preferences.isUsePercentageBasedPrice());
buyerSecurityDeposit.set(Restrictions.getMinBuyerSecurityDepositAsPercent());
xmrBalanceListener = new XmrBalanceListener(getAddressEntry().getAccountIndex()) {
xmrBalanceListener = new XmrBalanceListener(getAddressEntry().getSubaddressIndex()) {
@Override
public void onBalanceChanged(BigInteger balance) {
updateBalance();

View file

@ -629,7 +629,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
if (newValue != null) {
stopTimeoutTimer();
createOfferRequested = false;
if (offer.getState() == Offer.State.OFFER_FEE_PAID)
if (offer.getState() == Offer.State.OFFER_FEE_RESERVED)
errorMessage.set(newValue + Res.get("createOffer.errorInfo"));
else
errorMessage.set(newValue);

View file

@ -65,7 +65,7 @@ public abstract class OfferDataModel extends ActivatableDataModel {
}
protected void updateBalance() {
Coin tradeWalletBalance = xmrWalletService.getBalanceForAccount(addressEntry.getAccountIndex());
Coin tradeWalletBalance = xmrWalletService.getBalanceForSubaddress(addressEntry.getSubaddressIndex());
if (useSavingsWallet) {
Coin savingWalletBalance = xmrWalletService.getSavingWalletBalance();
totalAvailableBalance = savingWalletBalance.add(tradeWalletBalance);

View file

@ -85,8 +85,8 @@ public class OfferBook {
.filter(item -> item.getOffer().getId().equals(offer.getId()))
.findAny();
if (candidateWithSameId.isPresent()) {
log.warn("We had an old offer in the list with the same Offer ID. We remove the old one. " +
"old offerBookListItem={}, new offerBookListItem={}", candidateWithSameId.get(), offerBookListItem);
log.warn("We had an old offer in the list with the same Offer ID {}. We remove the old one. " +
"old offerBookListItem={}, new offerBookListItem={}", offer.getId(), candidateWithSameId.get(), offerBookListItem);
offerBookListItems.remove(candidateWithSameId.get());
}

View file

@ -668,6 +668,9 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
"isInsufficientTradeLimit case.");
}
break;
case SIGNATURE_NOT_VALIDATED:
new Popup().warning(Res.get("offerbook.warning.signatureNotValidated")).show();
break;
default:
break;
}

View file

@ -52,7 +52,6 @@ import bisq.core.util.VolumeUtil;
import bisq.core.util.coin.CoinUtil;
import bisq.network.p2p.P2PService;
import bisq.common.util.Tuple2;
import org.bitcoinj.core.Coin;
@ -184,6 +183,7 @@ class TakeOfferDataModel extends OfferDataModel {
if (canTakeOffer()) {
tradeManager.checkOfferAvailability(offer,
false,
paymentAccount.getId(),
() -> {
},
errorMessage -> new Popup().warning(errorMessage).show());
@ -265,40 +265,11 @@ class TakeOfferDataModel extends OfferDataModel {
calculateVolume();
calculateTotalToPay();
balanceListener = new XmrBalanceListener(addressEntry.getAccountIndex()) {
balanceListener = new XmrBalanceListener(addressEntry.getSubaddressIndex()) {
@Override
public void onBalanceChanged(BigInteger balance) {
updateBalance();
updateBalance();
}
// public void onBalanceChanged(Coin balance, Transaction tx) {
// updateBalance();
//
// /*if (isMainNet.get()) {
// SettableFuture<Coin> future = blockchainService.requestFee(tx.getHashAsString());
// Futures.addCallback(future, new FutureCallback<Coin>() {
// public void onSuccess(Coin fee) {
// UserThread.execute(() -> setFeeFromFundingTx(fee));
// }
//
// public void onFailure(@NotNull Throwable throwable) {
// UserThread.execute(() -> new Popup<>()
// .warning("We did not get a response for the request of the mining fee used " +
// "in the funding transaction.\n\n" +
// "Are you sure you used a sufficiently high fee of at least " +
// formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + "?")
// .actionButtonText("Yes, I used a sufficiently high fee.")
// .onAction(() -> setFeeFromFundingTx(FeePolicy.getMinRequiredFeeForFundingTx()))
// .closeButtonText("No. Let's cancel that payment.")
// .onClose(() -> setFeeFromFundingTx(Coin.NEGATIVE_SATOSHI))
// .show());
// }
// });
// } else {
// setFeeFromFundingTx(FeePolicy.getMinRequiredFeeForFundingTx());
// isFeeFromFundingTxSufficient.set(feeFromFundingTx.compareTo(FeePolicy.getMinRequiredFeeForFundingTx()) >= 0);
// }*/
// }
};
offer.resetState();
@ -364,7 +335,6 @@ class TakeOfferDataModel extends OfferDataModel {
tradeManager.onTakeOffer(amount.get(),
txFeeFromFeeService,
getTakerFee(),
tradePrice.getValue(),
fundsNeededForTrade,
offer,
paymentAccount.getId(),

View file

@ -379,7 +379,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
switch (state) {
case UNKNOWN:
break;
case OFFER_FEE_PAID:
case OFFER_FEE_RESERVED:
// irrelevant for taker
break;
case AVAILABLE:

View file

@ -251,7 +251,7 @@ public class PeerInfoWithTagEditor extends Overlay<PeerInfoWithTagEditor> {
UserThread.runAfter(() -> {
PubKeyRing peersPubKeyRing = null;
if (trade != null) {
peersPubKeyRing = trade.getProcessModel().getTradingPeer().getPubKeyRing();
peersPubKeyRing = trade.getTradingPeer().getPubKeyRing();
} else if (offer != null) {
peersPubKeyRing = offer.getPubKeyRing();
}

View file

@ -148,7 +148,6 @@ public class ContractWindow extends Overlay<ContractWindow> {
if (showAcceptedBanks)
rows++;
PaymentAccountPayload sellerPaymentAccountPayload = contract.getSellerPaymentAccountPayload();
addTitledGroupBg(gridPane, ++rowIndex, rows, Res.get("contractWindow.title"));
addConfirmationLabelTextFieldWithCopyIcon(gridPane, rowIndex, Res.get("shared.offerId"), offer.getId(),
Layout.TWICE_FIRST_ROW_DISTANCE).second.setMouseTransparent(false);
@ -178,8 +177,8 @@ public class ContractWindow extends Overlay<ContractWindow> {
contract.getBuyerNodeAddress().getFullAddress() + " / " + contract.getSellerNodeAddress().getFullAddress());
addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, Res.get("contractWindow.accountAge"),
getAccountAge(contract.getBuyerPaymentAccountPayload(), contract.getBuyerPubKeyRing(), offer.getCurrencyCode()) + " / " +
getAccountAge(contract.getSellerPaymentAccountPayload(), contract.getSellerPubKeyRing(), offer.getCurrencyCode()));
getAccountAge(dispute.getBuyerPaymentAccountPayload(), contract.getBuyerPubKeyRing(), offer.getCurrencyCode()) + " / " +
getAccountAge(dispute.getSellerPaymentAccountPayload(), contract.getSellerPubKeyRing(), offer.getCurrencyCode()));
DisputeManager<? extends DisputeList<Dispute>> disputeManager = getDisputeManager(dispute);
String nrOfDisputesAsBuyer = disputeManager != null ? disputeManager.getNrOfDisputes(true, contract) : "";
@ -188,9 +187,9 @@ public class ContractWindow extends Overlay<ContractWindow> {
nrOfDisputesAsBuyer + " / " + nrOfDisputesAsSeller);
addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, Res.get("shared.paymentDetails", Res.get("shared.buyer")),
contract.getBuyerPaymentAccountPayload().getPaymentDetails()).second.setMouseTransparent(false);
dispute.getBuyerPaymentAccountPayload().getPaymentDetails()).second.setMouseTransparent(false);
addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, Res.get("shared.paymentDetails", Res.get("shared.seller")),
sellerPaymentAccountPayload.getPaymentDetails()).second.setMouseTransparent(false);
dispute.getSellerPaymentAccountPayload().getPaymentDetails()).second.setMouseTransparent(false);
String title = "";
String agentKeyBaseUserName = "";

View file

@ -603,9 +603,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
if (!dispute.isMediationDispute()) {
try {
System.out.println(disputeResult);
XmrAddressEntry arbitratorAddressEntry = walletService.getArbitratorAddressEntry();
MoneroWallet multisigWallet = walletService.getOrCreateMultisigWallet(dispute.getTradeId());
System.out.println("Arbitrator payout address entry: " + arbitratorAddressEntry.getAddressString());
MoneroWallet multisigWallet = walletService.getMultisigWallet(dispute.getTradeId());
//dispute.getContract().getArbitratorPubKeyRing(); // TODO: support arbitrator pub key ring in contract?
//disputeResult.setArbitratorPubKey(arbitratorAddressEntry.getPubKey());

View file

@ -180,8 +180,8 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
if (contract != null) {
rows++;
buyerPaymentAccountPayload = contract.getBuyerPaymentAccountPayload();
sellerPaymentAccountPayload = contract.getSellerPaymentAccountPayload();
buyerPaymentAccountPayload = trade.getBuyer().getPaymentAccountPayload();
sellerPaymentAccountPayload = trade.getSeller().getPaymentAccountPayload();
if (buyerPaymentAccountPayload != null)
rows++;
@ -235,11 +235,10 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.txFee"), txFee);
NodeAddress arbitratorNodeAddress = trade.getArbitratorNodeAddress();
NodeAddress mediatorNodeAddress = trade.getMediatorNodeAddress();
if (arbitratorNodeAddress != null && mediatorNodeAddress != null) {
if (arbitratorNodeAddress != null) {
addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex,
Res.get("tradeDetailsWindow.agentAddresses"),
arbitratorNodeAddress.getFullAddress() + " / " + mediatorNodeAddress.getFullAddress());
arbitratorNodeAddress.getFullAddress());
}
if (trade.getTradingPeerNodeAddress() != null)

View file

@ -433,10 +433,10 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
if (trade.getTakerFeeTxId() != null && trade.getTakerFeeTxId().contains(filterString)) {
return true;
}
if (trade.getMakerDepositTxId() != null && trade.getMakerDepositTxId().contains(filterString)) {
if (trade.getMaker().getDepositTxHash() != null && trade.getMaker().getDepositTxHash().contains(filterString)) {
return true;
}
if (trade.getTakerDepositTxId() != null && trade.getTakerDepositTxId().contains(filterString)) {
if (trade.getTaker().getDepositTxHash() != null && trade.getTaker().getDepositTxHash().contains(filterString)) {
return true;
}
if (trade.getPayoutTxId() != null && trade.getPayoutTxId().contains(filterString)) {
@ -451,8 +451,8 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
if (contract != null) {
isBuyerOnion = contract.getBuyerNodeAddress().getFullAddress().contains(filterString);
isSellerOnion = contract.getSellerNodeAddress().getFullAddress().contains(filterString);
matchesBuyersPaymentAccountData = contract.getBuyerPaymentAccountPayload().getPaymentDetails().contains(filterString);
matchesSellersPaymentAccountData = contract.getSellerPaymentAccountPayload().getPaymentDetails().contains(filterString);
matchesBuyersPaymentAccountData = trade.getBuyer().getPaymentAccountPayload().getPaymentDetails().contains(filterString);
matchesSellersPaymentAccountData = trade.getSeller().getPaymentAccountPayload().getPaymentDetails().contains(filterString);
}
return isBuyerOnion || isSellerOnion ||
matchesBuyersPaymentAccountData || matchesSellersPaymentAccountData;

View file

@ -199,8 +199,6 @@ class EditOfferDataModel extends MutableOfferDataModel {
offerPayload.getMinAmount(),
newOfferPayload.getBaseCurrencyCode(),
newOfferPayload.getCounterCurrencyCode(),
offerPayload.getArbitratorNodeAddresses(),
offerPayload.getMediatorNodeAddresses(),
newOfferPayload.getPaymentMethodId(),
newOfferPayload.getMakerPaymentAccountId(),
offerPayload.getOfferFeePaymentTxId(),
@ -224,7 +222,9 @@ class EditOfferDataModel extends MutableOfferDataModel {
offerPayload.isPrivateOffer(),
offerPayload.getHashOfChallenge(),
offerPayload.getExtraDataMap(),
offerPayload.getProtocolVersion());
offerPayload.getProtocolVersion(),
offerPayload.getArbitratorNodeAddress(),
offerPayload.getArbitratorSignature());
final Offer editedOffer = new Offer(editedPayload);
editedOffer.setPriceFeedService(priceFeedService);

View file

@ -282,10 +282,10 @@ public class FailedTradesView extends ActivatableViewAndModel<VBox, FailedTrades
if (trade.getTakerFeeTxId() != null && trade.getTakerFeeTxId().contains(filterString)) {
return true;
}
if (trade.getMakerDepositTxId() != null && trade.getMakerDepositTxId().contains(filterString)) {
if (trade.getMaker().getDepositTxHash() != null && trade.getMaker().getDepositTxHash().contains(filterString)) {
return true;
}
if (trade.getTakerDepositTxId() != null && trade.getTakerDepositTxId().contains(filterString)) {
if (trade.getTaker().getDepositTxHash() != null && trade.getTaker().getDepositTxHash().contains(filterString)) {
return true;
}
if (trade.getPayoutTxId() != null && trade.getPayoutTxId().contains(filterString)) {
@ -301,8 +301,8 @@ public class FailedTradesView extends ActivatableViewAndModel<VBox, FailedTrades
if (contract != null) {
isBuyerOnion = contract.getBuyerNodeAddress().getFullAddress().contains(filterString);
isSellerOnion = contract.getSellerNodeAddress().getFullAddress().contains(filterString);
matchesBuyersPaymentAccountData = contract.getBuyerPaymentAccountPayload().getPaymentDetails().contains(filterString);
matchesSellersPaymentAccountData = contract.getSellerPaymentAccountPayload().getPaymentDetails().contains(filterString);
matchesBuyersPaymentAccountData = trade.getBuyer().getPaymentAccountPayload().getPaymentDetails().contains(filterString);
matchesSellersPaymentAccountData = trade.getSeller().getPaymentAccountPayload().getPaymentDetails().contains(filterString);
}
return isBuyerOnion || isSellerOnion ||
matchesBuyersPaymentAccountData || matchesSellersPaymentAccountData;

View file

@ -341,18 +341,14 @@ public class PendingTradesDataModel extends ActivatableDataModel {
@Nullable
public PaymentAccountPayload getSellersPaymentAccountPayload() {
if (getTrade() != null && getTrade().getContract() != null)
return getTrade().getContract().getSellerPaymentAccountPayload();
else
return null;
if (getTrade() == null) return null;
return getTrade().getSeller().getPaymentAccountPayload();
}
@Nullable
public PaymentAccountPayload getBuyersPaymentAccountPayload() {
if (getTrade() != null && getTrade().getContract() != null)
return getTrade().getContract().getBuyerPaymentAccountPayload();
else
return null;
if (getTrade() == null) return null;
return getTrade().getBuyer().getPaymentAccountPayload();
}
public String getReference() {
@ -459,19 +455,19 @@ public class PendingTradesDataModel extends ActivatableDataModel {
// in such cases. The mediators or arbitrators could not help anyway with a payout in such cases.
String depositTxId = null;
if (isMaker) {
if (trade.getMakerDepositTxId() == null) {
if (trade.getMaker().getDepositTxHash() == null) {
log.error("Deposit tx must not be null");
new Popup().instruction(Res.get("portfolio.pending.error.depositTxNull")).show();
return;
}
depositTxId = trade.getMakerDepositTxId();
depositTxId = trade.getMaker().getDepositTxHash();
} else {
if (trade.getTakerDepositTxId() == null) {
if (trade.getTaker().getDepositTxHash() == null) {
log.error("Deposit tx must not be null");
new Popup().instruction(Res.get("portfolio.pending.error.depositTxNull")).show();
return;
}
depositTxId = trade.getTakerDepositTxId();
depositTxId = trade.getTaker().getDepositTxHash();
}
Offer offer = trade.getOffer();
@ -487,7 +483,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
byte[] payoutTxSerialized = null;
String payoutTxHashAsString = null;
MoneroTxWallet payoutTx = trade.getPayoutTx();
MoneroWallet multisigWallet = xmrWalletService.getOrCreateMultisigWallet(trade.getId());
MoneroWallet multisigWallet = xmrWalletService.getMultisigWallet(trade.getId());
String updatedMultisigHex = multisigWallet.getMultisigHex();
if (payoutTx != null) {
// payoutTxSerialized = payoutTx.bitcoinSerialize(); // TODO (woodser): no need to pass serialized txs for xmr
@ -542,8 +538,8 @@ public class PendingTradesDataModel extends ActivatableDataModel {
// If no dispute state set we start with mediation
resultHandler = () -> navigation.navigateTo(MainView.class, SupportView.class, MediationClientView.class);
disputeManager = mediationManager;
PubKeyRing mediatorPubKeyRing = trade.getMediatorPubKeyRing();
checkNotNull(mediatorPubKeyRing, "mediatorPubKeyRing must not be null");
PubKeyRing arbitratorPubKeyRing = trade.getArbitratorPubKeyRing();
checkNotNull(arbitratorPubKeyRing, "arbitratorPubKeyRing must not be null");
byte[] depositTxSerialized = null; // depositTx.bitcoinSerialize(); // TODO (woodser): no serialized txs in xmr
Dispute dispute = new Dispute(new Date().getTime(),
trade.getId(),
@ -561,9 +557,11 @@ public class PendingTradesDataModel extends ActivatableDataModel {
depositTxId,
payoutTxHashAsString,
trade.getContractAsJson(),
trade.getMakerContractSignature(),
trade.getTakerContractSignature(),
mediatorPubKeyRing,
trade.getMaker().getContractSignature(),
trade.getTaker().getContractSignature(),
trade.getMaker().getPaymentAccountPayload(),
trade.getTaker().getPaymentAccountPayload(),
arbitratorPubKeyRing,
isSupportTicket,
SupportType.MEDIATION);
dispute.setExtraData("counterCurrencyTxId", trade.getCounterCurrencyTxId());
@ -595,8 +593,10 @@ public class PendingTradesDataModel extends ActivatableDataModel {
depositTxHashAsString,
payoutTxHashAsString,
trade.getContractAsJson(),
trade.getMakerContractSignature(),
trade.getTakerContractSignature(),
trade.getMaker().getContractSignature(),
trade.getTaker().getContractSignature(),
trade.getMaker().getPaymentAccountPayload(),
trade.getTaker().getPaymentAccountPayload(),
arbitratorPubKeyRing,
isSupportTicket,
SupportType.ARBITRATION);

View file

@ -190,8 +190,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
}
public void setMessageStateProperty(MessageState messageState) {
if (messageStateProperty.get() == MessageState.ACKNOWLEDGED) {
log.warn("We have already an ACKNOWLEDGED message received. " +
// ARRIVED is set internally after ACKNOWLEDGED, otherwise warn if subsequent states received
if ((messageStateProperty.get() == MessageState.ACKNOWLEDGED && messageState != MessageState.ARRIVED) || messageStateProperty.get() == MessageState.ARRIVED) {
log.warn("We have already an ACKNOWLEDGED/ARRIVED message received. " +
"We would not expect any other message after that. Received messageState={}", messageState);
return;
}

View file

@ -64,7 +64,7 @@ import javafx.geometry.Insets;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.value.ChangeListener;
@ -409,6 +409,21 @@ public abstract class TradeStepView extends AnchorPane {
private void updateTimeLeft() {
if (timeLeftTextField != null) {
// TODO (woodser): extra TradeStepView created but not deactivated on trade.setState(), so deactivate when model's trade is null
if (model.dataModel.getTrade() == null) {
log.warn("deactivating TradeStepView because model's trade is null");
// schedule deactivation to avoid concurrent modification of clock listeners
Platform.runLater(new Runnable() {
@Override
public void run() {
deactivate();
}
});
return;
}
String remainingTime = model.getRemainingTradeDurationAsWords();
timeLeftProgressBar.setProgress(model.getRemainingTradeDurationAsPercentage());
if (!remainingTime.isEmpty()) {
@ -625,7 +640,7 @@ public abstract class TradeStepView extends AnchorPane {
}
private boolean peerAccepted() {
return trade.getProcessModel().getTradingPeer().getMediatedPayoutTxSignature() != null;
return trade.getTradingPeer().getMediatedPayoutTxSignature() != null;
}
private void openMediationResultPopup(String headLine) {

View file

@ -209,8 +209,8 @@ public class SellerStep3View extends TradeStepView {
String currencyName = getCurrencyName(trade);
Contract contract = trade.getContract();
if (contract != null) {
PaymentAccountPayload myPaymentAccountPayload = contract.getSellerPaymentAccountPayload();
PaymentAccountPayload peersPaymentAccountPayload = contract.getBuyerPaymentAccountPayload();
PaymentAccountPayload myPaymentAccountPayload = trade.getSeller().getPaymentAccountPayload();
PaymentAccountPayload peersPaymentAccountPayload = trade.getBuyer().getPaymentAccountPayload();
myPaymentDetails = PaymentAccountUtil.findPaymentAccount(myPaymentAccountPayload, model.getUser())
.map(PaymentAccount::getAccountName)
@ -453,7 +453,7 @@ public class SellerStep3View extends TradeStepView {
private Optional<String> getOptionalHolderName() {
Contract contract = trade.getContract();
if (contract != null) {
PaymentAccountPayload paymentAccountPayload = contract.getBuyerPaymentAccountPayload();
PaymentAccountPayload paymentAccountPayload = trade.getBuyer().getPaymentAccountPayload();
if (paymentAccountPayload instanceof BankAccountPayload)
return Optional.of(((BankAccountPayload) paymentAccountPayload).getHolderName());
else if (paymentAccountPayload instanceof SepaAccountPayload)

View file

@ -453,11 +453,11 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
return FilterResult.SELLER_NODE_ADDRESS;
}
if (dispute.getContract().getBuyerPaymentAccountPayload().getPaymentDetails().toLowerCase().contains(filter)) {
if (dispute.getBuyerPaymentAccountPayload().getPaymentDetails().toLowerCase().contains(filter)) {
return FilterResult.BUYER_ACCOUNT_DETAILS;
}
if (dispute.getContract().getSellerPaymentAccountPayload().getPaymentDetails().toLowerCase().contains(filter)) {
if (dispute.getSellerPaymentAccountPayload().getPaymentDetails().toLowerCase().contains(filter)) {
return FilterResult.SELLER_ACCOUNT_DETAILS;
}
@ -750,10 +750,10 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
.append(")\n");
String buyerPaymentAccountPayload = Utilities.toTruncatedString(
contract.getBuyerPaymentAccountPayload().getPaymentDetails().
firstDispute.getBuyerPaymentAccountPayload().getPaymentDetails().
replace("\n", " ").replace(";", "."), 100);
String sellerPaymentAccountPayload = Utilities.toTruncatedString(
contract.getSellerPaymentAccountPayload().getPaymentDetails()
firstDispute.getSellerPaymentAccountPayload().getPaymentDetails()
.replace("\n", " ").replace(";", "."), 100);
String buyerNodeAddress = contract.getBuyerNodeAddress().getFullAddress();
String sellerNodeAddress = contract.getSellerNodeAddress().getFullAddress();
@ -1226,7 +1226,7 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
NodeAddress buyerNodeAddress = contract.getBuyerNodeAddress();
if (buyerNodeAddress != null) {
String nrOfDisputes = disputeManager.getNrOfDisputes(true, contract);
long accountAge = accountAgeWitnessService.getAccountAge(contract.getBuyerPaymentAccountPayload(), contract.getBuyerPubKeyRing());
long accountAge = accountAgeWitnessService.getAccountAge(item.getBuyerPaymentAccountPayload(), contract.getBuyerPubKeyRing());
String age = DisplayUtils.formatAccountAge(accountAge);
String postFix = CurrencyUtil.isFiatCurrency(item.getContract().getOfferPayload().getCurrencyCode()) ? " / " + age : "";
return buyerNodeAddress.getHostNameWithoutPostFix() + " (" + nrOfDisputes + postFix + ")";
@ -1243,7 +1243,7 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
NodeAddress sellerNodeAddress = contract.getSellerNodeAddress();
if (sellerNodeAddress != null) {
String nrOfDisputes = disputeManager.getNrOfDisputes(false, contract);
long accountAge = accountAgeWitnessService.getAccountAge(contract.getSellerPaymentAccountPayload(), contract.getSellerPubKeyRing());
long accountAge = accountAgeWitnessService.getAccountAge(item.getSellerPaymentAccountPayload(), contract.getSellerPubKeyRing());
String age = DisplayUtils.formatAccountAge(accountAge);
String postFix = CurrencyUtil.isFiatCurrency(item.getContract().getOfferPayload().getCurrencyCode()) ? " / " + age : "";
return sellerNodeAddress.getHostNameWithoutPostFix() + " (" + nrOfDisputes + postFix + ")";

View file

@ -582,7 +582,7 @@ public class GUIUtil {
break;
case BUILDING:
tooltip.setText(Res.get("confidence.confirmed", confidence.getDepthInBlocks()));
txConfidenceIndicator.setProgress(Math.min(1, (double) confidence.getDepthInBlocks() / 6.0));
txConfidenceIndicator.setProgress(Math.min(1, confidence.getDepthInBlocks() / 6.0));
break;
case DEAD:
tooltip.setText(Res.get("confidence.invalid"));
@ -786,9 +786,12 @@ public class GUIUtil {
}
public static boolean canCreateOrTakeOfferOrShowPopup(User user, Navigation navigation) {
// TODO (woodser): use refund agents to dispute arbitration?
if (!user.hasAcceptedRefundAgents()) {
new Popup().warning(Res.get("popup.warning.noArbitratorsAvailable")).show();
return false;
log.warn("There are no refund agents available"); // TODO (woodser): refund agents changing from [4444] to [] causing this error
//new Popup().warning(Res.get("popup.warning.noArbitratorsAvailable")).show();
//return false;
}
if (!user.hasAcceptedMediators()) {