Fix bug with tx broadcast state

This commit is contained in:
Manfred Karrer 2016-02-12 18:23:15 +01:00
parent e5cfc2892b
commit 43d811d9fe
12 changed files with 59 additions and 69 deletions

View file

@ -233,8 +233,6 @@ abstract public class Trade implements Tradable, Model, Serializable {
createProtocol(); createProtocol();
tradeProtocol.checkPayoutTxTimeLock(this);
if (decryptedMsgWithPubKey != null) { if (decryptedMsgWithPubKey != null) {
tradeProtocol.applyMailboxMessage(decryptedMsgWithPubKey, this); tradeProtocol.applyMailboxMessage(decryptedMsgWithPubKey, this);
} }

View file

@ -30,9 +30,9 @@ import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest;
import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
import io.bitsquare.trade.protocol.trade.tasks.buyer.*; import io.bitsquare.trade.protocol.trade.tasks.buyer.*;
import io.bitsquare.trade.protocol.trade.tasks.offerer.*; import io.bitsquare.trade.protocol.trade.tasks.offerer.*;
import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime;
import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx; import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx;
import io.bitsquare.trade.protocol.trade.tasks.shared.InitWaitPeriodForOpenDispute; import io.bitsquare.trade.protocol.trade.tasks.shared.InitWaitPeriodForOpenDispute;
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -56,7 +56,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
// If we are after the time lock state we need to setup the listener again // If we are after the time lock state we need to setup the listener again
Trade.State tradeState = trade.getState(); Trade.State tradeState = trade.getState();
if (tradeState.getPhase() == Trade.Phase.PAYOUT_PAID) { if (tradeState.getPhase() == Trade.Phase.PAYOUT_PAID && tradeState != Trade.State.PAYOUT_BROAD_CASTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade, TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> { () -> {
@ -65,7 +65,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
}, },
this::handleTaskRunnerFault); this::handleTaskRunnerFault);
taskRunner.addTasks(SetupPayoutTxLockTimeReachedListener.class); taskRunner.addTasks(BroadcastAfterLockTime.class);
taskRunner.run(); taskRunner.run();
} }
} }
@ -185,7 +185,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
SignAndFinalizePayoutTx.class, SignAndFinalizePayoutTx.class,
CommitPayoutTx.class, CommitPayoutTx.class,
SendPayoutTxFinalizedMessage.class, SendPayoutTxFinalizedMessage.class,
SetupPayoutTxLockTimeReachedListener.class BroadcastAfterLockTime.class
); );
taskRunner.run(); taskRunner.run();
} }

View file

@ -29,8 +29,8 @@ import io.bitsquare.trade.protocol.trade.messages.FinalizePayoutTxRequest;
import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest; import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest;
import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
import io.bitsquare.trade.protocol.trade.tasks.buyer.*; import io.bitsquare.trade.protocol.trade.tasks.buyer.*;
import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime;
import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx; import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx;
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
import io.bitsquare.trade.protocol.trade.tasks.taker.*; import io.bitsquare.trade.protocol.trade.tasks.taker.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -54,7 +54,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
// If we are after the timeLock state we need to setup the listener again // If we are after the timeLock state we need to setup the listener again
Trade.State tradeState = trade.getState(); Trade.State tradeState = trade.getState();
if (tradeState.getPhase() == Trade.Phase.PAYOUT_PAID) { if (tradeState.getPhase() == Trade.Phase.PAYOUT_PAID && tradeState != Trade.State.PAYOUT_BROAD_CASTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade, TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> { () -> {
handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener"); handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener");
@ -62,7 +62,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
}, },
this::handleTaskRunnerFault); this::handleTaskRunnerFault);
taskRunner.addTasks(SetupPayoutTxLockTimeReachedListener.class); taskRunner.addTasks(BroadcastAfterLockTime.class);
taskRunner.run(); taskRunner.run();
} }
} }
@ -173,7 +173,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
SignAndFinalizePayoutTx.class, SignAndFinalizePayoutTx.class,
CommitPayoutTx.class, CommitPayoutTx.class,
SendPayoutTxFinalizedMessage.class, SendPayoutTxFinalizedMessage.class,
SetupPayoutTxLockTimeReachedListener.class BroadcastAfterLockTime.class
); );
taskRunner.run(); taskRunner.run();
} }

View file

@ -26,9 +26,9 @@ import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.messages.*; import io.bitsquare.trade.protocol.trade.messages.*;
import io.bitsquare.trade.protocol.trade.tasks.offerer.*; import io.bitsquare.trade.protocol.trade.tasks.offerer.*;
import io.bitsquare.trade.protocol.trade.tasks.seller.*; import io.bitsquare.trade.protocol.trade.tasks.seller.*;
import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime;
import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx; import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx;
import io.bitsquare.trade.protocol.trade.tasks.shared.InitWaitPeriodForOpenDispute; import io.bitsquare.trade.protocol.trade.tasks.shared.InitWaitPeriodForOpenDispute;
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -53,7 +53,7 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
// If we are after the time lock state we need to setup the listener again // If we are after the time lock state we need to setup the listener again
//TODO not sure if that is not called already from the checkPayoutTxTimeLock at tradeProtocol //TODO not sure if that is not called already from the checkPayoutTxTimeLock at tradeProtocol
Trade.State tradeState = trade.getState(); Trade.State tradeState = trade.getState();
if (tradeState.getPhase() == Trade.Phase.PAYOUT_PAID) { if (tradeState.getPhase() == Trade.Phase.PAYOUT_PAID && tradeState != Trade.State.PAYOUT_BROAD_CASTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade, TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> { () -> {
handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener"); handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener");
@ -61,7 +61,7 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
}, },
this::handleTaskRunnerFault); this::handleTaskRunnerFault);
taskRunner.addTasks(SetupPayoutTxLockTimeReachedListener.class); taskRunner.addTasks(BroadcastAfterLockTime.class);
taskRunner.run(); taskRunner.run();
} }
} }
@ -189,7 +189,7 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
taskRunner.addTasks( taskRunner.addTasks(
ProcessPayoutTxFinalizedMessage.class, ProcessPayoutTxFinalizedMessage.class,
CommitPayoutTx.class, CommitPayoutTx.class,
SetupPayoutTxLockTimeReachedListener.class BroadcastAfterLockTime.class
); );
taskRunner.run(); taskRunner.run();
} }

View file

@ -28,8 +28,8 @@ import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest; import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest;
import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
import io.bitsquare.trade.protocol.trade.tasks.seller.*; import io.bitsquare.trade.protocol.trade.tasks.seller.*;
import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime;
import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx; import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx;
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
import io.bitsquare.trade.protocol.trade.tasks.taker.*; import io.bitsquare.trade.protocol.trade.tasks.taker.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -54,7 +54,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
// If we are after the timeLock state we need to setup the listener again // If we are after the timeLock state we need to setup the listener again
//TODO not sure if that is not called already from the checkPayoutTxTimeLock at tradeProtocol //TODO not sure if that is not called already from the checkPayoutTxTimeLock at tradeProtocol
Trade.State tradeState = trade.getState(); Trade.State tradeState = trade.getState();
if (tradeState.getPhase() == Trade.Phase.PAYOUT_PAID) { if (tradeState.getPhase() == Trade.Phase.PAYOUT_PAID && tradeState != Trade.State.PAYOUT_BROAD_CASTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade, TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> { () -> {
handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener"); handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener");
@ -62,7 +62,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
}, },
this::handleTaskRunnerFault); this::handleTaskRunnerFault);
taskRunner.addTasks(SetupPayoutTxLockTimeReachedListener.class); taskRunner.addTasks(BroadcastAfterLockTime.class);
taskRunner.run(); taskRunner.run();
} }
} }
@ -188,7 +188,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
taskRunner.addTasks( taskRunner.addTasks(
ProcessPayoutTxFinalizedMessage.class, ProcessPayoutTxFinalizedMessage.class,
CommitPayoutTx.class, CommitPayoutTx.class,
SetupPayoutTxLockTimeReachedListener.class BroadcastAfterLockTime.class
); );
taskRunner.run(); taskRunner.run();
} }

View file

@ -28,7 +28,6 @@ import io.bitsquare.trade.TakerTrade;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.TradeManager;
import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -104,22 +103,6 @@ public abstract class TradeProtocol {
protected abstract void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress); protected abstract void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress);
public void checkPayoutTxTimeLock(Trade trade) {
this.trade = trade;
if (trade.getState() == Trade.State.PAYOUT_TX_COMMITTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
log.debug("taskRunner needPayoutTxBroadcast completed");
processModel.onComplete();
},
this::handleTaskRunnerFault);
taskRunner.addTasks(SetupPayoutTxLockTimeReachedListener.class);
taskRunner.run();
}
}
protected void startTimeout() { protected void startTimeout() {
stopTimeout(); stopTimeout();

View file

@ -25,16 +25,17 @@ import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask; import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.bitcoinj.core.StoredBlock; import org.bitcoinj.core.StoredBlock;
import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
public class SetupPayoutTxLockTimeReachedListener extends TradeTask { public class BroadcastAfterLockTime extends TradeTask {
private static final Logger log = LoggerFactory.getLogger(SetupPayoutTxLockTimeReachedListener.class); private static final Logger log = LoggerFactory.getLogger(BroadcastAfterLockTime.class);
public SetupPayoutTxLockTimeReachedListener(TaskRunner taskHandler, Trade trade) { public BroadcastAfterLockTime(TaskRunner taskHandler, Trade trade) {
super(taskHandler, trade); super(taskHandler, trade);
} }
@ -66,6 +67,18 @@ public class SetupPayoutTxLockTimeReachedListener extends TradeTask {
} }
private void broadcastTx() { private void broadcastTx() {
boolean needsBroadCast = true;
Transaction walletTx = processModel.getTradeWalletService().getWalletTx(trade.getPayoutTx().getHash());
if (walletTx != null) {
TransactionConfidence.ConfidenceType confidenceType = walletTx.getConfidence().getConfidenceType();
if (confidenceType.equals(TransactionConfidence.ConfidenceType.PENDING) ||
confidenceType.equals(TransactionConfidence.ConfidenceType.BUILDING)) {
needsBroadCast = false;
trade.setState(Trade.State.PAYOUT_BROAD_CASTED);
complete();
}
}
if (needsBroadCast) {
processModel.getTradeWalletService().broadcastTx(trade.getPayoutTx(), new FutureCallback<Transaction>() { processModel.getTradeWalletService().broadcastTx(trade.getPayoutTx(), new FutureCallback<Transaction>() {
@Override @Override
public void onSuccess(Transaction transaction) { public void onSuccess(Transaction transaction) {
@ -81,3 +94,4 @@ public class SetupPayoutTxLockTimeReachedListener extends TradeTask {
}); });
} }
} }
}

View file

@ -110,13 +110,11 @@ public class BuyerSubView extends TradeSubView {
step2.setCompleted(); step2.setCompleted();
showItem(step3); showItem(step3);
break; break;
case WAIT_FOR_UNLOCK_PAYOUT: case WAIT_FOR_BROADCAST_AFTER_UNLOCK:
if (model.getLockTime() > 0) {
step1.setCompleted(); step1.setCompleted();
step2.setCompleted(); step2.setCompleted();
step3.setCompleted(); step3.setCompleted();
showItem(step4); showItem(step4);
}
break; break;
case REQUEST_WITHDRAWAL: case REQUEST_WITHDRAWAL:
step1.setCompleted(); step1.setCompleted();

View file

@ -53,7 +53,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
WAIT_FOR_BLOCKCHAIN_CONFIRMATION, WAIT_FOR_BLOCKCHAIN_CONFIRMATION,
REQUEST_START_FIAT_PAYMENT, REQUEST_START_FIAT_PAYMENT,
WAIT_FOR_FIAT_PAYMENT_RECEIPT, WAIT_FOR_FIAT_PAYMENT_RECEIPT,
WAIT_FOR_UNLOCK_PAYOUT, WAIT_FOR_BROADCAST_AFTER_UNLOCK,
REQUEST_WITHDRAWAL REQUEST_WITHDRAWAL
} }
@ -63,7 +63,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
WAIT_FOR_FIAT_PAYMENT_STARTED, WAIT_FOR_FIAT_PAYMENT_STARTED,
REQUEST_CONFIRM_FIAT_PAYMENT_RECEIVED, REQUEST_CONFIRM_FIAT_PAYMENT_RECEIVED,
WAIT_FOR_PAYOUT_TX, WAIT_FOR_PAYOUT_TX,
WAIT_FOR_UNLOCK_PAYOUT, WAIT_FOR_BROADCAST_AFTER_UNLOCK,
REQUEST_WITHDRAWAL REQUEST_WITHDRAWAL
} }
@ -412,12 +412,12 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
case PAYOUT_TX_SENT: case PAYOUT_TX_SENT:
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_UNLOCK_PAYOUT); buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK);
break; break;
case PAYOUT_TX_RECEIVED: case PAYOUT_TX_RECEIVED:
break; break;
case PAYOUT_TX_COMMITTED: case PAYOUT_TX_COMMITTED:
sellerState.set(WAIT_FOR_UNLOCK_PAYOUT); sellerState.set(SellerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK);
break; break;
case PAYOUT_BROAD_CASTED: case PAYOUT_BROAD_CASTED:
sellerState.set(REQUEST_WITHDRAWAL); sellerState.set(REQUEST_WITHDRAWAL);

View file

@ -20,7 +20,6 @@ package io.bitsquare.gui.main.portfolio.pendingtrades;
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem; import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller.*; import io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller.*;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.scene.layout.GridPane;
public class SellerSubView extends TradeSubView { public class SellerSubView extends TradeSubView {
private TradeWizardItem step1; private TradeWizardItem step1;
@ -59,7 +58,7 @@ public class SellerSubView extends TradeSubView {
step1 = new TradeWizardItem(SellerStep1View.class, "Wait for blockchain confirmation"); step1 = new TradeWizardItem(SellerStep1View.class, "Wait for blockchain confirmation");
step2 = new TradeWizardItem(SellerStep2View.class, "Wait until payment has started"); step2 = new TradeWizardItem(SellerStep2View.class, "Wait until payment has started");
step3 = new TradeWizardItem(SellerStep3View.class, "Confirm payment received"); step3 = new TradeWizardItem(SellerStep3View.class, "Confirm payment received");
step4 = new TradeWizardItem(SellerStep4aView.class, "Wait for payout unlock"); step4 = new TradeWizardItem(SellerStep4View.class, "Wait for payout unlock");
step5 = new TradeWizardItem(SellerStep5View.class, "Completed"); step5 = new TradeWizardItem(SellerStep5View.class, "Completed");
if (model.getLockTime() > 0) { if (model.getLockTime() > 0) {
@ -74,7 +73,6 @@ public class SellerSubView extends TradeSubView {
addWizardsToGridPane(step2); addWizardsToGridPane(step2);
addWizardsToGridPane(step3); addWizardsToGridPane(step3);
addWizardsToGridPane(step5); addWizardsToGridPane(step5);
GridPane.setRowSpan(tradeProcessTitledGroupBg, 4);
} }
} }
@ -115,14 +113,13 @@ public class SellerSubView extends TradeSubView {
case WAIT_FOR_PAYOUT_TX: case WAIT_FOR_PAYOUT_TX:
step1.setCompleted(); step1.setCompleted();
step2.setCompleted(); step2.setCompleted();
step3.setCompleted(); showItem(step3);
showItem(step4);
// We don't use a wizard for that step as it only gets displayed in case the other peer is offline // We don't use a wizard for that step as it only gets displayed in case the other peer is offline
tradeStepView = new SellerStep4bView(model); tradeStepView = new SellerStep3bView(model);
contentPane.getChildren().setAll(tradeStepView); contentPane.getChildren().setAll(tradeStepView);
break; break;
case WAIT_FOR_UNLOCK_PAYOUT: case WAIT_FOR_BROADCAST_AFTER_UNLOCK:
step1.setCompleted(); step1.setCompleted();
step2.setCompleted(); step2.setCompleted();
step3.setCompleted(); step3.setCompleted();

View file

@ -20,13 +20,13 @@ package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel; import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView; import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
public class SellerStep4bView extends TradeStepView { public class SellerStep3bView extends TradeStepView {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation // Constructor, Initialisation
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public SellerStep4bView(PendingTradesViewModel model) { public SellerStep3bView(PendingTradesViewModel model) {
super(model); super(model);
} }

View file

@ -20,13 +20,13 @@ package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel; import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer.BuyerStep4View; import io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer.BuyerStep4View;
public class SellerStep4aView extends BuyerStep4View { public class SellerStep4View extends BuyerStep4View {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation // Constructor, Initialisation
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public SellerStep4aView(PendingTradesViewModel model) { public SellerStep4View(PendingTradesViewModel model) {
super(model); super(model);
} }
} }