mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-23 15:10:41 -04:00
Add locktime to payout tx
This commit is contained in:
parent
f24ebb9038
commit
08dde43ffc
33 changed files with 620 additions and 198 deletions
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package io.bitsquare.app.bootstrap;
|
package io.bitsquare.app.bootstrap;
|
||||||
|
|
||||||
|
import io.bitsquare.p2p.BootstrapNodes;
|
||||||
import io.bitsquare.p2p.Node;
|
import io.bitsquare.p2p.Node;
|
||||||
|
|
||||||
import net.tomp2p.connection.ChannelClientConfiguration;
|
import net.tomp2p.connection.ChannelClientConfiguration;
|
||||||
|
@ -52,7 +53,7 @@ public class BootstrapNode {
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
String name = env.getRequiredProperty(Node.NAME_KEY);
|
String name = env.getRequiredProperty(Node.NAME_KEY);
|
||||||
int port = env.getProperty(Node.PORT_KEY, Integer.class, Node.DEFAULT_PORT);
|
int port = env.getProperty(Node.PORT_KEY, Integer.class, BootstrapNodes.DEFAULT_PORT);
|
||||||
try {
|
try {
|
||||||
Number160 peerId = Number160.createHash(name);
|
Number160 peerId = Number160.createHash(name);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ package io.bitsquare.app.bootstrap;
|
||||||
|
|
||||||
import io.bitsquare.app.BitsquareEnvironment;
|
import io.bitsquare.app.BitsquareEnvironment;
|
||||||
import io.bitsquare.app.BitsquareExecutable;
|
import io.bitsquare.app.BitsquareExecutable;
|
||||||
|
import io.bitsquare.p2p.BootstrapNodes;
|
||||||
import io.bitsquare.p2p.Node;
|
import io.bitsquare.p2p.Node;
|
||||||
|
|
||||||
import joptsimple.OptionParser;
|
import joptsimple.OptionParser;
|
||||||
|
@ -34,7 +35,7 @@ public class BootstrapNodeMain extends BitsquareExecutable {
|
||||||
parser.accepts(Node.NAME_KEY, description("Name of this node", null))
|
parser.accepts(Node.NAME_KEY, description("Name of this node", null))
|
||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.isRequired();
|
.isRequired();
|
||||||
parser.accepts(Node.PORT_KEY, description("Port to listen on", Node.DEFAULT_PORT))
|
parser.accepts(Node.PORT_KEY, description("Port to listen on", BootstrapNodes.DEFAULT_PORT))
|
||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.ofType(int.class);
|
.ofType(int.class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InvalidObjectException;
|
||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.scene.*;
|
import javafx.scene.*;
|
||||||
|
@ -69,7 +70,7 @@ public class BitsquareApp extends Application {
|
||||||
this.primaryStage = primaryStage;
|
this.primaryStage = primaryStage;
|
||||||
|
|
||||||
log.trace("BitsquareApp.start");
|
log.trace("BitsquareApp.start");
|
||||||
|
try {
|
||||||
bitsquareAppModule = new BitsquareAppModule(env, primaryStage);
|
bitsquareAppModule = new BitsquareAppModule(env, primaryStage);
|
||||||
injector = Guice.createInjector(bitsquareAppModule);
|
injector = Guice.createInjector(bitsquareAppModule);
|
||||||
injector.getInstance(InjectorViewFactory.class).setInjector(injector);
|
injector.getInstance(InjectorViewFactory.class).setInjector(injector);
|
||||||
|
@ -136,6 +137,13 @@ public class BitsquareApp extends Application {
|
||||||
|
|
||||||
//TODO just temp.
|
//TODO just temp.
|
||||||
//showDebugWindow();
|
//showDebugWindow();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
if (t instanceof InvalidObjectException) {
|
||||||
|
Popups.openErrorPopup("There is a problem with different version of persisted objects. " +
|
||||||
|
"Please delete the db directory inside the app directory.");
|
||||||
|
}
|
||||||
|
log.error(t.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDebugWindow() {
|
private void showDebugWindow() {
|
||||||
|
|
|
@ -23,11 +23,13 @@ import io.bitsquare.btc.exceptions.WalletException;
|
||||||
|
|
||||||
import org.bitcoinj.core.Address;
|
import org.bitcoinj.core.Address;
|
||||||
import org.bitcoinj.core.AddressFormatException;
|
import org.bitcoinj.core.AddressFormatException;
|
||||||
|
import org.bitcoinj.core.BlockChainListener;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
import org.bitcoinj.core.ECKey;
|
import org.bitcoinj.core.ECKey;
|
||||||
import org.bitcoinj.core.InsufficientMoneyException;
|
import org.bitcoinj.core.InsufficientMoneyException;
|
||||||
import org.bitcoinj.core.NetworkParameters;
|
import org.bitcoinj.core.NetworkParameters;
|
||||||
import org.bitcoinj.core.Sha256Hash;
|
import org.bitcoinj.core.Sha256Hash;
|
||||||
|
import org.bitcoinj.core.StoredBlock;
|
||||||
import org.bitcoinj.core.Transaction;
|
import org.bitcoinj.core.Transaction;
|
||||||
import org.bitcoinj.core.TransactionInput;
|
import org.bitcoinj.core.TransactionInput;
|
||||||
import org.bitcoinj.core.TransactionOutPoint;
|
import org.bitcoinj.core.TransactionOutPoint;
|
||||||
|
@ -118,11 +120,6 @@ public class TradeWalletService {
|
||||||
return createOfferFeeTx;
|
return createOfferFeeTx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcastCreateOfferFeeTx(Transaction createOfferFeeTx, FutureCallback<Transaction> callback) {
|
|
||||||
ListenableFuture<Transaction> future = walletAppKit.peerGroup().broadcastTransaction(createOfferFeeTx).future();
|
|
||||||
Futures.addCallback(future, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Transaction createTakeOfferFeeTx(AddressEntry sellerAddressEntry) throws InsufficientMoneyException {
|
public Transaction createTakeOfferFeeTx(AddressEntry sellerAddressEntry) throws InsufficientMoneyException {
|
||||||
Transaction takeOfferFeeTx = new Transaction(params);
|
Transaction takeOfferFeeTx = new Transaction(params);
|
||||||
Coin fee = FeePolicy.TAKE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
|
Coin fee = FeePolicy.TAKE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
|
||||||
|
@ -139,8 +136,8 @@ public class TradeWalletService {
|
||||||
return takeOfferFeeTx;
|
return takeOfferFeeTx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcastTakeOfferFeeTx(Transaction takeOfferFeeTx, FutureCallback<Transaction> callback) {
|
public void broadcastTx(Transaction tx, FutureCallback<Transaction> callback) {
|
||||||
ListenableFuture<Transaction> future = walletAppKit.peerGroup().broadcastTransaction(takeOfferFeeTx).future();
|
ListenableFuture<Transaction> future = walletAppKit.peerGroup().broadcastTransaction(tx).future();
|
||||||
Futures.addCallback(future, callback);
|
Futures.addCallback(future, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,6 +416,7 @@ public class TradeWalletService {
|
||||||
Coin sellerPayoutAmount,
|
Coin sellerPayoutAmount,
|
||||||
AddressEntry buyerAddressEntry,
|
AddressEntry buyerAddressEntry,
|
||||||
String sellerPayoutAddressString,
|
String sellerPayoutAddressString,
|
||||||
|
long lockTimeDelta,
|
||||||
byte[] buyerPubKey,
|
byte[] buyerPubKey,
|
||||||
byte[] sellerPubKey,
|
byte[] sellerPubKey,
|
||||||
byte[] arbitratorPubKey)
|
byte[] arbitratorPubKey)
|
||||||
|
@ -438,6 +436,8 @@ public class TradeWalletService {
|
||||||
sellerPayoutAmount,
|
sellerPayoutAmount,
|
||||||
buyerAddressEntry.getAddressString(),
|
buyerAddressEntry.getAddressString(),
|
||||||
sellerPayoutAddressString);
|
sellerPayoutAddressString);
|
||||||
|
preparedPayoutTx.setLockTime(wallet.getLastBlockSeenHeight() + lockTimeDelta);
|
||||||
|
preparedPayoutTx.getInputs().stream().forEach(i -> i.setSequenceNumber(0));
|
||||||
// MS redeemScript
|
// MS redeemScript
|
||||||
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
|
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
|
||||||
Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
|
Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
|
||||||
|
@ -454,16 +454,16 @@ public class TradeWalletService {
|
||||||
return buyerSignature.encodeToDER();
|
return buyerSignature.encodeToDER();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void signAndPublishPayoutTx(Transaction depositTx,
|
public Transaction signAndFinalizePayoutTx(Transaction depositTx,
|
||||||
byte[] buyerSignature,
|
byte[] buyerSignature,
|
||||||
Coin buyerPayoutAmount,
|
Coin buyerPayoutAmount,
|
||||||
Coin sellerPayoutAmount,
|
Coin sellerPayoutAmount,
|
||||||
String buyerAddressString,
|
String buyerAddressString,
|
||||||
AddressEntry sellerAddressEntry,
|
AddressEntry sellerAddressEntry,
|
||||||
|
long lockTimeDelta,
|
||||||
byte[] buyerPubKey,
|
byte[] buyerPubKey,
|
||||||
byte[] sellerPubKey,
|
byte[] sellerPubKey,
|
||||||
byte[] arbitratorPubKey,
|
byte[] arbitratorPubKey)
|
||||||
FutureCallback<Transaction> callback)
|
|
||||||
throws AddressFormatException, TransactionVerificationException, WalletException, SigningException {
|
throws AddressFormatException, TransactionVerificationException, WalletException, SigningException {
|
||||||
log.trace("signAndPublishPayoutTx called");
|
log.trace("signAndPublishPayoutTx called");
|
||||||
log.trace("depositTx " + depositTx.toString());
|
log.trace("depositTx " + depositTx.toString());
|
||||||
|
@ -482,6 +482,8 @@ public class TradeWalletService {
|
||||||
sellerPayoutAmount,
|
sellerPayoutAmount,
|
||||||
buyerAddressString,
|
buyerAddressString,
|
||||||
sellerAddressEntry.getAddressString());
|
sellerAddressEntry.getAddressString());
|
||||||
|
payoutTx.setLockTime(wallet.getLastBlockSeenHeight() + lockTimeDelta);
|
||||||
|
payoutTx.getInputs().stream().forEach(i -> i.setSequenceNumber(0));
|
||||||
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
|
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
|
||||||
Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
|
Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
|
||||||
ECKey.ECDSASignature sellerSignature = sellerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised();
|
ECKey.ECDSASignature sellerSignature = sellerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised();
|
||||||
|
@ -508,8 +510,25 @@ public class TradeWalletService {
|
||||||
|
|
||||||
printTxWithInputs("payoutTx", payoutTx);
|
printTxWithInputs("payoutTx", payoutTx);
|
||||||
|
|
||||||
ListenableFuture<Transaction> broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(payoutTx).future();
|
// As we use lockTime the tx will not be relayed as it is not considered standard.
|
||||||
Futures.addCallback(broadcastComplete, callback);
|
// We need to broadcast on our own when we reahced the block height. Both peers will do the broadcast.
|
||||||
|
return payoutTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<StoredBlock> getBlockHeightFuture(Transaction transaction) {
|
||||||
|
return walletAppKit.chain().getHeightFuture((int) transaction.getLockTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBestChainHeight() {
|
||||||
|
return walletAppKit.chain().getBestChainHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
|
walletAppKit.chain().addListener(blockChainListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
|
walletAppKit.chain().removeListener(blockChainListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -32,21 +32,27 @@ public class FiatAccount implements Serializable {
|
||||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final long HOUR_IN_BLOCKS = 6;
|
||||||
|
public static final long DAY_IN_BLOCKS = HOUR_IN_BLOCKS * 24;
|
||||||
|
public static final long WEEK_IN_BLOCKS = DAY_IN_BLOCKS * 7;
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
IRC("", ""),
|
IRC("", "", 1),
|
||||||
SEPA("IBAN", "BIC"),
|
SEPA("IBAN", "BIC", WEEK_IN_BLOCKS),
|
||||||
WIRE("primary ID", "secondary ID"),
|
WIRE("primary ID", "secondary ID", WEEK_IN_BLOCKS),
|
||||||
INTERNATIONAL("primary ID", "secondary ID"),
|
INTERNATIONAL("primary ID", "secondary ID", 2 * WEEK_IN_BLOCKS),
|
||||||
OK_PAY("primary ID", "secondary ID"),
|
OK_PAY("primary ID", "secondary ID", HOUR_IN_BLOCKS),
|
||||||
NET_TELLER("primary ID", "secondary ID"),
|
NET_TELLER("primary ID", "secondary ID", HOUR_IN_BLOCKS),
|
||||||
PERFECT_MONEY("primary ID", "secondary ID");
|
PERFECT_MONEY("primary ID", "secondary ID", HOUR_IN_BLOCKS);
|
||||||
|
|
||||||
public final String primaryId;
|
public final String primaryId;
|
||||||
public final String secondaryId;
|
public final String secondaryId;
|
||||||
|
public final long lockTimeDelta;
|
||||||
|
|
||||||
Type(String primaryId, String secondaryId) {
|
Type(String primaryId, String secondaryId, long lockTimeDelta) {
|
||||||
this.primaryId = primaryId;
|
this.primaryId = primaryId;
|
||||||
this.secondaryId = secondaryId;
|
this.secondaryId = secondaryId;
|
||||||
|
this.lockTimeDelta = lockTimeDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<Type> getAllBankAccountTypes() {
|
public static ArrayList<Type> getAllBankAccountTypes() {
|
||||||
|
|
|
@ -32,7 +32,7 @@ import io.bitsquare.trade.protocol.trade.BuyerAsOffererProtocol;
|
||||||
import io.bitsquare.trade.protocol.trade.SellerAsTakerProtocol;
|
import io.bitsquare.trade.protocol.trade.SellerAsTakerProtocol;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestDepositTxInputsMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestDepositTxInputsMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
||||||
|
@ -46,9 +46,9 @@ import io.bitsquare.trade.protocol.trade.tasks.seller.CreateAndSignDepositTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestDepositTxInputsMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestDepositTxInputsMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndPublishPayoutTx;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndFinalizePayoutTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOfferFeePayment;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOfferFeePayment;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOffererAccount;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOffererAccount;
|
||||||
|
@ -111,7 +111,7 @@ public class DebugView extends InitializableView {
|
||||||
VerifyTakeOfferFeePayment.class,
|
VerifyTakeOfferFeePayment.class,
|
||||||
SendFiatTransferStartedMessage.class,
|
SendFiatTransferStartedMessage.class,
|
||||||
|
|
||||||
ProcessPayoutTxPublishedMessage.class,
|
ProcessPayoutTxFinalizedMessage.class,
|
||||||
Boolean.class, /* used as seperator*/
|
Boolean.class, /* used as seperator*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,9 +129,9 @@ public class DebugView extends InitializableView {
|
||||||
|
|
||||||
ProcessFiatTransferStartedMessage.class,
|
ProcessFiatTransferStartedMessage.class,
|
||||||
|
|
||||||
SignAndPublishPayoutTx.class,
|
SignAndFinalizePayoutTx.class,
|
||||||
VerifyOfferFeePayment.class,
|
VerifyOfferFeePayment.class,
|
||||||
SendPayoutTxPublishedMessage.class
|
SendPayoutTxFinalizedMessage.class
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -255,7 +255,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||||
"Please try later again." + msg);
|
"Please try later again." + msg);
|
||||||
takeOfferRequested = false;
|
takeOfferRequested = false;
|
||||||
break;
|
break;
|
||||||
case PAYOUT_PUBLISHED:
|
case PAYOUT_FINALIZED:
|
||||||
break;
|
break;
|
||||||
case EXCEPTION:
|
case EXCEPTION:
|
||||||
errorMessage.set(msg);
|
errorMessage.set(msg);
|
||||||
|
@ -292,7 +292,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||||
"Please try later again." + msg);
|
"Please try later again." + msg);
|
||||||
takeOfferRequested = false;
|
takeOfferRequested = false;
|
||||||
break;
|
break;
|
||||||
case PAYOUT_PUBLISHED:
|
case PAYOUT_FINALIZED:
|
||||||
break;
|
break;
|
||||||
case EXCEPTION:
|
case EXCEPTION:
|
||||||
errorMessage.set(msg);
|
errorMessage.set(msg);
|
||||||
|
|
|
@ -22,6 +22,7 @@ import io.bitsquare.gui.main.portfolio.pendingtrades.steps.CompletedView;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.StartFiatView;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.StartFiatView;
|
||||||
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.WaitFiatReceivedView;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitFiatReceivedView;
|
||||||
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitPayoutLockTimeView;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitTxInBlockchainView;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitTxInBlockchainView;
|
||||||
import io.bitsquare.locale.BSResources;
|
import io.bitsquare.locale.BSResources;
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ public class BuyerSubView extends TradeSubView {
|
||||||
private TradeWizardItem waitTxInBlockchain;
|
private TradeWizardItem waitTxInBlockchain;
|
||||||
private TradeWizardItem startFiat;
|
private TradeWizardItem startFiat;
|
||||||
private TradeWizardItem waitFiatReceived;
|
private TradeWizardItem waitFiatReceived;
|
||||||
|
private TradeWizardItem payoutUnlock;
|
||||||
private TradeWizardItem completed;
|
private TradeWizardItem completed;
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,9 +62,10 @@ public class BuyerSubView extends TradeSubView {
|
||||||
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
|
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
|
||||||
startFiat = new TradeWizardItem(StartFiatView.class, "Start payment");
|
startFiat = new TradeWizardItem(StartFiatView.class, "Start payment");
|
||||||
waitFiatReceived = new TradeWizardItem(WaitFiatReceivedView.class, "Wait until payment has arrived");
|
waitFiatReceived = new TradeWizardItem(WaitFiatReceivedView.class, "Wait until payment has arrived");
|
||||||
|
payoutUnlock = new TradeWizardItem(WaitPayoutLockTimeView.class, "Wait for payout unlock");
|
||||||
completed = new TradeWizardItem(CompletedView.class, "Completed");
|
completed = new TradeWizardItem(CompletedView.class, "Completed");
|
||||||
|
|
||||||
leftVBox.getChildren().addAll(waitTxInBlockchain, startFiat, waitFiatReceived, completed);
|
leftVBox.getChildren().addAll(waitTxInBlockchain, startFiat, waitFiatReceived, payoutUnlock, completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,10 +113,20 @@ public class BuyerSubView extends TradeSubView {
|
||||||
"the Bitcoin sellers payment account, the payout transaction will be published.",
|
"the Bitcoin sellers payment account, the payout transaction will be published.",
|
||||||
model.getCurrencyCode()));
|
model.getCurrencyCode()));
|
||||||
break;
|
break;
|
||||||
|
case BUYER_PAYOUT_FINALIZED:
|
||||||
|
waitTxInBlockchain.done();
|
||||||
|
startFiat.done();
|
||||||
|
waitFiatReceived.done();
|
||||||
|
showItem(payoutUnlock);
|
||||||
|
|
||||||
|
((WaitPayoutLockTimeView) tradeStepDetailsView).setInfoLabelText("The payout transaction is signed and finalized by both parties." +
|
||||||
|
"\nFor reducing bank chargeback risks you need to wait until the payout gets unlocked to transfer your Bitcoin.");
|
||||||
|
break;
|
||||||
case BUYER_COMPLETED:
|
case BUYER_COMPLETED:
|
||||||
waitTxInBlockchain.done();
|
waitTxInBlockchain.done();
|
||||||
startFiat.done();
|
startFiat.done();
|
||||||
waitFiatReceived.done();
|
waitFiatReceived.done();
|
||||||
|
payoutUnlock.done();
|
||||||
showItem(completed);
|
showItem(completed);
|
||||||
|
|
||||||
CompletedView completedView = (CompletedView) tradeStepDetailsView;
|
CompletedView completedView = (CompletedView) tradeStepDetailsView;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||||
|
|
||||||
import io.bitsquare.btc.FeePolicy;
|
import io.bitsquare.btc.FeePolicy;
|
||||||
|
import io.bitsquare.btc.TradeWalletService;
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.btc.WalletService;
|
||||||
import io.bitsquare.common.viewfx.model.Activatable;
|
import io.bitsquare.common.viewfx.model.Activatable;
|
||||||
import io.bitsquare.common.viewfx.model.DataModel;
|
import io.bitsquare.common.viewfx.model.DataModel;
|
||||||
|
@ -35,6 +36,7 @@ import io.bitsquare.trade.TradeManager;
|
||||||
import io.bitsquare.trade.states.TradeState;
|
import io.bitsquare.trade.states.TradeState;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.BlockChainListener;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
@ -60,6 +62,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
||||||
|
|
||||||
private final TradeManager tradeManager;
|
private final TradeManager tradeManager;
|
||||||
private final WalletService walletService;
|
private final WalletService walletService;
|
||||||
|
private TradeWalletService tradeWalletService;
|
||||||
private final User user;
|
private final User user;
|
||||||
private Navigation navigation;
|
private Navigation navigation;
|
||||||
|
|
||||||
|
@ -80,9 +83,11 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public PendingTradesDataModel(TradeManager tradeManager, WalletService walletService, User user, Navigation navigation) {
|
public PendingTradesDataModel(TradeManager tradeManager, WalletService walletService, TradeWalletService tradeWalletService, User user, Navigation
|
||||||
|
navigation) {
|
||||||
this.tradeManager = tradeManager;
|
this.tradeManager = tradeManager;
|
||||||
this.walletService = walletService;
|
this.walletService = walletService;
|
||||||
|
this.tradeWalletService = tradeWalletService;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
|
|
||||||
|
@ -281,5 +286,24 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
||||||
return txId;
|
return txId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getPayoutTxId() {
|
||||||
|
return trade.getPayoutTx().getHashAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
|
tradeWalletService.addBlockChainListener(blockChainListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
|
tradeWalletService.removeBlockChainListener(blockChainListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLockTime() {
|
||||||
|
return trade.getPayoutTx().getLockTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBestChainHeight() {
|
||||||
|
return tradeWalletService.getBestChainHeight();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.states.OffererTradeState;
|
import io.bitsquare.trade.states.OffererTradeState;
|
||||||
import io.bitsquare.trade.states.TakerTradeState;
|
import io.bitsquare.trade.states.TakerTradeState;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.BlockChainListener;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
import org.bitcoinj.utils.Fiat;
|
import org.bitcoinj.utils.Fiat;
|
||||||
|
|
||||||
|
@ -58,11 +59,13 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
SELLER_WAIT_PAYMENT_STARTED,
|
SELLER_WAIT_PAYMENT_STARTED,
|
||||||
SELLER_CONFIRM_RECEIVE_PAYMENT,
|
SELLER_CONFIRM_RECEIVE_PAYMENT,
|
||||||
SELLER_SEND_PUBLISHED_MSG,
|
SELLER_SEND_PUBLISHED_MSG,
|
||||||
|
SELLER_PAYOUT_FINALIZED,
|
||||||
SELLER_COMPLETED,
|
SELLER_COMPLETED,
|
||||||
|
|
||||||
BUYER_WAIT_TX_CONF,
|
BUYER_WAIT_TX_CONF,
|
||||||
BUYER_START_PAYMENT,
|
BUYER_START_PAYMENT,
|
||||||
BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED,
|
BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED,
|
||||||
|
BUYER_PAYOUT_FINALIZED,
|
||||||
BUYER_COMPLETED,
|
BUYER_COMPLETED,
|
||||||
|
|
||||||
MESSAGE_SENDING_FAILED,
|
MESSAGE_SENDING_FAILED,
|
||||||
|
@ -135,6 +138,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
return txId;
|
return txId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPayoutTxId() {
|
||||||
|
return dataModel.getPayoutTxId();
|
||||||
|
}
|
||||||
|
|
||||||
public ReadOnlyBooleanProperty getWithdrawalButtonDisable() {
|
public ReadOnlyBooleanProperty getWithdrawalButtonDisable() {
|
||||||
return withdrawalButtonDisable;
|
return withdrawalButtonDisable;
|
||||||
}
|
}
|
||||||
|
@ -224,6 +231,26 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
return formatter.formatDateTime(value);
|
return formatter.formatDateTime(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
|
dataModel.addBlockChainListener(blockChainListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
|
dataModel.removeBlockChainListener(blockChainListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLockTime() {
|
||||||
|
return dataModel.getLockTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBestChainHeight() {
|
||||||
|
return dataModel.getBestChainHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUnlockDate(long missingBlocks) {
|
||||||
|
return formatter.getUnlockDate(missingBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
// payment
|
// payment
|
||||||
public String getPaymentMethod() {
|
public String getPaymentMethod() {
|
||||||
assert dataModel.getContract() != null;
|
assert dataModel.getContract() != null;
|
||||||
|
@ -304,12 +331,18 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
|
|
||||||
case FIAT_PAYMENT_RECEIVED:
|
case FIAT_PAYMENT_RECEIVED:
|
||||||
break;
|
break;
|
||||||
case PAYOUT_PUBLISHED:
|
case PAYOUT_FINALIZED:
|
||||||
viewState.set(ViewState.SELLER_SEND_PUBLISHED_MSG);
|
viewState.set(ViewState.SELLER_SEND_PUBLISHED_MSG);
|
||||||
break;
|
break;
|
||||||
case PAYOUT_PUBLISHED_MSG_SENT:
|
case PAYOUT_FINALIZED_MSG_SENT:
|
||||||
|
viewState.set(ViewState.SELLER_PAYOUT_FINALIZED);
|
||||||
|
break;
|
||||||
|
case PAYOUT_BROAD_CASTED:
|
||||||
viewState.set(ViewState.SELLER_COMPLETED);
|
viewState.set(ViewState.SELLER_COMPLETED);
|
||||||
break;
|
break;
|
||||||
|
case PAYOUT_BROAD_CASTED_FAILED:
|
||||||
|
viewState.set(ViewState.EXCEPTION);
|
||||||
|
break;
|
||||||
|
|
||||||
case MESSAGE_SENDING_FAILED:
|
case MESSAGE_SENDING_FAILED:
|
||||||
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
|
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
|
||||||
|
@ -345,12 +378,18 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
|
|
||||||
case FIAT_PAYMENT_RECEIVED:
|
case FIAT_PAYMENT_RECEIVED:
|
||||||
break;
|
break;
|
||||||
case PAYOUT_PUBLISHED:
|
case PAYOUT_FINALIZED:
|
||||||
viewState.set(ViewState.SELLER_SEND_PUBLISHED_MSG);
|
viewState.set(ViewState.SELLER_SEND_PUBLISHED_MSG);
|
||||||
break;
|
break;
|
||||||
case PAYOUT_PUBLISHED_MSG_SENT:
|
case PAYOUT_FINALIZED_MSG_SENT:
|
||||||
|
viewState.set(ViewState.SELLER_PAYOUT_FINALIZED);
|
||||||
|
break;
|
||||||
|
case PAYOUT_BROAD_CASTED:
|
||||||
viewState.set(ViewState.SELLER_COMPLETED);
|
viewState.set(ViewState.SELLER_COMPLETED);
|
||||||
break;
|
break;
|
||||||
|
case PAYOUT_BROAD_CASTED_FAILED:
|
||||||
|
viewState.set(ViewState.EXCEPTION);
|
||||||
|
break;
|
||||||
|
|
||||||
case MESSAGE_SENDING_FAILED:
|
case MESSAGE_SENDING_FAILED:
|
||||||
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
|
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
|
||||||
|
@ -393,9 +432,16 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIAT_PAYMENT_RECEIVED:
|
case FIAT_PAYMENT_RECEIVED:
|
||||||
case PAYOUT_PUBLISHED:
|
case PAYOUT_FINALIZED:
|
||||||
|
case PAYOUT_FINALIZED_MSG_SENT:
|
||||||
|
viewState.set(ViewState.BUYER_PAYOUT_FINALIZED);
|
||||||
|
break;
|
||||||
|
case PAYOUT_BROAD_CASTED:
|
||||||
viewState.set(ViewState.BUYER_COMPLETED);
|
viewState.set(ViewState.BUYER_COMPLETED);
|
||||||
break;
|
break;
|
||||||
|
case PAYOUT_BROAD_CASTED_FAILED:
|
||||||
|
viewState.set(ViewState.EXCEPTION);
|
||||||
|
break;
|
||||||
|
|
||||||
case MESSAGE_SENDING_FAILED:
|
case MESSAGE_SENDING_FAILED:
|
||||||
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
|
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
|
||||||
|
@ -432,9 +478,16 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIAT_PAYMENT_RECEIVED:
|
case FIAT_PAYMENT_RECEIVED:
|
||||||
case PAYOUT_PUBLISHED:
|
case PAYOUT_FINALIZED:
|
||||||
|
case PAYOUT_FINALIZED_MSG_SENT:
|
||||||
|
viewState.set(ViewState.BUYER_PAYOUT_FINALIZED);
|
||||||
|
break;
|
||||||
|
case PAYOUT_BROAD_CASTED:
|
||||||
viewState.set(ViewState.BUYER_COMPLETED);
|
viewState.set(ViewState.BUYER_COMPLETED);
|
||||||
break;
|
break;
|
||||||
|
case PAYOUT_BROAD_CASTED_FAILED:
|
||||||
|
viewState.set(ViewState.EXCEPTION);
|
||||||
|
break;
|
||||||
|
|
||||||
case MESSAGE_SENDING_FAILED:
|
case MESSAGE_SENDING_FAILED:
|
||||||
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
|
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import io.bitsquare.gui.components.Popups;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.CompletedView;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.CompletedView;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.ConfirmFiatReceivedView;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.ConfirmFiatReceivedView;
|
||||||
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.WaitPayoutLockTimeView;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitTxInBlockchainView;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitTxInBlockchainView;
|
||||||
import io.bitsquare.locale.BSResources;
|
import io.bitsquare.locale.BSResources;
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ public class SellerSubView extends TradeSubView {
|
||||||
private TradeWizardItem waitTxInBlockchain;
|
private TradeWizardItem waitTxInBlockchain;
|
||||||
private TradeWizardItem waitFiatStarted;
|
private TradeWizardItem waitFiatStarted;
|
||||||
private TradeWizardItem confirmFiatReceived;
|
private TradeWizardItem confirmFiatReceived;
|
||||||
|
private TradeWizardItem payoutUnlock;
|
||||||
private TradeWizardItem completed;
|
private TradeWizardItem completed;
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,9 +61,10 @@ public class SellerSubView extends TradeSubView {
|
||||||
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
|
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
|
||||||
waitFiatStarted = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for payment started");
|
waitFiatStarted = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for payment started");
|
||||||
confirmFiatReceived = new TradeWizardItem(ConfirmFiatReceivedView.class, "Confirm payment received");
|
confirmFiatReceived = new TradeWizardItem(ConfirmFiatReceivedView.class, "Confirm payment received");
|
||||||
|
payoutUnlock = new TradeWizardItem(WaitPayoutLockTimeView.class, "Wait for payout unlock");
|
||||||
completed = new TradeWizardItem(CompletedView.class, "Completed");
|
completed = new TradeWizardItem(CompletedView.class, "Completed");
|
||||||
|
|
||||||
leftVBox.getChildren().addAll(waitTxInBlockchain, waitFiatStarted, confirmFiatReceived, completed);
|
leftVBox.getChildren().addAll(waitTxInBlockchain, waitFiatStarted, confirmFiatReceived, payoutUnlock, completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,6 +79,7 @@ public class SellerSubView extends TradeSubView {
|
||||||
waitTxInBlockchain.inactive();
|
waitTxInBlockchain.inactive();
|
||||||
waitFiatStarted.inactive();
|
waitFiatStarted.inactive();
|
||||||
confirmFiatReceived.inactive();
|
confirmFiatReceived.inactive();
|
||||||
|
payoutUnlock.inactive();
|
||||||
completed.inactive();
|
completed.inactive();
|
||||||
|
|
||||||
if (tradeStepDetailsView != null)
|
if (tradeStepDetailsView != null)
|
||||||
|
@ -129,14 +133,23 @@ public class SellerSubView extends TradeSubView {
|
||||||
waitTxInBlockchain.done();
|
waitTxInBlockchain.done();
|
||||||
waitFiatStarted.done();
|
waitFiatStarted.done();
|
||||||
showItem(confirmFiatReceived);
|
showItem(confirmFiatReceived);
|
||||||
}
|
|
||||||
|
|
||||||
((ConfirmFiatReceivedView) tradeStepDetailsView).setStatusText("Sending message to trading peer transaction...");
|
((ConfirmFiatReceivedView) tradeStepDetailsView).setStatusText("Sending message to trading peer transaction...");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SELLER_PAYOUT_FINALIZED:
|
||||||
|
waitTxInBlockchain.done();
|
||||||
|
waitFiatStarted.done();
|
||||||
|
confirmFiatReceived.done();
|
||||||
|
showItem(payoutUnlock);
|
||||||
|
|
||||||
|
((WaitPayoutLockTimeView) tradeStepDetailsView).setInfoLabelText("The payout transaction is signed and finalized by both parties." +
|
||||||
|
"\nFor reducing bank chargeback risks you need to wait until the payout gets unlocked to transfer your Bitcoin.");
|
||||||
break;
|
break;
|
||||||
case SELLER_COMPLETED:
|
case SELLER_COMPLETED:
|
||||||
waitTxInBlockchain.done();
|
waitTxInBlockchain.done();
|
||||||
waitFiatStarted.done();
|
waitFiatStarted.done();
|
||||||
confirmFiatReceived.done();
|
confirmFiatReceived.done();
|
||||||
|
payoutUnlock.done();
|
||||||
showItem(completed);
|
showItem(completed);
|
||||||
|
|
||||||
CompletedView completedView = (CompletedView) tradeStepDetailsView;
|
CompletedView completedView = (CompletedView) tradeStepDetailsView;
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Bitsquare.
|
||||||
|
*
|
||||||
|
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||||
|
|
||||||
|
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||||
|
import io.bitsquare.gui.util.Layout;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.AbstractBlockChain;
|
||||||
|
import org.bitcoinj.core.BlockChainListener;
|
||||||
|
import org.bitcoinj.core.ScriptException;
|
||||||
|
import org.bitcoinj.core.Sha256Hash;
|
||||||
|
import org.bitcoinj.core.StoredBlock;
|
||||||
|
import org.bitcoinj.core.Transaction;
|
||||||
|
import org.bitcoinj.core.VerificationException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static io.bitsquare.gui.util.ComponentBuilder.*;
|
||||||
|
|
||||||
|
public class WaitPayoutLockTimeView extends TradeStepDetailsView {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(WaitPayoutLockTimeView.class);
|
||||||
|
|
||||||
|
private final BlockChainListener blockChainListener;
|
||||||
|
|
||||||
|
private TextField blockTextField;
|
||||||
|
private Label infoLabel;
|
||||||
|
private TextField timeTextField;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor, Initialisation
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public WaitPayoutLockTimeView(PendingTradesViewModel model) {
|
||||||
|
super(model);
|
||||||
|
|
||||||
|
blockChainListener = new BlockChainListener() {
|
||||||
|
@Override
|
||||||
|
public void notifyNewBestBlock(StoredBlock block) throws VerificationException {
|
||||||
|
setLockTime(block.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks) throws VerificationException {
|
||||||
|
setLockTime(model.getBestChainHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTransactionRelevant(Transaction tx) throws ScriptException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveFromBlock(Transaction tx, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset) throws
|
||||||
|
VerificationException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset)
|
||||||
|
throws VerificationException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate() {
|
||||||
|
super.activate();
|
||||||
|
|
||||||
|
model.addBlockChainListener(blockChainListener);
|
||||||
|
setLockTime(model.getBestChainHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deactivate() {
|
||||||
|
super.deactivate();
|
||||||
|
|
||||||
|
model.removeBlockChainListener(blockChainListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Setters
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void setInfoLabelText(String text) {
|
||||||
|
if (infoLabel != null)
|
||||||
|
infoLabel.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLockTime(int bestBlocKHeight) {
|
||||||
|
long missingBlocks = model.getLockTime() - (long) bestBlocKHeight;
|
||||||
|
blockTextField.setText(String.valueOf(missingBlocks));
|
||||||
|
timeTextField.setText(model.getUnlockDate(missingBlocks));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Build view
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void buildGridEntries() {
|
||||||
|
getAndAddTitledGroupBg(gridPane, gridRow, 2, "Payout transaction lock time");
|
||||||
|
blockTextField = getAndAddLabelTextFieldPair(gridPane, gridRow++, "Block(s) to wait until unlock:", Layout.FIRST_ROW_DISTANCE).textField;
|
||||||
|
timeTextField = getAndAddLabelTextFieldPair(gridPane, gridRow++, "Approx. date when payout gets unlocked:").textField;
|
||||||
|
|
||||||
|
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
||||||
|
infoLabel = getAndAddInfoLabel(gridPane, gridRow++, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -356,4 +356,11 @@ public class BSFormatter {
|
||||||
Double.parseDouble(input);
|
Double.parseDouble(input);
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUnlockDate(long missingBlocks) {
|
||||||
|
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
|
||||||
|
DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, locale);
|
||||||
|
Date unlockDate = new Date(new Date().getTime() + missingBlocks * 10 * 60 * 1000);
|
||||||
|
return dateFormatter.format(unlockDate) + " " + timeFormatter.format(unlockDate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||||
public class OfferBook {
|
public class OfferBook {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(OfferBook.class);
|
private static final Logger log = LoggerFactory.getLogger(OfferBook.class);
|
||||||
private static final int POLLING_INTERVAL = 5000; // in ms
|
private static final int POLLING_INTERVAL = 2000; // in ms
|
||||||
|
|
||||||
private final OfferBookService offerBookService;
|
private final OfferBookService offerBookService;
|
||||||
private final User user;
|
private final User user;
|
||||||
|
|
|
@ -252,7 +252,7 @@ public class FileManager<T> {
|
||||||
private void saveNowInternal(T serializable) {
|
private void saveNowInternal(T serializable) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
saveToFile(serializable, dir, storageFile);
|
saveToFile(serializable, dir, storageFile);
|
||||||
log.info("Save {} completed in {}msec", storageFile, System.currentTimeMillis() - now);
|
Platform.runLater(() -> log.info("Save {} completed in {}msec", storageFile, System.currentTimeMillis() - now));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveToFile(T serializable, File dir, File storageFile) {
|
private void saveToFile(T serializable, File dir, File storageFile) {
|
||||||
|
@ -289,7 +289,6 @@ public class FileManager<T> {
|
||||||
renameTempFileToFile(tempFile, storageFile);
|
renameTempFileToFile(tempFile, storageFile);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
log.debug("storageFile " + storageFile.toString());
|
log.debug("storageFile " + storageFile.toString());
|
||||||
log.debug("currentThread " + Thread.currentThread());
|
|
||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
log.error("Error at saveToFile: " + t.getMessage());
|
log.error("Error at saveToFile: " + t.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -169,10 +169,11 @@ abstract public class Trade implements Model, Serializable {
|
||||||
createProtocol();
|
createProtocol();
|
||||||
|
|
||||||
if (mailboxMessage != null) {
|
if (mailboxMessage != null) {
|
||||||
tradeProtocol.applyMailboxMessage(mailboxMessage);
|
tradeProtocol.applyMailboxMessage(mailboxMessage, this);
|
||||||
// After applied to protocol we remove it
|
// After applied to protocol we remove it
|
||||||
mailboxMessage = null;
|
mailboxMessage = null;
|
||||||
}
|
}
|
||||||
|
tradeProtocol.checkPayoutTxTimeLock(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initStateProperties() {
|
protected void initStateProperties() {
|
||||||
|
@ -333,6 +334,11 @@ abstract public class Trade implements Model, Serializable {
|
||||||
tradeVolumeProperty.set(getTradeVolume());
|
tradeVolumeProperty.set(getTradeVolume());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO support case of multiple fiat accounts
|
||||||
|
public long getLockTimeDelta() {
|
||||||
|
return getOffer().getFiatAccountType().lockTimeDelta;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Coin getTradeAmount() {
|
public Coin getTradeAmount() {
|
||||||
return tradeAmount;
|
return tradeAmount;
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class BroadcastCreateOfferFeeTx extends Task<PlaceOfferModel> {
|
||||||
Coin balance = model.walletService.getBalanceForAddress(addressEntry.getAddress());
|
Coin balance = model.walletService.getBalanceForAddress(addressEntry.getAddress());
|
||||||
if (balance.compareTo(totalsNeeded) >= 0) {
|
if (balance.compareTo(totalsNeeded) >= 0) {
|
||||||
|
|
||||||
model.tradeWalletService.broadcastCreateOfferFeeTx(model.getTransaction(), new FutureCallback<Transaction>() {
|
model.tradeWalletService.broadcastTx(model.getTransaction(), new FutureCallback<Transaction>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Transaction transaction) {
|
public void onSuccess(Transaction transaction) {
|
||||||
log.info("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString());
|
log.info("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString());
|
||||||
|
|
|
@ -22,16 +22,17 @@ import io.bitsquare.p2p.Message;
|
||||||
import io.bitsquare.p2p.Peer;
|
import io.bitsquare.p2p.Peer;
|
||||||
import io.bitsquare.p2p.listener.SendMessageListener;
|
import io.bitsquare.p2p.listener.SendMessageListener;
|
||||||
import io.bitsquare.trade.BuyerAsOffererTrade;
|
import io.bitsquare.trade.BuyerAsOffererTrade;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage;
|
import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage;
|
||||||
import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage;
|
import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.RequestDepositTxInputsMessage;
|
import io.bitsquare.trade.protocol.trade.messages.RequestDepositTxInputsMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxMessage;
|
import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CommitPayoutTx;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.CommitPayoutTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestDepositTxInputsMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestDepositTxInputsMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
||||||
|
@ -41,6 +42,7 @@ import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndPublishDepositTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.VerifyAndSignContract;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.VerifyAndSignContract;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakeOfferFeePayment;
|
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakeOfferFeePayment;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakerAccount;
|
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakerAccount;
|
||||||
|
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||||
import io.bitsquare.trade.states.OffererTradeState;
|
import io.bitsquare.trade.states.OffererTradeState;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -72,13 +74,16 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyMailboxMessage(MailboxMessage mailboxMessage) {
|
public void applyMailboxMessage(MailboxMessage mailboxMessage, Trade trade) {
|
||||||
|
if (trade == null)
|
||||||
|
this.trade = trade;
|
||||||
|
|
||||||
log.debug("setMailboxMessage " + mailboxMessage);
|
log.debug("setMailboxMessage " + mailboxMessage);
|
||||||
// Might be called twice, so check that its only processed once
|
// Might be called twice, so check that its only processed once
|
||||||
if (!processModel.isMailboxMessageProcessed()) {
|
if (!processModel.isMailboxMessageProcessed()) {
|
||||||
processModel.mailboxMessageProcessed();
|
processModel.mailboxMessageProcessed();
|
||||||
if (mailboxMessage instanceof PayoutTxPublishedMessage) {
|
if (mailboxMessage instanceof PayoutTxFinalizedMessage) {
|
||||||
handle((PayoutTxPublishedMessage) mailboxMessage);
|
handle((PayoutTxFinalizedMessage) mailboxMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +184,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||||
// Incoming message handling
|
// Incoming message handling
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void handle(PayoutTxPublishedMessage tradeMessage) {
|
private void handle(PayoutTxFinalizedMessage tradeMessage) {
|
||||||
processModel.setTradeMessage(tradeMessage);
|
processModel.setTradeMessage(tradeMessage);
|
||||||
|
|
||||||
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
|
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
|
||||||
|
@ -190,8 +195,11 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||||
},
|
},
|
||||||
this::handleTaskRunnerFault);
|
this::handleTaskRunnerFault);
|
||||||
|
|
||||||
taskRunner.addTasks(ProcessPayoutTxPublishedMessage.class);
|
taskRunner.addTasks(
|
||||||
taskRunner.addTasks(CommitPayoutTx.class);
|
ProcessPayoutTxFinalizedMessage.class,
|
||||||
|
CommitPayoutTx.class,
|
||||||
|
SetupPayoutTxLockTimeReachedListener.class
|
||||||
|
);
|
||||||
taskRunner.run();
|
taskRunner.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,8 +224,8 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||||
else if (tradeMessage instanceof RequestPublishDepositTxMessage) {
|
else if (tradeMessage instanceof RequestPublishDepositTxMessage) {
|
||||||
handle((RequestPublishDepositTxMessage) tradeMessage);
|
handle((RequestPublishDepositTxMessage) tradeMessage);
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
else if (tradeMessage instanceof PayoutTxFinalizedMessage) {
|
||||||
handle((PayoutTxPublishedMessage) tradeMessage);
|
handle((PayoutTxFinalizedMessage) tradeMessage);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.error("Incoming tradeMessage not supported. " + tradeMessage);
|
log.error("Incoming tradeMessage not supported. " + tradeMessage);
|
||||||
|
|
|
@ -21,19 +21,21 @@ import io.bitsquare.p2p.MailboxMessage;
|
||||||
import io.bitsquare.p2p.Message;
|
import io.bitsquare.p2p.Message;
|
||||||
import io.bitsquare.p2p.Peer;
|
import io.bitsquare.p2p.Peer;
|
||||||
import io.bitsquare.trade.BuyerAsTakerTrade;
|
import io.bitsquare.trade.BuyerAsTakerTrade;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxPublishedMessage;
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxMessage;
|
import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CommitPayoutTx;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.CommitPayoutTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendFiatTransferStartedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendFiatTransferStartedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendRequestPayDepositMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendRequestPayDepositMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndPublishDepositTx;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndPublishDepositTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.VerifyAndSignContract;
|
import io.bitsquare.trade.protocol.trade.tasks.buyer.VerifyAndSignContract;
|
||||||
|
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.BroadcastTakeOfferFeeTx;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.BroadcastTakeOfferFeeTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOfferFeePayment;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOfferFeePayment;
|
||||||
|
@ -69,13 +71,16 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyMailboxMessage(MailboxMessage mailboxMessage) {
|
public void applyMailboxMessage(MailboxMessage mailboxMessage, Trade trade) {
|
||||||
|
if (trade == null)
|
||||||
|
this.trade = trade;
|
||||||
|
|
||||||
log.debug("setMailboxMessage " + mailboxMessage);
|
log.debug("setMailboxMessage " + mailboxMessage);
|
||||||
// Might be called twice, so check that its only processed once
|
// Might be called twice, so check that its only processed once
|
||||||
if (!processModel.isMailboxMessageProcessed()) {
|
if (!processModel.isMailboxMessageProcessed()) {
|
||||||
processModel.mailboxMessageProcessed();
|
processModel.mailboxMessageProcessed();
|
||||||
if (mailboxMessage instanceof PayoutTxPublishedMessage) {
|
if (mailboxMessage instanceof PayoutTxFinalizedMessage) {
|
||||||
handle((PayoutTxPublishedMessage) mailboxMessage);
|
handle((PayoutTxFinalizedMessage) mailboxMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +147,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
// After peer has received Fiat tx
|
// After peer has received Fiat tx
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void handle(PayoutTxPublishedMessage tradeMessage) {
|
private void handle(PayoutTxFinalizedMessage tradeMessage) {
|
||||||
processModel.setTradeMessage(tradeMessage);
|
processModel.setTradeMessage(tradeMessage);
|
||||||
|
|
||||||
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
|
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
|
||||||
|
@ -154,8 +159,9 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
this::handleTaskRunnerFault);
|
this::handleTaskRunnerFault);
|
||||||
|
|
||||||
taskRunner.addTasks(
|
taskRunner.addTasks(
|
||||||
ProcessPayoutTxPublishedMessage.class,
|
ProcessPayoutTxFinalizedMessage.class,
|
||||||
CommitPayoutTx.class);
|
CommitPayoutTx.class,
|
||||||
|
SetupPayoutTxLockTimeReachedListener.class);
|
||||||
taskRunner.run();
|
taskRunner.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,8 +180,8 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
if (tradeMessage instanceof RequestPublishDepositTxMessage) {
|
if (tradeMessage instanceof RequestPublishDepositTxMessage) {
|
||||||
handle((RequestPublishDepositTxMessage) tradeMessage);
|
handle((RequestPublishDepositTxMessage) tradeMessage);
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
else if (tradeMessage instanceof PayoutTxFinalizedMessage) {
|
||||||
handle((PayoutTxPublishedMessage) tradeMessage);
|
handle((PayoutTxFinalizedMessage) tradeMessage);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.error("Incoming message not supported. " + tradeMessage);
|
log.error("Incoming message not supported. " + tradeMessage);
|
||||||
|
|
|
@ -69,7 +69,6 @@ public class ProcessModel implements Model, Serializable {
|
||||||
transient private boolean mailboxMessageProcessed;
|
transient private boolean mailboxMessageProcessed;
|
||||||
transient private TradeMessage tradeMessage;
|
transient private TradeMessage tradeMessage;
|
||||||
private String takeOfferFeeTxId;
|
private String takeOfferFeeTxId;
|
||||||
private Transaction payoutTx;
|
|
||||||
private List<TransactionOutput> connectedOutputsForAllInputs;
|
private List<TransactionOutput> connectedOutputsForAllInputs;
|
||||||
private Coin payoutAmount;
|
private Coin payoutAmount;
|
||||||
private Transaction preparedDepositTx;
|
private Transaction preparedDepositTx;
|
||||||
|
@ -166,15 +165,6 @@ public class ProcessModel implements Model, Serializable {
|
||||||
return mailboxMessageProcessed;
|
return mailboxMessageProcessed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Transaction getPayoutTx() {
|
|
||||||
return payoutTx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayoutTx(Transaction payoutTx) {
|
|
||||||
this.payoutTx = payoutTx;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Transaction getTakeOfferFeeTx() {
|
public Transaction getTakeOfferFeeTx() {
|
||||||
return takeOfferFeeTx;
|
return takeOfferFeeTx;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import io.bitsquare.p2p.Message;
|
||||||
import io.bitsquare.p2p.Peer;
|
import io.bitsquare.p2p.Peer;
|
||||||
import io.bitsquare.p2p.listener.SendMessageListener;
|
import io.bitsquare.p2p.listener.SendMessageListener;
|
||||||
import io.bitsquare.trade.SellerAsOffererTrade;
|
import io.bitsquare.trade.SellerAsOffererTrade;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage;
|
import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage;
|
||||||
import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage;
|
import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
||||||
|
@ -36,9 +37,10 @@ import io.bitsquare.trade.protocol.trade.tasks.seller.CreateAndSignDepositTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestPublishDepositTxMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestPublishDepositTxMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndPublishPayoutTx;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndFinalizePayoutTx;
|
||||||
|
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||||
import io.bitsquare.trade.states.OffererTradeState;
|
import io.bitsquare.trade.states.OffererTradeState;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -71,7 +73,10 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyMailboxMessage(MailboxMessage mailboxMessage) {
|
public void applyMailboxMessage(MailboxMessage mailboxMessage, Trade trade) {
|
||||||
|
if (trade == null)
|
||||||
|
this.trade = trade;
|
||||||
|
|
||||||
log.debug("setMailboxMessage " + mailboxMessage);
|
log.debug("setMailboxMessage " + mailboxMessage);
|
||||||
// Might be called twice, so check that its only processed once
|
// Might be called twice, so check that its only processed once
|
||||||
if (!processModel.isMailboxMessageProcessed()) {
|
if (!processModel.isMailboxMessageProcessed()) {
|
||||||
|
@ -201,8 +206,9 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
|
||||||
|
|
||||||
taskRunner.addTasks(
|
taskRunner.addTasks(
|
||||||
VerifyTakeOfferFeePayment.class,
|
VerifyTakeOfferFeePayment.class,
|
||||||
SignAndPublishPayoutTx.class,
|
SignAndFinalizePayoutTx.class,
|
||||||
SendPayoutTxPublishedMessage.class
|
SendPayoutTxFinalizedMessage.class,
|
||||||
|
SetupPayoutTxLockTimeReachedListener.class
|
||||||
);
|
);
|
||||||
taskRunner.run();
|
taskRunner.run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import io.bitsquare.p2p.MailboxMessage;
|
||||||
import io.bitsquare.p2p.Message;
|
import io.bitsquare.p2p.Message;
|
||||||
import io.bitsquare.p2p.Peer;
|
import io.bitsquare.p2p.Peer;
|
||||||
import io.bitsquare.trade.SellerAsTakerTrade;
|
import io.bitsquare.trade.SellerAsTakerTrade;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
|
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositMessage;
|
import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositMessage;
|
||||||
|
@ -31,10 +32,11 @@ import io.bitsquare.trade.protocol.trade.tasks.seller.CreateAndSignDepositTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestDepositTxInputsMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestDepositTxInputsMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestPublishDepositTxMessage;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestPublishDepositTxMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndPublishPayoutTx;
|
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndFinalizePayoutTx;
|
||||||
|
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.BroadcastTakeOfferFeeTx;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.BroadcastTakeOfferFeeTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOfferFeePayment;
|
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOfferFeePayment;
|
||||||
|
@ -71,7 +73,10 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyMailboxMessage(MailboxMessage mailboxMessage) {
|
public void applyMailboxMessage(MailboxMessage mailboxMessage, Trade trade) {
|
||||||
|
if (trade == null)
|
||||||
|
this.trade = trade;
|
||||||
|
|
||||||
log.debug("setMailboxMessage " + mailboxMessage);
|
log.debug("setMailboxMessage " + mailboxMessage);
|
||||||
// Might be called twice, so check that its only processed once
|
// Might be called twice, so check that its only processed once
|
||||||
if (!processModel.isMailboxMessageProcessed()) {
|
if (!processModel.isMailboxMessageProcessed()) {
|
||||||
|
@ -177,8 +182,9 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||||
|
|
||||||
taskRunner.addTasks(
|
taskRunner.addTasks(
|
||||||
VerifyOfferFeePayment.class,
|
VerifyOfferFeePayment.class,
|
||||||
SignAndPublishPayoutTx.class,
|
SignAndFinalizePayoutTx.class,
|
||||||
SendPayoutTxPublishedMessage.class
|
SendPayoutTxFinalizedMessage.class,
|
||||||
|
SetupPayoutTxLockTimeReachedListener.class
|
||||||
);
|
);
|
||||||
taskRunner.run();
|
taskRunner.run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,10 @@ package io.bitsquare.trade.protocol.trade;
|
||||||
|
|
||||||
import io.bitsquare.p2p.MailboxMessage;
|
import io.bitsquare.p2p.MailboxMessage;
|
||||||
import io.bitsquare.p2p.MessageHandler;
|
import io.bitsquare.p2p.MessageHandler;
|
||||||
|
import io.bitsquare.trade.OffererTrade;
|
||||||
import io.bitsquare.trade.TakerTrade;
|
import io.bitsquare.trade.TakerTrade;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||||
import io.bitsquare.trade.states.OffererTradeState;
|
import io.bitsquare.trade.states.OffererTradeState;
|
||||||
import io.bitsquare.trade.states.TakerTradeState;
|
import io.bitsquare.trade.states.TakerTradeState;
|
||||||
|
|
||||||
|
@ -51,7 +53,32 @@ public abstract class TradeProtocol {
|
||||||
processModel.getMessageService().removeMessageHandler(messageHandler);
|
processModel.getMessageService().removeMessageHandler(messageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public void applyMailboxMessage(MailboxMessage mailboxMessage);
|
abstract public void applyMailboxMessage(MailboxMessage mailboxMessage, Trade trade);
|
||||||
|
|
||||||
|
public void checkPayoutTxTimeLock(Trade trade) {
|
||||||
|
if (trade == null)
|
||||||
|
this.trade = trade;
|
||||||
|
|
||||||
|
boolean needPayoutTxBroadcast = false;
|
||||||
|
if (trade instanceof TakerTrade)
|
||||||
|
needPayoutTxBroadcast = trade.processStateProperty().get() == TakerTradeState.ProcessState.PAYOUT_FINALIZED
|
||||||
|
|| trade.processStateProperty().get() == TakerTradeState.ProcessState.PAYOUT_FINALIZED_MSG_SENT;
|
||||||
|
else if (trade instanceof OffererTrade)
|
||||||
|
needPayoutTxBroadcast = trade.processStateProperty().get() == OffererTradeState.ProcessState.PAYOUT_FINALIZED
|
||||||
|
|| trade.processStateProperty().get() == OffererTradeState.ProcessState.PAYOUT_FINALIZED_MSG_SENT;
|
||||||
|
|
||||||
|
if (needPayoutTxBroadcast) {
|
||||||
|
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() {
|
||||||
log.debug("startTimeout");
|
log.debug("startTimeout");
|
||||||
|
|
|
@ -26,13 +26,13 @@ import java.io.Serializable;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
public class PayoutTxPublishedMessage extends TradeMessage implements MailboxMessage, Serializable {
|
public class PayoutTxFinalizedMessage extends TradeMessage implements MailboxMessage, Serializable {
|
||||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public final Transaction payoutTx;
|
public final Transaction payoutTx;
|
||||||
|
|
||||||
public PayoutTxPublishedMessage(String tradeId, Transaction payoutTx) {
|
public PayoutTxFinalizedMessage(String tradeId, Transaction payoutTx) {
|
||||||
super(tradeId);
|
super(tradeId);
|
||||||
this.payoutTx = payoutTx;
|
this.payoutTx = payoutTx;
|
||||||
}
|
}
|
|
@ -47,6 +47,7 @@ public class CreateAndSignPayoutTx extends TradeTask {
|
||||||
sellerPayoutAmount,
|
sellerPayoutAmount,
|
||||||
processModel.getAddressEntry(),
|
processModel.getAddressEntry(),
|
||||||
processModel.tradingPeer.getPayoutAddressString(),
|
processModel.tradingPeer.getPayoutAddressString(),
|
||||||
|
trade.getLockTimeDelta(),
|
||||||
processModel.getTradeWalletPubKey(),
|
processModel.getTradeWalletPubKey(),
|
||||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||||
processModel.getArbitratorPubKey());
|
processModel.getArbitratorPubKey());
|
||||||
|
|
|
@ -22,7 +22,7 @@ import io.bitsquare.trade.OffererTrade;
|
||||||
import io.bitsquare.trade.TakerTrade;
|
import io.bitsquare.trade.TakerTrade;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.trade.TradeTask;
|
import io.bitsquare.trade.protocol.trade.TradeTask;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.states.OffererTradeState;
|
import io.bitsquare.trade.states.OffererTradeState;
|
||||||
import io.bitsquare.trade.states.TakerTradeState;
|
import io.bitsquare.trade.states.TakerTradeState;
|
||||||
|
|
||||||
|
@ -32,26 +32,26 @@ import org.slf4j.LoggerFactory;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static io.bitsquare.util.Validator.checkTradeId;
|
import static io.bitsquare.util.Validator.checkTradeId;
|
||||||
|
|
||||||
public class ProcessPayoutTxPublishedMessage extends TradeTask {
|
public class ProcessPayoutTxFinalizedMessage extends TradeTask {
|
||||||
private static final Logger log = LoggerFactory.getLogger(ProcessPayoutTxPublishedMessage.class);
|
private static final Logger log = LoggerFactory.getLogger(ProcessPayoutTxFinalizedMessage.class);
|
||||||
|
|
||||||
public ProcessPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) {
|
public ProcessPayoutTxFinalizedMessage(TaskRunner taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doRun() {
|
protected void doRun() {
|
||||||
try {
|
try {
|
||||||
PayoutTxPublishedMessage message = (PayoutTxPublishedMessage) processModel.getTradeMessage();
|
PayoutTxFinalizedMessage message = (PayoutTxFinalizedMessage) processModel.getTradeMessage();
|
||||||
checkTradeId(processModel.getId(), message);
|
checkTradeId(processModel.getId(), message);
|
||||||
checkNotNull(message);
|
checkNotNull(message);
|
||||||
|
|
||||||
trade.setPayoutTx(checkNotNull(message.payoutTx));
|
trade.setPayoutTx(checkNotNull(message.payoutTx));
|
||||||
|
|
||||||
if (trade instanceof OffererTrade)
|
if (trade instanceof OffererTrade)
|
||||||
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_PUBLISHED);
|
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_FINALIZED);
|
||||||
else if (trade instanceof TakerTrade)
|
else if (trade instanceof TakerTrade)
|
||||||
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_PUBLISHED);
|
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_FINALIZED);
|
||||||
|
|
||||||
complete();
|
complete();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
|
@ -23,7 +23,7 @@ import io.bitsquare.trade.OffererTrade;
|
||||||
import io.bitsquare.trade.TakerTrade;
|
import io.bitsquare.trade.TakerTrade;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.trade.TradeTask;
|
import io.bitsquare.trade.protocol.trade.TradeTask;
|
||||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||||
import io.bitsquare.trade.states.OffererTradeState;
|
import io.bitsquare.trade.states.OffererTradeState;
|
||||||
import io.bitsquare.trade.states.StateUtil;
|
import io.bitsquare.trade.states.StateUtil;
|
||||||
import io.bitsquare.trade.states.TakerTradeState;
|
import io.bitsquare.trade.states.TakerTradeState;
|
||||||
|
@ -31,17 +31,17 @@ import io.bitsquare.trade.states.TakerTradeState;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class SendPayoutTxPublishedMessage extends TradeTask {
|
public class SendPayoutTxFinalizedMessage extends TradeTask {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxPublishedMessage.class);
|
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxFinalizedMessage.class);
|
||||||
|
|
||||||
public SendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) {
|
public SendPayoutTxFinalizedMessage(TaskRunner taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doRun() {
|
protected void doRun() {
|
||||||
try {
|
try {
|
||||||
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(processModel.getId(), processModel.getPayoutTx());
|
PayoutTxFinalizedMessage tradeMessage = new PayoutTxFinalizedMessage(processModel.getId(), trade.getPayoutTx());
|
||||||
processModel.getMessageService().sendMessage(trade.getTradingPeer(),
|
processModel.getMessageService().sendMessage(trade.getTradingPeer(),
|
||||||
tradeMessage,
|
tradeMessage,
|
||||||
processModel.tradingPeer.getP2pSigPubKey(),
|
processModel.tradingPeer.getP2pSigPubKey(),
|
||||||
|
@ -52,9 +52,9 @@ public class SendPayoutTxPublishedMessage extends TradeTask {
|
||||||
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
||||||
|
|
||||||
if (trade instanceof TakerTrade)
|
if (trade instanceof TakerTrade)
|
||||||
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_PUBLISHED_MSG_SENT);
|
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_FINALIZED_MSG_SENT);
|
||||||
else if (trade instanceof OffererTrade)
|
else if (trade instanceof OffererTrade)
|
||||||
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_PUBLISHED_MSG_SENT);
|
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_FINALIZED_MSG_SENT);
|
||||||
|
|
||||||
complete();
|
complete();
|
||||||
}
|
}
|
|
@ -27,53 +27,39 @@ import io.bitsquare.trade.states.TakerTradeState;
|
||||||
|
|
||||||
import org.bitcoinj.core.Transaction;
|
import org.bitcoinj.core.Transaction;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class SignAndPublishPayoutTx extends TradeTask {
|
public class SignAndFinalizePayoutTx extends TradeTask {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
|
private static final Logger log = LoggerFactory.getLogger(SignAndFinalizePayoutTx.class);
|
||||||
|
|
||||||
public SignAndPublishPayoutTx(TaskRunner taskHandler, Trade trade) {
|
public SignAndFinalizePayoutTx(TaskRunner taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doRun() {
|
protected void doRun() {
|
||||||
try {
|
try {
|
||||||
processModel.getTradeWalletService().signAndPublishPayoutTx(
|
Transaction transaction = processModel.getTradeWalletService().signAndFinalizePayoutTx(
|
||||||
trade.getDepositTx(),
|
trade.getDepositTx(),
|
||||||
processModel.tradingPeer.getSignature(),
|
processModel.tradingPeer.getSignature(),
|
||||||
processModel.tradingPeer.getPayoutAmount(),
|
processModel.tradingPeer.getPayoutAmount(),
|
||||||
processModel.getPayoutAmount(),
|
processModel.getPayoutAmount(),
|
||||||
processModel.tradingPeer.getPayoutAddressString(),
|
processModel.tradingPeer.getPayoutAddressString(),
|
||||||
processModel.getAddressEntry(),
|
processModel.getAddressEntry(),
|
||||||
|
trade.getLockTimeDelta(),
|
||||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||||
processModel.getTradeWalletPubKey(),
|
processModel.getTradeWalletPubKey(),
|
||||||
processModel.getArbitratorPubKey(),
|
processModel.getArbitratorPubKey()
|
||||||
new FutureCallback<Transaction>() {
|
);
|
||||||
@Override
|
|
||||||
public void onSuccess(Transaction transaction) {
|
|
||||||
processModel.setPayoutTx(transaction);
|
|
||||||
|
|
||||||
|
trade.setPayoutTx(transaction);
|
||||||
if (trade instanceof TakerTrade)
|
if (trade instanceof TakerTrade)
|
||||||
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_PUBLISHED);
|
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_FINALIZED);
|
||||||
else if (trade instanceof OffererTrade)
|
else if (trade instanceof OffererTrade)
|
||||||
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_PUBLISHED);
|
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_FINALIZED);
|
||||||
|
|
||||||
complete();
|
complete();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NotNull Throwable t) {
|
|
||||||
t.printStackTrace();
|
|
||||||
trade.setThrowable(t);
|
|
||||||
failed(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
trade.setThrowable(t);
|
trade.setThrowable(t);
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Bitsquare.
|
||||||
|
*
|
||||||
|
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.bitsquare.trade.protocol.trade.tasks.shared;
|
||||||
|
|
||||||
|
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||||
|
import io.bitsquare.trade.OffererTrade;
|
||||||
|
import io.bitsquare.trade.TakerTrade;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.protocol.trade.TradeTask;
|
||||||
|
import io.bitsquare.trade.states.OffererTradeState;
|
||||||
|
import io.bitsquare.trade.states.TakerTradeState;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.StoredBlock;
|
||||||
|
import org.bitcoinj.core.Transaction;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SetupPayoutTxLockTimeReachedListener extends TradeTask {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SetupPayoutTxLockTimeReachedListener.class);
|
||||||
|
|
||||||
|
public SetupPayoutTxLockTimeReachedListener(TaskRunner taskHandler, Trade trade) {
|
||||||
|
super(taskHandler, trade);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doRun() {
|
||||||
|
try {
|
||||||
|
if (processModel.getTradeWalletService().getBestChainHeight() >= trade.getPayoutTx().getLockTime()) {
|
||||||
|
broadcastTx();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ListenableFuture<StoredBlock> blockHeightFuture = processModel.getTradeWalletService().getBlockHeightFuture(trade.getPayoutTx());
|
||||||
|
blockHeightFuture.addListener(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
log.debug("Block height reached " + blockHeightFuture.get().getHeight());
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
broadcastTx();
|
||||||
|
},
|
||||||
|
Platform::runLater);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
trade.setThrowable(t);
|
||||||
|
failed(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void broadcastTx() {
|
||||||
|
processModel.getTradeWalletService().broadcastTx(trade.getPayoutTx(), new FutureCallback<Transaction>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction) {
|
||||||
|
log.debug("BroadcastTx succeeded. Transaction:" + transaction);
|
||||||
|
|
||||||
|
if (trade instanceof TakerTrade)
|
||||||
|
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_BROAD_CASTED);
|
||||||
|
else if (trade instanceof OffererTrade)
|
||||||
|
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_BROAD_CASTED);
|
||||||
|
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NotNull Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
trade.setThrowable(t);
|
||||||
|
|
||||||
|
if (trade instanceof TakerTrade)
|
||||||
|
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_BROAD_CASTED_FAILED);
|
||||||
|
else if (trade instanceof OffererTrade)
|
||||||
|
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_BROAD_CASTED_FAILED);
|
||||||
|
|
||||||
|
|
||||||
|
failed(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ public class BroadcastTakeOfferFeeTx extends TradeTask {
|
||||||
@Override
|
@Override
|
||||||
protected void doRun() {
|
protected void doRun() {
|
||||||
try {
|
try {
|
||||||
processModel.getTradeWalletService().broadcastTakeOfferFeeTx(processModel.getTakeOfferFeeTx(),
|
processModel.getTradeWalletService().broadcastTx(processModel.getTakeOfferFeeTx(),
|
||||||
new FutureCallback<Transaction>() {
|
new FutureCallback<Transaction>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Transaction transaction) {
|
public void onSuccess(Transaction transaction) {
|
||||||
|
|
|
@ -40,8 +40,10 @@ public class OffererTradeState {
|
||||||
FIAT_PAYMENT_STARTED,
|
FIAT_PAYMENT_STARTED,
|
||||||
|
|
||||||
FIAT_PAYMENT_RECEIVED,
|
FIAT_PAYMENT_RECEIVED,
|
||||||
PAYOUT_PUBLISHED,
|
PAYOUT_FINALIZED,
|
||||||
PAYOUT_PUBLISHED_MSG_SENT,
|
PAYOUT_FINALIZED_MSG_SENT,
|
||||||
|
PAYOUT_BROAD_CASTED,
|
||||||
|
PAYOUT_BROAD_CASTED_FAILED,
|
||||||
|
|
||||||
MESSAGE_SENDING_FAILED,
|
MESSAGE_SENDING_FAILED,
|
||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
|
|
|
@ -41,8 +41,10 @@ public class TakerTradeState {
|
||||||
FIAT_PAYMENT_STARTED,
|
FIAT_PAYMENT_STARTED,
|
||||||
|
|
||||||
FIAT_PAYMENT_RECEIVED,
|
FIAT_PAYMENT_RECEIVED,
|
||||||
PAYOUT_PUBLISHED,
|
PAYOUT_FINALIZED,
|
||||||
PAYOUT_PUBLISHED_MSG_SENT,
|
PAYOUT_FINALIZED_MSG_SENT,
|
||||||
|
PAYOUT_BROAD_CASTED,
|
||||||
|
PAYOUT_BROAD_CASTED_FAILED,
|
||||||
|
|
||||||
MESSAGE_SENDING_FAILED,
|
MESSAGE_SENDING_FAILED,
|
||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
|
|
|
@ -34,12 +34,13 @@
|
||||||
<logger name="io.bitsquare.gui.util.Profiler" level="ERROR"/>
|
<logger name="io.bitsquare.gui.util.Profiler" level="ERROR"/>
|
||||||
<logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
|
<logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
|
||||||
|
|
||||||
<logger name="org.bitcoinj" level="INFO"/>
|
<logger name="org.bitcoinj" level="WARN"/>
|
||||||
<logger name="net.tomp2p" level="INFO"/>
|
<logger name="net.tomp2p" level="WARN"/>
|
||||||
|
|
||||||
<logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
<logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
||||||
<logger name="org.bitcoinj.core.Peer" level="WARN"/>
|
<logger name="org.bitcoinj.core.Peer" level="WARN"/>
|
||||||
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<logger name="com.vinumeris.updatefx" level="OFF"/>
|
<logger name="com.vinumeris.updatefx" level="OFF"/>
|
||||||
<logger name="io.netty" level="OFF"/>
|
<logger name="io.netty" level="OFF"/>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue