From fd1f23ea629dd113b55f8be2a3b275e478bc63bf Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 5 Jul 2014 15:37:34 +0200 Subject: [PATCH] refactoring trade protocol, reformatting --- pom.xml | 13 +- src/main/java/io/bitsquare/BitSquare.java | 8 + src/main/java/io/bitsquare/RelayNode.java | 4 + .../java/io/bitsquare/bank/BankAccount.java | 12 +- .../btc/AddressBasedCoinSelector.java | 34 +- .../bitsquare/btc/BitSquareWalletAppKit.java | 44 +- .../java/io/bitsquare/btc/WalletFacade.java | 84 +- .../java/io/bitsquare/di/GuiceFXMLLoader.java | 2 + .../java/io/bitsquare/gui/MainController.java | 6 + .../ArbitratorOverviewController.java | 2 + .../profile/ArbitratorProfileController.java | 4 +- .../ArbitratorRegistrationController.java | 48 +- .../gui/components/LazyLoadingTabPane.java | 8 + .../gui/components/ValidatedTextField.java | 4 +- .../ConfidenceProgressIndicator.java | 6 +- .../skin/ConfidenceProgressIndicatorSkin.java | 265 +++--- .../components/processbar/ProcessStepBar.java | 2 + .../processbar/ProcessStepBarSkin.java | 10 +- .../withdrawal/WithdrawalController.java | 5 +- .../funds/withdrawal/WithdrawalListItem.java | 4 + .../io/bitsquare/gui/home/HomeController.java | 2 + .../gui/market/MarketController.java | 4 + .../createOffer/CreateOfferController.java | 28 +- .../market/orderbook/OrderBookController.java | 45 +- .../market/trade/TakerOfferController.java | 123 +-- .../market/trade/TakerTradeController.java | 6 +- .../pending/PendingTradeController.java | 4 + .../java/io/bitsquare/gui/popups/Popups.java | 59 +- .../gui/settings/SettingsController.java | 282 +++--- .../gui/util/BitSquareFormatter.java | 14 + .../bitsquare/gui/util/ConfidenceDisplay.java | 12 + .../java/io/bitsquare/locale/Country.java | 4 + .../java/io/bitsquare/locale/CountryUtil.java | 218 +---- src/main/java/io/bitsquare/locale/Region.java | 4 + .../java/io/bitsquare/msg/MessageFacade.java | 43 +- .../java/io/bitsquare/settings/Settings.java | 6 + .../java/io/bitsquare/storage/Storage.java | 6 + src/main/java/io/bitsquare/trade/Trading.java | 204 ++-- .../bitsquare/trade/orderbook/OrderBook.java | 30 +- .../protocol/{tasks => }/FaultHandler.java | 2 +- .../protocol/{tasks => }/ResultHandler.java | 2 +- .../AcceptTakeOfferRequestMessage.java | 22 - .../RejectTakeOfferRequestMessage.java | 21 - .../offerer/BankTransferInitedMessage.java | 5 +- .../{tasks => }/offerer/CreateDepositTx.java | 10 +- .../offerer/DepositTxPublishedMessage.java | 2 +- .../offerer/HandleTakeOfferRequest.java | 44 + ...ol.java => ProtocolForOffererAsBuyer.java} | 714 +++++++------- ...=> ProtocolForOffererAsBuyerListener.java} | 10 +- .../offerer/RequestTakerDepositPayment.java | 14 +- .../RequestTakerDepositPaymentMessage.java | 5 +- .../RespondToTakeOfferRequestMessage.java | 28 + .../offerer/SendDepositTxIdToTaker.java | 7 +- .../offerer/SendSignedPayoutTx.java | 25 +- ...etupListenerForBlockChainConfirmation.java | 38 + .../offerer/SignAndPublishDepositTx.java | 60 ++ .../offerer/VerifyAndSignContract.java | 14 +- .../offerer/VerifyTakeOfferFeePayment.java | 6 +- .../protocol/offerer/VerifyTakerAccount.java | 20 + .../BuyOffererPaymentProcess.java | 2 +- .../{mock => old}/BuyTakerPaymentProcess.java | 2 +- .../{mock => old}/PaymentProcess.java | 2 +- .../SellOffererPaymentProcess.java | 2 +- .../SellTakerPaymentProcess.java | 2 +- .../VerifyPeerAccount.java} | 10 +- .../protocol/taker/CreateAndSignContract.java | 51 + .../{tasks => }/taker/GetPeerAddress.java | 4 +- .../trade/protocol/taker/PayDeposit.java | 54 ++ .../{tasks => }/taker/PayTakeOfferFee.java | 8 +- .../taker/PayoutTxPublishedMessage.java | 2 +- .../taker/ProtocolForTakerAsSeller.java | 400 ++++++++ ... => ProtocolForTakerAsSellerListener.java} | 8 +- ...RequestOffererPublishDepositTxMessage.java | 8 +- .../{tasks => }/taker/RequestTakeOffer.java | 7 +- .../taker/RequestTakeOfferMessage.java | 2 +- .../taker/SendPayoutTxToOfferer.java | 12 +- .../taker/SendSignedTakerDepositTxAsHex.java | 67 ++ .../taker/SendTakeOfferFeePayedTxId.java | 14 +- .../taker/SignAndPublishPayoutTx.java | 66 ++ .../taker/TakeOfferFeePayedMessage.java | 12 +- .../protocol/taker/TakerAsSellerProtocol.java | 882 ------------------ .../protocol/taker/VerifyOffererAccount.java | 19 + .../tasks/offerer/HandleTakeOfferRequest.java | 65 -- ...etupListenerForBlockChainConfirmation.java | 40 - .../offerer/SignAndPublishDepositTx.java | 60 -- .../tasks/taker/CreateAndSignContract.java | 60 -- .../protocol/tasks/taker/PayDeposit.java | 46 - .../taker/SendSignedTakerDepositTxAsHex.java | 61 -- .../tasks/taker/SignAndPublishPayoutTx.java | 68 -- .../tasks/taker/VerifyOffererAccount.java | 35 - .../java/io/bitsquare/user/Arbitrator.java | 8 + src/main/java/io/bitsquare/user/User.java | 21 +- .../java/io/bitsquare/util/DSAKeyUtil.java | 16 + src/main/java/io/bitsquare/util/FileUtil.java | 2 + .../java/io/bitsquare/util/Utilities.java | 2 + 95 files changed, 2207 insertions(+), 2621 deletions(-) rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/FaultHandler.java (63%) rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/ResultHandler.java (57%) delete mode 100644 src/main/java/io/bitsquare/trade/protocol/messages/offerer/AcceptTakeOfferRequestMessage.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/messages/offerer/RejectTakeOfferRequestMessage.java rename src/main/java/io/bitsquare/trade/protocol/{messages => }/offerer/BankTransferInitedMessage.java (92%) rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/offerer/CreateDepositTx.java (85%) rename src/main/java/io/bitsquare/trade/protocol/{messages => }/offerer/DepositTxPublishedMessage.java (92%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/offerer/HandleTakeOfferRequest.java rename src/main/java/io/bitsquare/trade/protocol/offerer/{OffererAsBuyerProtocol.java => ProtocolForOffererAsBuyer.java} (57%) rename src/main/java/io/bitsquare/trade/protocol/offerer/{OffererAsBuyerProtocolListener.java => ProtocolForOffererAsBuyerListener.java} (55%) rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/offerer/RequestTakerDepositPayment.java (78%) rename src/main/java/io/bitsquare/trade/protocol/{messages => }/offerer/RequestTakerDepositPaymentMessage.java (94%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/offerer/RespondToTakeOfferRequestMessage.java rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/offerer/SendDepositTxIdToTaker.java (85%) rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/offerer/SendSignedPayoutTx.java (73%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/offerer/SetupListenerForBlockChainConfirmation.java create mode 100644 src/main/java/io/bitsquare/trade/protocol/offerer/SignAndPublishDepositTx.java rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/offerer/VerifyAndSignContract.java (84%) rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/offerer/VerifyTakeOfferFeePayment.java (79%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/offerer/VerifyTakerAccount.java rename src/main/java/io/bitsquare/trade/protocol/{mock => old}/BuyOffererPaymentProcess.java (95%) rename src/main/java/io/bitsquare/trade/protocol/{mock => old}/BuyTakerPaymentProcess.java (95%) rename src/main/java/io/bitsquare/trade/protocol/{mock => old}/PaymentProcess.java (99%) rename src/main/java/io/bitsquare/trade/protocol/{mock => old}/SellOffererPaymentProcess.java (95%) rename src/main/java/io/bitsquare/trade/protocol/{mock => old}/SellTakerPaymentProcess.java (95%) rename src/main/java/io/bitsquare/trade/protocol/{tasks/offerer/VerifyTakerAccount.java => shared/VerifyPeerAccount.java} (82%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/taker/CreateAndSignContract.java rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/taker/GetPeerAddress.java (91%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/taker/PayDeposit.java rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/taker/PayTakeOfferFee.java (88%) rename src/main/java/io/bitsquare/trade/protocol/{messages => }/taker/PayoutTxPublishedMessage.java (92%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/taker/ProtocolForTakerAsSeller.java rename src/main/java/io/bitsquare/trade/protocol/taker/{TakerAsSellerProtocolListener.java => ProtocolForTakerAsSellerListener.java} (53%) rename src/main/java/io/bitsquare/trade/protocol/{messages => }/taker/RequestOffererPublishDepositTxMessage.java (94%) rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/taker/RequestTakeOffer.java (82%) rename src/main/java/io/bitsquare/trade/protocol/{messages => }/taker/RequestTakeOfferMessage.java (89%) rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/taker/SendPayoutTxToOfferer.java (76%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/taker/SendSignedTakerDepositTxAsHex.java rename src/main/java/io/bitsquare/trade/protocol/{tasks => }/taker/SendTakeOfferFeePayedTxId.java (78%) create mode 100644 src/main/java/io/bitsquare/trade/protocol/taker/SignAndPublishPayoutTx.java rename src/main/java/io/bitsquare/trade/protocol/{messages => }/taker/TakeOfferFeePayedMessage.java (73%) delete mode 100644 src/main/java/io/bitsquare/trade/protocol/taker/TakerAsSellerProtocol.java create mode 100644 src/main/java/io/bitsquare/trade/protocol/taker/VerifyOffererAccount.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/tasks/offerer/HandleTakeOfferRequest.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SetupListenerForBlockChainConfirmation.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SignAndPublishDepositTx.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/tasks/taker/CreateAndSignContract.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/tasks/taker/PayDeposit.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendSignedTakerDepositTxAsHex.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/tasks/taker/SignAndPublishPayoutTx.java delete mode 100644 src/main/java/io/bitsquare/trade/protocol/tasks/taker/VerifyOffererAccount.java diff --git a/pom.xml b/pom.xml index 06c8a87ef7..e38afde78d 100644 --- a/pom.xml +++ b/pom.xml @@ -198,17 +198,10 @@ --> - com.typesafe.akka - akka-actor_2.11 - 2.3.3 + org.jetbrains + annotations + 13.0 - diff --git a/src/main/java/io/bitsquare/BitSquare.java b/src/main/java/io/bitsquare/BitSquare.java index 1ed40fb5f0..1921605666 100644 --- a/src/main/java/io/bitsquare/BitSquare.java +++ b/src/main/java/io/bitsquare/BitSquare.java @@ -36,7 +36,9 @@ public class BitSquare extends Application { log.debug("Startup: main"); if (args != null && args.length > 0) + { ID = args[0]; + } launch(args); } @@ -73,9 +75,13 @@ public class BitSquare extends Application settings.updateFromStorage((Settings) storage.read(settings.getClass().getName())); if (ID.isEmpty()) + { stage.setTitle("BitSquare"); + } else + { stage.setTitle("BitSquare (" + ID + ")"); + } GuiceFXMLLoader.setInjector(injector); @@ -101,7 +107,9 @@ public class BitSquare extends Application stage.show(); Action response = Popups.openExceptionPopup(e); if (response == Dialog.Actions.OK) + { Platform.exit(); + } } } diff --git a/src/main/java/io/bitsquare/RelayNode.java b/src/main/java/io/bitsquare/RelayNode.java index 51e7abce84..aab891689f 100755 --- a/src/main/java/io/bitsquare/RelayNode.java +++ b/src/main/java/io/bitsquare/RelayNode.java @@ -16,9 +16,13 @@ class RelayNode public static void main(String[] args) throws Exception { if (args != null && args.length == 1) + { INSTANCE(new Integer(args[0])); + } else + { INSTANCE(5000); + } } private static void INSTANCE(int port) throws Exception diff --git a/src/main/java/io/bitsquare/bank/BankAccount.java b/src/main/java/io/bitsquare/bank/BankAccount.java index 2df783a350..428ee3184e 100644 --- a/src/main/java/io/bitsquare/bank/BankAccount.java +++ b/src/main/java/io/bitsquare/bank/BankAccount.java @@ -26,13 +26,7 @@ public class BankAccount implements Serializable private final String accountTitle; - public BankAccount(BankAccountType bankAccountType, - Currency currency, - Country country, - String accountTitle, - String accountHolderName, - String accountPrimaryID, - String accountSecondaryID) + public BankAccount(BankAccountType bankAccountType, Currency currency, Country country, String accountTitle, String accountHolderName, String accountPrimaryID, String accountSecondaryID) { this.bankAccountType = bankAccountType; this.currency = currency; @@ -53,9 +47,13 @@ public class BankAccount implements Serializable public boolean equals(Object obj) { if (!(obj instanceof BankAccount)) + { return false; + } if (obj == this) + { return true; + } final BankAccount other = (BankAccount) obj; return uid.equals(other.getUid()); diff --git a/src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java b/src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java index bfeee1b383..cdf8823e43 100644 --- a/src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java +++ b/src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java @@ -51,18 +51,28 @@ class AddressBasedCoinSelector extends DefaultCoinSelector TransactionConfidence conf1 = a.getParentTransaction().getConfidence(); TransactionConfidence conf2 = b.getParentTransaction().getConfidence(); if (conf1.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) + { depth1 = conf1.getDepthInBlocks(); + } if (conf2.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) + { depth2 = conf2.getDepthInBlocks(); + } BigInteger aValue = a.getValue(); BigInteger bValue = b.getValue(); BigInteger aCoinDepth = aValue.multiply(BigInteger.valueOf(depth1)); BigInteger bCoinDepth = bValue.multiply(BigInteger.valueOf(depth2)); int c1 = bCoinDepth.compareTo(aCoinDepth); - if (c1 != 0) return c1; + if (c1 != 0) + { + return c1; + } // The "coin*days" destroyed are equal, sort by value alone to get the lowest transaction size. int c2 = bValue.compareTo(aValue); - if (c2 != 0) return c2; + if (c2 != 0) + { + return c2; + } // They are entirely equivalent (possibly pending) so sort by hash to ensure a total ordering. BigInteger aHash = a.getParentTransaction().getHash().toBigInteger(); BigInteger bHash = b.getParentTransaction().getHash().toBigInteger(); @@ -75,11 +85,10 @@ class AddressBasedCoinSelector extends DefaultCoinSelector // Pick chain-included transactions and transactions that are pending. TransactionConfidence confidence = tx.getConfidence(); TransactionConfidence.ConfidenceType type = confidence.getConfidenceType(); - return type.equals(TransactionConfidence.ConfidenceType.BUILDING) || - type.equals(TransactionConfidence.ConfidenceType.PENDING) && - // In regtest mode we expect to have only one peer, so we won't see transactions propagate. - // TODO: The value 1 below dates from a time when transactions we broadcast *to* were counted, set to 0 - (confidence.numBroadcastPeers() > 1 || tx.getParams() == RegTestParams.get()); + return type.equals(TransactionConfidence.ConfidenceType.BUILDING) || type.equals(TransactionConfidence.ConfidenceType.PENDING) && + // In regtest mode we expect to have only one peer, so we won't see transactions propagate. + // TODO: The value 1 below dates from a time when transactions we broadcast *to* were counted, set to 0 + (confidence.numBroadcastPeers() > 1 || tx.getParams() == RegTestParams.get()); } private static boolean isInBlockChain(Transaction tx) @@ -96,9 +105,13 @@ class AddressBasedCoinSelector extends DefaultCoinSelector protected boolean shouldSelect(Transaction tx) { if (includePending) + { return isInBlockChainOrPending(tx); + } else + { return isInBlockChain(tx); + } } @SuppressWarnings("WeakerAccess") @@ -134,11 +147,16 @@ class AddressBasedCoinSelector extends DefaultCoinSelector long total = 0; for (TransactionOutput output : sortedOutputs) { - if (total >= target) break; + if (total >= target) + { + break; + } // Only pick chain-included transactions, or transactions that are ours and pending. // Only select outputs from our defined address(es) if (!shouldSelect(output.getParentTransaction()) || !matchesRequiredAddress(output)) + { continue; + } selected.add(output); total += output.getValue().longValue(); diff --git a/src/main/java/io/bitsquare/btc/BitSquareWalletAppKit.java b/src/main/java/io/bitsquare/btc/BitSquareWalletAppKit.java index e93b334acc..09ca44ad98 100644 --- a/src/main/java/io/bitsquare/btc/BitSquareWalletAppKit.java +++ b/src/main/java/io/bitsquare/btc/BitSquareWalletAppKit.java @@ -63,7 +63,9 @@ public class BitSquareWalletAppKit extends WalletAppKit vPeerGroup.setBloomFilterFalsePositiveRate(0.001); // 0,1% instead of default 0,05% if (this.userAgent != null) + { vPeerGroup.setUserAgent(userAgent, version); + } if (vWalletFile.exists()) { walletStream = new FileInputStream(vWalletFile); @@ -71,7 +73,9 @@ public class BitSquareWalletAppKit extends WalletAppKit addWalletExtensions(); // All extensions must be present before we deserialize new WalletProtobufSerializer().readWallet(WalletProtobufSerializer.parseToProto(walletStream), vWallet); if (shouldReplayWallet) + { vWallet.clearTransactions(0); + } } else { @@ -79,12 +83,18 @@ public class BitSquareWalletAppKit extends WalletAppKit vWallet.addKey(new ECKey()); addWalletExtensions(); } - if (useAutoSave) vWallet.autosaveToFile(vWalletFile, 1, TimeUnit.SECONDS, null); + if (useAutoSave) + { + vWallet.autosaveToFile(vWalletFile, 1, TimeUnit.SECONDS, null); + } // Set up peer addresses or discovery first, so if wallet extensions try to broadcast a transaction // before we're actually connected the broadcast waits for an appropriate number of connections. if (peerAddresses != null) { - for (PeerAddress addr : peerAddresses) vPeerGroup.addAddress(addr); + for (PeerAddress addr : peerAddresses) + { + vPeerGroup.addAddress(addr); + } peerAddresses = null; } else @@ -130,27 +140,33 @@ public class BitSquareWalletAppKit extends WalletAppKit throw new IOException(e); } finally { - if (walletStream != null) walletStream.close(); + if (walletStream != null) + { + walletStream.close(); + } } } private void installShutdownHook() { - if (autoStop) Runtime.getRuntime().addShutdownHook(new Thread() + if (autoStop) { - @Override - public void run() + Runtime.getRuntime().addShutdownHook(new Thread() { - try + @Override + public void run() { - BitSquareWalletAppKit.this.stopAsync(); - BitSquareWalletAppKit.this.awaitTerminated(); + try + { + BitSquareWalletAppKit.this.stopAsync(); + BitSquareWalletAppKit.this.awaitTerminated(); - } catch (Exception e) - { - throw new RuntimeException(e); + } catch (Exception e) + { + throw new RuntimeException(e); + } } - } - }); + }); + } } } diff --git a/src/main/java/io/bitsquare/btc/WalletFacade.java b/src/main/java/io/bitsquare/btc/WalletFacade.java index 0dbf4e0c82..3ca10f357e 100644 --- a/src/main/java/io/bitsquare/btc/WalletFacade.java +++ b/src/main/java/io/bitsquare/btc/WalletFacade.java @@ -124,7 +124,9 @@ public class WalletFacade //walletAppKit.peerGroup().setMaxConnections(11); if (params == RegTestParams.get()) + { walletAppKit.peerGroup().setMinBroadcastConnections(1); + } /* else walletAppKit.peerGroup().setMinBroadcastConnections(2); */ @@ -262,7 +264,9 @@ public class WalletFacade { AddressEntry arbitratorDepositAddressEntry = getAddressInfoByAddressContext(AddressEntry.AddressContext.ARBITRATOR_DEPOSIT); if (arbitratorDepositAddressEntry == null) + { arbitratorDepositAddressEntry = getNewArbitratorDepositAddressEntry(); + } return arbitratorDepositAddressEntry; } @@ -270,23 +274,37 @@ public class WalletFacade AddressEntry getUnusedTradeAddressInfo() { - List filteredList = Lists.newArrayList(Collections2.filter(ImmutableList.copyOf(addressEntryList), addressInfo -> (addressInfo != null && addressInfo.getAddressContext().equals(AddressEntry.AddressContext.TRADE) && addressInfo.getTradeId() == null))); + List filteredList = Lists.newArrayList(Collections2.filter(ImmutableList.copyOf(addressEntryList), + addressInfo -> (addressInfo != null && addressInfo.getAddressContext() + .equals(AddressEntry.AddressContext.TRADE) && addressInfo + .getTradeId() == null))); if (filteredList != null && !filteredList.isEmpty()) + { return filteredList.get(0); + } else + { return getNewTradeAddressEntry(); + } } private AddressEntry getAddressInfoByAddressContext(AddressEntry.AddressContext addressContext) { - List filteredList = Lists.newArrayList(Collections2.filter(ImmutableList.copyOf(addressEntryList), addressInfo -> (addressInfo != null && addressInfo.getAddressContext() != null && addressInfo.getAddressContext().equals(addressContext)))); + List filteredList = Lists.newArrayList(Collections2.filter(ImmutableList.copyOf(addressEntryList), + addressInfo -> (addressInfo != null && addressInfo.getAddressContext() != null && addressInfo.getAddressContext() + .equals(addressContext) + ))); if (filteredList != null && !filteredList.isEmpty()) + { return filteredList.get(0); + } else + { return null; + } } @@ -295,7 +313,9 @@ public class WalletFacade for (AddressEntry addressEntry : ImmutableList.copyOf(addressEntryList)) { if (addressEntry.getTradeId() != null && addressEntry.getTradeId().equals(tradeId)) + { return addressEntry; + } } AddressEntry addressEntry = getUnusedTradeAddressInfo(); @@ -343,7 +363,9 @@ public class WalletFacade for (AddressEntry addressEntry : addressEntryList) { if (addressEntry.getAddressString().equals(address)) + { return addressEntry; + } } return null; } @@ -424,7 +446,9 @@ public class WalletFacade { TransactionOutput transactionOutput = transactionInput.getConnectedOutput(); if (transactionOutput != null) + { connectedOutputs.add(transactionOutput); + } } List mergedOutputs = new ArrayList<>(); @@ -460,7 +484,9 @@ public class WalletFacade { TransactionConfidence transactionConfidence = null; if (getRegistrationAddressInfo() != null) + { transactionConfidence = getConfidenceForAddress(getRegistrationAddressInfo().getAddress()); + } return transactionConfidence != null && transactionConfidence.getConfidenceType().equals(TransactionConfidence.ConfidenceType.BUILDING); } @@ -497,9 +523,13 @@ public class WalletFacade { BigInteger balance; if (balanceListener.getAddress() != null) + { balance = getBalanceForAddress(balanceListener.getAddress()); + } else + { balance = getWalletBalance(); + } balanceListener.onBalanceChanged(balance); } @@ -667,7 +697,11 @@ public class WalletFacade // 1. step: deposit tx // Offerer creates the 2of3 multiSig deposit tx with his unsigned input and change output - public Transaction offererCreatesMSTxAndAddPayment(BigInteger offererInputAmount, String offererPubKey, String takerPubKey, String arbitratorPubKey, String tradeId) throws InsufficientMoneyException + public Transaction offererCreatesMSTxAndAddPayment(BigInteger offererInputAmount, + String offererPubKey, + String takerPubKey, + String arbitratorPubKey, + String tradeId) throws InsufficientMoneyException { log.debug("offererCreatesMSTxAndAddPayment"); log.trace("inputs: "); @@ -724,8 +758,7 @@ public class WalletFacade String takerPubKey, String arbitratorPubKey, String offerersPartialDepositTxAsHex, - String tradeId - ) throws InsufficientMoneyException + String tradeId) throws InsufficientMoneyException { log.debug("takerAddPaymentAndSignTx"); log.trace("inputs: "); @@ -782,7 +815,9 @@ public class WalletFacade // Now we add the inputs and outputs from our temp tx and change the multiSig amount to the correct value tx.addInput(tempTx.getInput(0)); if (tempTx.getOutputs().size() == 2) + { tx.addOutput(tempTx.getOutput(1)); + } // We add the btc tx fee to the msOutputAmount and apply the change to the multiSig output msOutputAmount = msOutputAmount.add(FeePolicy.TX_FEE); @@ -791,7 +826,9 @@ public class WalletFacade // Now we sign our input TransactionInput input = tx.getInput(1); if (input == null || input.getConnectedOutput() == null) + { log.error("input or input.getConnectedOutput() is null: " + input); + } Script scriptPubKey = input.getConnectedOutput().getScriptPubKey(); ECKey sigKey = input.getOutpoint().getConnectedKey(wallet); @@ -799,11 +836,17 @@ public class WalletFacade ECKey.ECDSASignature ecSig = sigKey.sign(hash); TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false); if (scriptPubKey.isSentToRawPubKey()) + { input.setScriptSig(ScriptBuilder.createInputScript(txSig)); + } else if (scriptPubKey.isSentToAddress()) + { input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey)); + } else + { throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey); + } log.trace("check if it can be correctly spent for input 1"); input.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false); @@ -862,7 +905,8 @@ public class WalletFacade // add input Transaction offerersFirstTxConnOut = wallet.getTransaction(offerersFirstTx.getInput(0).getOutpoint().getHash()); // pass that around! TransactionOutPoint offerersFirstTxOutPoint = new TransactionOutPoint(params, offererTxOutIndex, offerersFirstTxConnOut); - //TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, offerersFirstTx.getInput(0).getScriptBytes(), offerersFirstTxOutPoint); // pass that around! getScriptBytes = empty bytes array + //TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, offerersFirstTx.getInput(0).getScriptBytes(), offerersFirstTxOutPoint); // pass that around! getScriptBytes = + // empty bytes array TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, new byte[]{}, offerersFirstTxOutPoint); // pass that around! getScriptBytes = empty bytes array offerersFirstTxInput.setParent(tx); tx.addInput(offerersFirstTxInput); @@ -884,9 +928,13 @@ public class WalletFacade // add outputs from takers tx, they are already correct tx.addOutput(takersSignedTx.getOutput(0)); if (takersSignedTx.getOutputs().size() > 1) + { tx.addOutput(takersSignedTx.getOutput(1)); + } if (takersSignedTx.getOutputs().size() == 3) + { tx.addOutput(takersSignedTx.getOutput(2)); + } printInputs("tx", tx); log.trace("tx = " + tx); @@ -895,7 +943,9 @@ public class WalletFacade // sign the input TransactionInput input = tx.getInput(0); if (input == null || input.getConnectedOutput() == null) + { log.error("input or input.getConnectedOutput() is null: " + input); + } Script scriptPubKey = input.getConnectedOutput().getScriptPubKey(); ECKey sigKey = input.getOutpoint().getConnectedKey(wallet); @@ -903,11 +953,17 @@ public class WalletFacade ECKey.ECDSASignature ecSig = sigKey.sign(hash); TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false); if (scriptPubKey.isSentToRawPubKey()) + { input.setScriptSig(ScriptBuilder.createInputScript(txSig)); + } else if (scriptPubKey.isSentToAddress()) + { input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey)); + } else + { throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey); + } input.getScriptSig().correctlySpends(tx, 0, scriptPubKey, false); log.trace("check if it can be correctly spent for input 0 OK"); @@ -1089,11 +1145,7 @@ public class WalletFacade } - private Transaction createPayoutTx(String depositTxAsHex, - BigInteger offererPaybackAmount, - BigInteger takerPaybackAmount, - String offererAddress, - String takerAddress) throws AddressFormatException + private Transaction createPayoutTx(String depositTxAsHex, BigInteger offererPaybackAmount, BigInteger takerPaybackAmount, String offererAddress, String takerAddress) throws AddressFormatException { log.trace("createPayoutTx"); log.trace("inputs: "); @@ -1116,10 +1168,16 @@ public class WalletFacade private void printInputs(String tracePrefix, Transaction tx) { for (TransactionInput input : tx.getInputs()) + { if (input.getConnectedOutput() != null) + { log.trace(tracePrefix + " input value : " + BtcFormatter.formatSatoshis(input.getConnectedOutput().getValue())); + } else + { log.trace(tracePrefix + ": " + "Transaction already has inputs but we don't have the connected outputs, so we don't know the value."); + } + } } @@ -1153,13 +1211,17 @@ public class WalletFacade private void onProgressInUserThread(double percent, int blocksSoFar, final Date date) { for (DownloadListener downloadListener : downloadListeners) + { downloadListener.progress(percent); + } } private void onDoneDownloadInUserThread() { for (DownloadListener downloadListener : downloadListeners) + { downloadListener.doneDownload(); + } } } diff --git a/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java b/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java index b967cb65a6..7081a8d87a 100644 --- a/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java +++ b/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java @@ -48,7 +48,9 @@ public class GuiceFXMLLoader extends FXMLLoader private void setupControllerFactory() { if (GuiceFXMLLoader.injector != null) + { setControllerFactory(new GuiceControllerFactory(GuiceFXMLLoader.injector)); + } } } diff --git a/src/main/java/io/bitsquare/gui/MainController.java b/src/main/java/io/bitsquare/gui/MainController.java index 8ed74829dd..c86cdf7f2d 100644 --- a/src/main/java/io/bitsquare/gui/MainController.java +++ b/src/main/java/io/bitsquare/gui/MainController.java @@ -149,7 +149,9 @@ public class MainController implements Initializable, NavigationController private ChildController loadView(NavigationItem navigationItem) { if (childController != null) + { childController.cleanup(); + } final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle()); try @@ -205,7 +207,9 @@ public class MainController implements Initializable, NavigationController NavigationItem selectedNavigationItem = (NavigationItem) storage.read(this, "selectedNavigationItem"); if (selectedNavigationItem == null) + { selectedNavigationItem = NavigationItem.HOME; + } navigateToView(selectedNavigationItem); } @@ -268,7 +272,9 @@ public class MainController implements Initializable, NavigationController childController = loadView(navigationItem); if (childController instanceof MarketController) + { ((MarketController) childController).setDirection(navigationItem == NavigationItem.BUY ? Direction.BUY : Direction.SELL); + } storage.write(this, "selectedNavigationItem", navigationItem); diff --git a/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java b/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java index f704736ddf..02aed20303 100644 --- a/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java +++ b/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java @@ -104,7 +104,9 @@ public class ArbitratorOverviewController implements Initializable, ChildControl public ChildController navigateToView(NavigationItem navigationItem) { if (arbitratorProfileController != null) + { arbitratorProfileController.cleanup(); + } final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle()); try diff --git a/src/main/java/io/bitsquare/gui/arbitrators/profile/ArbitratorProfileController.java b/src/main/java/io/bitsquare/gui/arbitrators/profile/ArbitratorProfileController.java index ecaa1c6f40..b11ea135f6 100644 --- a/src/main/java/io/bitsquare/gui/arbitrators/profile/ArbitratorProfileController.java +++ b/src/main/java/io/bitsquare/gui/arbitrators/profile/ArbitratorProfileController.java @@ -28,8 +28,8 @@ public class ArbitratorProfileController implements Initializable, ChildControll @FXML private Label nameLabel; @FXML - private TextField nameTextField, languagesTextField, reputationTextField, maxTradeVolumeTextField, passiveServiceFeeTextField, - arbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField; + private TextField nameTextField, languagesTextField, reputationTextField, maxTradeVolumeTextField, passiveServiceFeeTextField, arbitrationFeeTextField, methodsTextField, + idVerificationsTextField, webPageTextField; @FXML private TextArea descriptionTextArea; diff --git a/src/main/java/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationController.java b/src/main/java/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationController.java index e186063b7d..d55c0c3c4a 100644 --- a/src/main/java/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationController.java +++ b/src/main/java/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationController.java @@ -79,8 +79,8 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon @FXML private ComboBox idVerificationsComboBox; @FXML - private TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField, passiveServiceFeeTextField, minPassiveServiceFeeTextField, - arbitrationFeeTextField, minArbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField, collateralAddressTextField, balanceTextField; + private TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField, passiveServiceFeeTextField, minPassiveServiceFeeTextField, arbitrationFeeTextField, + minArbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField, collateralAddressTextField, balanceTextField; @FXML private TextArea descriptionTextArea; @FXML @@ -361,11 +361,11 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon private void setupPayCollateralScreen() { infoLabel.setText("You need to pay 10 x the max. trading volume as collateral.\n\n" + - "That payment will be locked into a MultiSig fund and be refunded when you leave the arbitration pool.\n" + - "In case of fraud (collusion, not fulfilling the min. dispute quality requirements) you will lose your collateral.\n" + - "If you have a negative feedback from your clients you will lose a part of the collateral,\n" + - "depending on the overall relation of negative to positive ratings you received after a dispute resolution.\n\n" + - "Please pay in " + arbitrator.getMaxTradeVolume() * 10 + " BTC"); + "That payment will be locked into a MultiSig fund and be refunded when you leave the arbitration pool.\n" + + "In case of fraud (collusion, not fulfilling the min. dispute quality requirements) you will lose your collateral.\n" + + "If you have a negative feedback from your clients you will lose a part of the collateral,\n" + + "depending on the overall relation of negative to positive ratings you received after a dispute resolution.\n\n" + + "Please pay in " + arbitrator.getMaxTradeVolume() * 10 + " BTC"); String collateralAddress = walletFacade.getRegistrationAddressInfo() != null ? walletFacade.getRegistrationAddressInfo().toString() : ""; @@ -467,7 +467,11 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon try { BitSquareValidator.textFieldsNotEmptyWithReset(nameTextField, idTypeTextField, languagesTextField, methodsTextField, idVerificationsTextField); - BitSquareValidator.textFieldsHasDoubleValueWithReset(maxTradeVolumeTextField, passiveServiceFeeTextField, minPassiveServiceFeeTextField, arbitrationFeeTextField, minArbitrationFeeTextField); + BitSquareValidator.textFieldsHasDoubleValueWithReset(maxTradeVolumeTextField, + passiveServiceFeeTextField, + minPassiveServiceFeeTextField, + arbitrationFeeTextField, + minArbitrationFeeTextField); String pubKeyAsHex = walletFacade.getArbitratorDepositAddressInfo().getPubKeyAsHexString(); String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey()); @@ -483,20 +487,20 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon String description = descriptionTextArea.getText(); return new Arbitrator(pubKeyAsHex, - messagePubKeyAsHex, - name, - idType, - languageList, - new Reputation(), - maxTradeVolume, - passiveServiceFee, - minPassiveServiceFee, - arbitrationFee, - minArbitrationFee, - methodList, - idVerificationList, - webUrl, - description); + messagePubKeyAsHex, + name, + idType, + languageList, + new Reputation(), + maxTradeVolume, + passiveServiceFee, + minPassiveServiceFee, + arbitrationFee, + minArbitrationFee, + methodList, + idVerificationList, + webUrl, + description); } catch (BitSquareValidator.ValidationException e) { return null; diff --git a/src/main/java/io/bitsquare/gui/components/LazyLoadingTabPane.java b/src/main/java/io/bitsquare/gui/components/LazyLoadingTabPane.java index a0d63421d1..56afa1cca3 100644 --- a/src/main/java/io/bitsquare/gui/components/LazyLoadingTabPane.java +++ b/src/main/java/io/bitsquare/gui/components/LazyLoadingTabPane.java @@ -42,7 +42,9 @@ public class LazyLoadingTabPane extends TabPane public void initialize(NavigationController navigationController, Storage storage, String... tabContentFXMLUrls) { if (tabContentFXMLUrls.length == 0) + { throw new IllegalArgumentException("No tabContentFXMLUrls defined"); + } this.tabContentFXMLUrls = tabContentFXMLUrls; this.navigationController = navigationController; @@ -59,7 +61,9 @@ public class LazyLoadingTabPane extends TabPane Object indexObject = storage.read(storageId); log.trace("saved index" + indexObject); if (indexObject != null) + { selectionModel.select((int) indexObject); + } } else { @@ -72,7 +76,9 @@ public class LazyLoadingTabPane extends TabPane public void cleanup() { if (childController != null) + { childController.cleanup(); + } } @@ -97,7 +103,9 @@ public class LazyLoadingTabPane extends TabPane if (index < tabContentFXMLUrls.length && index >= 0) { if (childController != null) + { ((Hibernate) childController).sleep(); + } Node view = null; if (index < views.size()) diff --git a/src/main/java/io/bitsquare/gui/components/ValidatedTextField.java b/src/main/java/io/bitsquare/gui/components/ValidatedTextField.java index e9070e6236..8e7d6ed7bc 100644 --- a/src/main/java/io/bitsquare/gui/components/ValidatedTextField.java +++ b/src/main/java/io/bitsquare/gui/components/ValidatedTextField.java @@ -148,12 +148,12 @@ public class ValidatedTextField extends TextField { if (t1) { -// setStyle("-fx-font-weight: bold; -fx-text-fill: red;"); + // setStyle("-fx-font-weight: bold; -fx-text-fill: red;"); setEffect(invalidEffect); } else { -// setStyle("-fx-font-weight: normal; -fx-text-fill: inherit;"); + // setStyle("-fx-font-weight: normal; -fx-text-fill: inherit;"); setEffect(null); } } diff --git a/src/main/java/io/bitsquare/gui/components/confidence/ConfidenceProgressIndicator.java b/src/main/java/io/bitsquare/gui/components/confidence/ConfidenceProgressIndicator.java index 036a2d7b3d..345988f626 100644 --- a/src/main/java/io/bitsquare/gui/components/confidence/ConfidenceProgressIndicator.java +++ b/src/main/java/io/bitsquare/gui/components/confidence/ConfidenceProgressIndicator.java @@ -91,8 +91,7 @@ public class ConfidenceProgressIndicator extends Control * Pseudoclass indicating this is a determinate (i.e., progress can be * determined) progress indicator. */ - private static final PseudoClass PSEUDO_CLASS_DETERMINATE = - PseudoClass.getPseudoClass("determinate"); + private static final PseudoClass PSEUDO_CLASS_DETERMINATE = PseudoClass.getPseudoClass("determinate"); /*************************************************************************** * * * Properties * @@ -102,8 +101,7 @@ public class ConfidenceProgressIndicator extends Control * Pseudoclass indicating this is an indeterminate (i.e., progress cannot * be determined) progress indicator. */ - private static final PseudoClass PSEUDO_CLASS_INDETERMINATE = - PseudoClass.getPseudoClass("indeterminate"); + private static final PseudoClass PSEUDO_CLASS_INDETERMINATE = PseudoClass.getPseudoClass("indeterminate"); /** * A flag indicating whether it is possible to determine the progress * of the ProgressIndicator. Typically indeterminate progress bars are diff --git a/src/main/java/io/bitsquare/gui/components/confidence/skin/ConfidenceProgressIndicatorSkin.java b/src/main/java/io/bitsquare/gui/components/confidence/skin/ConfidenceProgressIndicatorSkin.java index a3433ac967..5824dd0d31 100644 --- a/src/main/java/io/bitsquare/gui/components/confidence/skin/ConfidenceProgressIndicatorSkin.java +++ b/src/main/java/io/bitsquare/gui/components/confidence/skin/ConfidenceProgressIndicatorSkin.java @@ -88,37 +88,39 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase getCssMetaData() - { - return StyleableProperties.INDETERMINATE_SEGMENT_COUNT; - } - }; + @Override + public CssMetaData getCssMetaData() + { + return StyleableProperties.INDETERMINATE_SEGMENT_COUNT; + } + }; /** * True if the progress indicator should rotate as well as animate opacity. */ @@ -128,7 +130,10 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase progressColor = - new StyleableObjectProperty(null) + private final ObjectProperty progressColor = new StyleableObjectProperty(null) + { + + @Override + public void set(Paint newProgressColor) + { + final Paint color = (newProgressColor instanceof Color) ? newProgressColor : null; + super.set(color); + } + + @Override + protected void invalidated() + { + if (spinner != null) { - - @Override - public void set(Paint newProgressColor) - { - final Paint color = (newProgressColor instanceof Color) - ? newProgressColor - : null; - super.set(color); - } - - @Override - protected void invalidated() - { - if (spinner != null) spinner.setFillOverride(get()); - if (determinateIndicator != null) determinateIndicator.setFillOverride(get()); - } + spinner.setFillOverride(get()); + } + if (determinateIndicator != null) + { + determinateIndicator.setFillOverride(get()); + } + } - @Override - public Object getBean() - { - return ConfidenceProgressIndicatorSkin.this; - } + @Override + public Object getBean() + { + return ConfidenceProgressIndicatorSkin.this; + } - @Override - public String getName() - { - return "progressColorProperty"; - } + @Override + public String getName() + { + return "progressColorProperty"; + } - @Override - public CssMetaData getCssMetaData() - { - return StyleableProperties.PROGRESS_COLOR; - } - }; + @Override + public CssMetaData getCssMetaData() + { + return StyleableProperties.PROGRESS_COLOR; + } + }; private boolean timelineNulled = false; /** @@ -338,8 +346,7 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase shiftColors())); + keyFrames.add(new KeyFrame(Duration.millis(i), event -> shiftColors())); } indeterminateTimeline.getKeyFrames().setAll(keyFrames); } @@ -750,7 +751,10 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase> STYLEABLES; - private static final CssMetaData PROGRESS_COLOR = - new CssMetaData("-fx-progress-color", - PaintConverter.getInstance(), null) - { + private static final CssMetaData PROGRESS_COLOR = new CssMetaData("-fx-progress-color", + PaintConverter.getInstance(), + null) + { - @Override - public boolean isSettable(ConfidenceProgressIndicator n) - { - final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin(); - return skin.progressColor == null || - !skin.progressColor.isBound(); - } + @Override + public boolean isSettable(ConfidenceProgressIndicator n) + { + final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin(); + return skin.progressColor == null || !skin.progressColor.isBound(); + } - @Override - public StyleableProperty getStyleableProperty(ConfidenceProgressIndicator n) - { - final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin(); - return (StyleableProperty) skin.progressColor; - } - }; + @Override + public StyleableProperty getStyleableProperty(ConfidenceProgressIndicator n) + { + final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin(); + return (StyleableProperty) skin.progressColor; + } + }; - private static final CssMetaData INDETERMINATE_SEGMENT_COUNT = - new CssMetaData("-fx-indeterminate-segment-count", - SizeConverter.getInstance(), 8) - { + private static final CssMetaData INDETERMINATE_SEGMENT_COUNT = new CssMetaData("-fx-indeterminate-segment-count", + SizeConverter.getInstance(), + 8) + { - @Override - public void set(ConfidenceProgressIndicator node, Number value, StyleOrigin origin) - { - super.set(node, value.intValue(), origin); - } + @Override + public void set(ConfidenceProgressIndicator node, Number value, StyleOrigin origin) + { + super.set(node, value.intValue(), origin); + } - @Override - public boolean isSettable(ConfidenceProgressIndicator n) - { - final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin(); - return skin.indeterminateSegmentCount == null || - !skin.indeterminateSegmentCount.isBound(); - } + @Override + public boolean isSettable(ConfidenceProgressIndicator n) + { + final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin(); + return skin.indeterminateSegmentCount == null || !skin.indeterminateSegmentCount.isBound(); + } - @Override - public StyleableProperty getStyleableProperty(ConfidenceProgressIndicator n) - { - final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin(); - return (StyleableProperty) skin.indeterminateSegmentCount; - } - }; + @Override + public StyleableProperty getStyleableProperty(ConfidenceProgressIndicator n) + { + final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin(); + return (StyleableProperty) skin.indeterminateSegmentCount; + } + }; - private static final CssMetaData SPIN_ENABLED = - new CssMetaData("-fx-spin-enabled", - BooleanConverter.getInstance(), Boolean.FALSE) - { + private static final CssMetaData SPIN_ENABLED = new CssMetaData("-fx-spin-enabled", + BooleanConverter.getInstance(), + Boolean.FALSE) + { - @Override - public boolean isSettable(ConfidenceProgressIndicator node) - { - final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) node.getSkin(); - return skin.spinEnabled == null || !skin.spinEnabled.isBound(); - } + @Override + public boolean isSettable(ConfidenceProgressIndicator node) + { + final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) node.getSkin(); + return skin.spinEnabled == null || !skin.spinEnabled.isBound(); + } - @Override - public StyleableProperty getStyleableProperty(ConfidenceProgressIndicator node) - { - final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) node.getSkin(); - return (StyleableProperty) skin.spinEnabled; - } - }; + @Override + public StyleableProperty getStyleableProperty(ConfidenceProgressIndicator node) + { + final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) node.getSkin(); + return (StyleableProperty) skin.spinEnabled; + } + }; static { diff --git a/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepBar.java b/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepBar.java index b34ef2844f..105c00aefc 100644 --- a/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepBar.java +++ b/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepBar.java @@ -37,7 +37,9 @@ public class ProcessStepBar extends Control { this.processStepItems = processStepItems; if (getSkin() != null) + { ((ProcessStepBarSkin) getSkin()).dataChanged(); + } } public void next() diff --git a/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepBarSkin.java b/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepBarSkin.java index 99ceee3017..a5c2c2ed63 100644 --- a/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepBarSkin.java +++ b/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepBarSkin.java @@ -52,7 +52,9 @@ class ProcessStepBarSkin extends BehaviorSkinBase, Behavior getChildren().add(labelWithBorder); labelWithBorders.add(labelWithBorder); if (i == 0) + { currentLabelWithBorder = prevLabelWithBorder = labelWithBorder; + } i++; } @@ -88,7 +90,9 @@ class ProcessStepBarSkin extends BehaviorSkinBase, Behavior double newHeight = snapSize(node.prefHeight(-1) + 10); if (i > 0) + { x = snapPosition(x - ((LabelWithBorder) node).getArrowWidth()); + } x = snapPosition(x); y = snapPosition(y); @@ -124,15 +128,13 @@ class ProcessStepBarSkin extends BehaviorSkinBase, Behavior this.setShape(createButtonShape()); - BorderStroke borderStroke = new BorderStroke(Color.LIGHTGRAY, BorderStrokeStyle.SOLID, null, - new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY); + BorderStroke borderStroke = new BorderStroke(Color.LIGHTGRAY, BorderStrokeStyle.SOLID, null, new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY); this.setBorder(new Border(borderStroke)); } public void select() { - BorderStroke borderStroke = new BorderStroke(processStepItem.getColor(), BorderStrokeStyle.SOLID, null, - new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY); + BorderStroke borderStroke = new BorderStroke(processStepItem.getColor(), BorderStrokeStyle.SOLID, null, new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY); this.setBorder(new Border(borderStroke)); setTextFill(processStepItem.getColor()); } diff --git a/src/main/java/io/bitsquare/gui/funds/withdrawal/WithdrawalController.java b/src/main/java/io/bitsquare/gui/funds/withdrawal/WithdrawalController.java index 32614dcc3b..b4c0fc3eee 100644 --- a/src/main/java/io/bitsquare/gui/funds/withdrawal/WithdrawalController.java +++ b/src/main/java/io/bitsquare/gui/funds/withdrawal/WithdrawalController.java @@ -160,7 +160,10 @@ public class WithdrawalController implements Initializable, ChildController, Hib public void onSuccess(@javax.annotation.Nullable Transaction transaction) { BitSquareValidator.resetTextFields(withdrawFromTextField, withdrawToTextField, amountTextField, changeAddressTextField); - if (transaction != null) log.info("onWithdraw onSuccess txid:" + transaction.getHashAsString()); + if (transaction != null) + { + log.info("onWithdraw onSuccess txid:" + transaction.getHashAsString()); + } } @Override diff --git a/src/main/java/io/bitsquare/gui/funds/withdrawal/WithdrawalListItem.java b/src/main/java/io/bitsquare/gui/funds/withdrawal/WithdrawalListItem.java index 6405d96ce6..aa0124a672 100644 --- a/src/main/java/io/bitsquare/gui/funds/withdrawal/WithdrawalListItem.java +++ b/src/main/java/io/bitsquare/gui/funds/withdrawal/WithdrawalListItem.java @@ -126,9 +126,13 @@ public class WithdrawalListItem return "Registration fee"; case TRADE: if (addressEntry.getTradeId() != null) + { return "Trade ID: " + addressEntry.getTradeId(); + } else + { return "Trade (not used yet)"; + } case ARBITRATOR_DEPOSIT: return "Arbitration deposit"; } diff --git a/src/main/java/io/bitsquare/gui/home/HomeController.java b/src/main/java/io/bitsquare/gui/home/HomeController.java index 1582089921..91f9537857 100644 --- a/src/main/java/io/bitsquare/gui/home/HomeController.java +++ b/src/main/java/io/bitsquare/gui/home/HomeController.java @@ -50,7 +50,9 @@ public class HomeController implements Initializable, ChildController, Navigatio public ChildController navigateToView(NavigationItem navigationItem) { if (arbitratorRegistrationController != null) + { arbitratorRegistrationController.cleanup(); + } final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle()); try diff --git a/src/main/java/io/bitsquare/gui/market/MarketController.java b/src/main/java/io/bitsquare/gui/market/MarketController.java index c4c7d10798..30e2f64a2c 100644 --- a/src/main/java/io/bitsquare/gui/market/MarketController.java +++ b/src/main/java/io/bitsquare/gui/market/MarketController.java @@ -60,7 +60,9 @@ public class MarketController implements Initializable, NavigationController, Ch childController.setNavigationController(this); if (childController instanceof OrderBookController) + { orderBookController = (OrderBookController) childController; + } String tabLabel; switch (navigationItem) @@ -125,7 +127,9 @@ public class MarketController implements Initializable, NavigationController, Ch { tabPane.getSelectionModel().select(0); if (orderBookController != null) + { orderBookController.setDirection(direction); + } } } diff --git a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java index 8673f7775d..9efb9b3898 100644 --- a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java +++ b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java @@ -63,8 +63,8 @@ public class CreateOfferController implements Initializable, ChildController, Hi @FXML private Button placeOfferButton, closeButton; @FXML - private TextField collateralTextField, minAmountTextField, bankAccountTypeTextField, bankAccountCurrencyTextField, bankAccountCountyTextField, - acceptedCountriesTextField, acceptedLanguagesTextField, feeLabel, txTextField; + private TextField collateralTextField, minAmountTextField, bankAccountTypeTextField, bankAccountCurrencyTextField, bankAccountCountyTextField, acceptedCountriesTextField, + acceptedLanguagesTextField, feeLabel, txTextField; @FXML private ConfidenceProgressIndicator progressIndicator; @@ -188,18 +188,18 @@ public class CreateOfferController implements Initializable, ChildController, Hi if (user.getCurrentBankAccount() != null) { offer = new Offer(user.getMessagePubKeyAsHex(), - direction, - BitSquareConverter.stringToDouble(priceTextField.getText()), - BtcFormatter.stringValueToSatoshis(amountTextField.getText()), - BtcFormatter.stringValueToSatoshis(minAmountTextField.getText()), - user.getCurrentBankAccount().getBankAccountType(), - user.getCurrentBankAccount().getCurrency(), - user.getCurrentBankAccount().getCountry(), - user.getCurrentBankAccount().getUid(), - arbitrator, - collateral, - settings.getAcceptedCountries(), - settings.getAcceptedLanguageLocales()); + direction, + BitSquareConverter.stringToDouble(priceTextField.getText()), + BtcFormatter.stringValueToSatoshis(amountTextField.getText()), + BtcFormatter.stringValueToSatoshis(minAmountTextField.getText()), + user.getCurrentBankAccount().getBankAccountType(), + user.getCurrentBankAccount().getCurrency(), + user.getCurrentBankAccount().getCountry(), + user.getCurrentBankAccount().getUid(), + arbitrator, + collateral, + settings.getAcceptedCountries(), + settings.getAcceptedLanguageLocales()); try diff --git a/src/main/java/io/bitsquare/gui/market/orderbook/OrderBookController.java b/src/main/java/io/bitsquare/gui/market/orderbook/OrderBookController.java index 00261ba85d..d68feb12e4 100644 --- a/src/main/java/io/bitsquare/gui/market/orderbook/OrderBookController.java +++ b/src/main/java/io/bitsquare/gui/market/orderbook/OrderBookController.java @@ -220,7 +220,8 @@ public class OrderBookController implements Initializable, ChildController } else { - Action response = Popups.openErrorPopup("Registration fee not confirmed yet", "The registration fee transaction has not been confirmed yet in the blockchain. Please wait until it has at least 1 confirmation."); + Action response = Popups.openErrorPopup("Registration fee not confirmed yet", + "The registration fee transaction has not been confirmed yet in the blockchain. Please wait until it has at least 1 confirmation."); if (response == Dialog.Actions.OK) { MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS); @@ -229,7 +230,8 @@ public class OrderBookController implements Initializable, ChildController } else { - Action response = Popups.openErrorPopup("Missing registration fee", "You have not funded the full registration fee of " + BtcFormatter.formatSatoshis(FeePolicy.ACCOUNT_REGISTRATION_FEE) + " BTC."); + Action response = Popups.openErrorPopup("Missing registration fee", + "You have not funded the full registration fee of " + BtcFormatter.formatSatoshis(FeePolicy.ACCOUNT_REGISTRATION_FEE) + " BTC."); if (response == Dialog.Actions.OK) { MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS); @@ -249,10 +251,17 @@ public class OrderBookController implements Initializable, ChildController if (selectedIndex >= 0) { Dialogs.CommandLink settingsCommandLink = new Dialogs.CommandLink("Open settings", "You need to configure your settings before you can actively trade."); - Dialogs.CommandLink depositFeeCommandLink = new Dialogs.CommandLink("Deposit funds", "You need to pay the registration fee before you can actively trade. That is needed as prevention against fraud."); - Dialogs.CommandLink sendRegistrationCommandLink = new Dialogs.CommandLink("Publish registration", "When settings are configured and the fee deposit is done your registration transaction will be published to the Bitcoin \nnetwork."); + Dialogs.CommandLink depositFeeCommandLink = new Dialogs.CommandLink("Deposit funds", + "You need to pay the registration fee before you can actively trade. That is needed as prevention against fraud."); + Dialogs.CommandLink sendRegistrationCommandLink = new Dialogs.CommandLink("Publish registration", + "When settings are configured and the fee deposit is done your registration transaction will be published to " + + "the Bitcoin \nnetwork."); List commandLinks = Arrays.asList(settingsCommandLink, depositFeeCommandLink, sendRegistrationCommandLink); - Action registrationMissingAction = Popups.openRegistrationMissingPopup("Not registered yet", "Please follow these steps:", "You need to register before you can place an offer.", commandLinks, selectedIndex); + Action registrationMissingAction = Popups.openRegistrationMissingPopup("Not registered yet", + "Please follow these steps:", + "You need to register before you can place an offer.", + commandLinks, + selectedIndex); if (registrationMissingAction == settingsCommandLink) { MainController.GET_INSTANCE().navigateToView(NavigationItem.SETTINGS); @@ -276,7 +285,10 @@ public class OrderBookController implements Initializable, ChildController public void onSuccess(@javax.annotation.Nullable Transaction transaction) { log.debug("payRegistrationFee onSuccess"); - if (transaction != null) log.info("payRegistrationFee onSuccess tx id:" + transaction.getHashAsString()); + if (transaction != null) + { + log.info("payRegistrationFee onSuccess tx id:" + transaction.getHashAsString()); + } } @Override @@ -289,8 +301,13 @@ public class OrderBookController implements Initializable, ChildController { walletFacade.payRegistrationFee(user.getStringifiedBankAccounts(), callback); if (walletFacade.getRegistrationAddressInfo() != null) + { user.setAccountID(walletFacade.getRegistrationAddressInfo().toString()); - if (messageFacade != null && messageFacade.getPubKey() != null) user.setMessagePubKeyAsHex(DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey())); + } + if (messageFacade != null && messageFacade.getPubKey() != null) + { + user.setMessagePubKeyAsHex(DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey())); + } storage.write(user.getClass().getName(), user); } catch (InsufficientMoneyException e1) @@ -308,7 +325,9 @@ public class OrderBookController implements Initializable, ChildController { ChildController nextController = navigationController.navigateToView(NavigationItem.CREATE_OFFER); if (nextController != null) + { ((CreateOfferController) nextController).setOrderBookFilter(orderBookFilter); + } } else { @@ -333,12 +352,18 @@ public class OrderBookController implements Initializable, ChildController BigInteger requestedAmount; if (!"".equals(amount.getText())) + { requestedAmount = BtcFormatter.stringValueToSatoshis(amount.getText()); + } else + { requestedAmount = offer.getAmount(); + } if (takerOfferController != null) + { takerOfferController.initWithData(offer, requestedAmount); + } } else { @@ -359,16 +384,22 @@ public class OrderBookController implements Initializable, ChildController orderBookTable.sort(); if (orderBookTable.getItems() != null) + { createOfferButton.setDefaultButton(orderBookTable.getItems().isEmpty()); + } } private void setupPolling() { pollingTimer = Utilities.setInterval(1000, (animationTimer) -> { if (user.getCurrentBankAccount() != null) + { messageFacade.getDirtyFlag(user.getCurrentBankAccount().getCurrency()); + } else + { messageFacade.getDirtyFlag(CurrencyUtil.getDefaultCurrency()); + } return null; }); diff --git a/src/main/java/io/bitsquare/gui/market/trade/TakerOfferController.java b/src/main/java/io/bitsquare/gui/market/trade/TakerOfferController.java index e54c97c0e5..c05699e802 100644 --- a/src/main/java/io/bitsquare/gui/market/trade/TakerOfferController.java +++ b/src/main/java/io/bitsquare/gui/market/trade/TakerOfferController.java @@ -17,8 +17,8 @@ import io.bitsquare.msg.MessageFacade; import io.bitsquare.trade.Offer; import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trading; -import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocol; -import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocolListener; +import io.bitsquare.trade.protocol.taker.ProtocolForTakerAsSeller; +import io.bitsquare.trade.protocol.taker.ProtocolForTakerAsSellerListener; import java.math.BigInteger; import java.net.URL; import java.util.ResourceBundle; @@ -53,9 +53,9 @@ public class TakerOfferController implements Initializable, ChildController @FXML private ValidatedTextField amountTextField; @FXML - private TextField priceTextField, volumeTextField, collateralTextField, feeTextField, totalTextField, bankAccountTypeTextField, countryTextField, - arbitratorsTextField, supportedLanguagesTextField, supportedCountriesTextField, depositTxIdTextField, summaryPaidTextField, summaryReceivedTextField, summaryFeesTextField, - summaryCollateralTextField, summaryDepositTxIdTextField, summaryPayoutTxIdTextField; + private TextField priceTextField, volumeTextField, collateralTextField, feeTextField, totalTextField, bankAccountTypeTextField, countryTextField, arbitratorsTextField, + supportedLanguagesTextField, supportedCountriesTextField, depositTxIdTextField, summaryPaidTextField, summaryReceivedTextField, summaryFeesTextField, summaryCollateralTextField, + summaryDepositTxIdTextField, summaryPayoutTxIdTextField; @FXML private Label infoLabel, headLineLabel; @FXML @@ -84,7 +84,9 @@ public class TakerOfferController implements Initializable, ChildController this.requestedAmount = requestedAmount.compareTo(BigInteger.ZERO) == 0 ? offer.getAmount() : requestedAmount; if (amountTextField != null) + { applyData(); + } } /////////////////////////////////////////////////////////////////////////////////////////// @@ -172,68 +174,67 @@ public class TakerOfferController implements Initializable, ChildController { takeOfferButton.setDisable(true); amountTextField.setEditable(false); - trading.takeOffer(amount, offer, new TakerAsSellerProtocolListener() - { - @Override - public void onDepositTxPublished(String depositTxId) - { - setDepositTxId(depositTxId); - accordion.setExpandedPane(waitBankTxTitledPane); - infoLabel.setText("Deposit transaction published by offerer.\n" + - "As soon as the offerer starts the \n" + - "Bank transfer, you will get informed."); - depositTxIdTextField.setText(depositTxId); - } + trading.takeOffer(amount, offer, new ProtocolForTakerAsSellerListener() + { + @Override + public void onDepositTxPublished(String depositTxId) + { + setDepositTxId(depositTxId); + accordion.setExpandedPane(waitBankTxTitledPane); + infoLabel.setText("Deposit transaction published by offerer.\n" + + "As soon as the offerer starts the \n" + + "Bank transfer, you will get informed."); + depositTxIdTextField.setText(depositTxId); + } - @Override - public void onBankTransferInited(String tradeId) - { - setTradeId(tradeId); - headLineLabel.setText("Bank transfer inited"); - infoLabel.setText("Check your bank account and continue \n" + - "when you have received the money."); - receivedFiatButton.setDisable(false); - } + @Override + public void onBankTransferInited(String tradeId) + { + setTradeId(tradeId); + headLineLabel.setText("Bank transfer inited"); + infoLabel.setText("Check your bank account and continue \n" + "when you have received the money."); + receivedFiatButton.setDisable(false); + } - @Override - public void onPayoutTxPublished(Trade trade, String payoutTxId) - { - accordion.setExpandedPane(summaryTitledPane); - summaryPaidTextField.setText(BtcFormatter.formatSatoshis(trade.getTradeAmount())); - summaryReceivedTextField.setText(BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()))); - summaryFeesTextField.setText(BtcFormatter.formatSatoshis(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE))); - summaryCollateralTextField.setText(BtcFormatter.formatSatoshis(trade.getCollateralAmount())); - summaryDepositTxIdTextField.setText(depositTxId); - summaryPayoutTxIdTextField.setText(payoutTxId); - } + @Override + public void onPayoutTxPublished(Trade trade, String payoutTxId) + { + accordion.setExpandedPane(summaryTitledPane); + summaryPaidTextField.setText(BtcFormatter.formatSatoshis(trade.getTradeAmount())); + summaryReceivedTextField.setText(BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()))); + summaryFeesTextField.setText(BtcFormatter.formatSatoshis(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE))); + summaryCollateralTextField.setText(BtcFormatter.formatSatoshis(trade.getCollateralAmount())); + summaryDepositTxIdTextField.setText(depositTxId); + summaryPayoutTxIdTextField.setText(payoutTxId); + } - @Override - public void onFault(Throwable throwable, TakerAsSellerProtocol.State state) - { - log.error("Error while executing trade process at state: " + state + " / " + throwable); - Popups.openErrorPopup("Error while executing trade process", "Error while executing trade process at state: " + state + " / " + throwable); - } + @Override + public void onFault(Throwable throwable, ProtocolForTakerAsSeller.State state) + { + log.error("Error while executing trade process at state: " + state + " / " + throwable); + Popups.openErrorPopup("Error while executing trade process", "Error while executing trade process at state: " + state + " / " + throwable); + } - @Override - public void onWaitingForPeerResponse(TakerAsSellerProtocol.State state) - { - log.debug("Waiting for peers response at state " + state); - } + @Override + public void onWaitingForPeerResponse(ProtocolForTakerAsSeller.State state) + { + log.debug("Waiting for peers response at state " + state); + } - @Override - public void onCompleted(TakerAsSellerProtocol.State state) - { - log.debug("Trade protocol completed at state " + state); - } + @Override + public void onCompleted(ProtocolForTakerAsSeller.State state) + { + log.debug("Trade protocol completed at state " + state); + } - @Override - public void onTakeOfferRequestRejected(Trade trade) - { - log.error("Take offer request rejected"); - Popups.openErrorPopup("Take offer request rejected", "Your take offer request has been rejected. It might be that the offerer got another request shortly before your request arrived."); - } - } - ); + @Override + public void onTakeOfferRequestRejected(Trade trade) + { + log.error("Take offer request rejected"); + Popups.openErrorPopup("Take offer request rejected", + "Your take offer request has been rejected. It might be that the offerer got another request shortly before your request arrived."); + } + }); } } diff --git a/src/main/java/io/bitsquare/gui/market/trade/TakerTradeController.java b/src/main/java/io/bitsquare/gui/market/trade/TakerTradeController.java index c35b939c53..bd6aeb5555 100644 --- a/src/main/java/io/bitsquare/gui/market/trade/TakerTradeController.java +++ b/src/main/java/io/bitsquare/gui/market/trade/TakerTradeController.java @@ -196,7 +196,9 @@ public class TakerTradeController implements Initializable, ChildController try { if (offer.getArbitrator() != null && offer.getArbitrator().getWebUrl() != null) + { Utilities.openURL(offer.getArbitrator().getWebUrl()); + } } catch (Exception e1) { log.warn(e1.toString()); @@ -230,13 +232,13 @@ public class TakerTradeController implements Initializable, ChildController trade = trading.createTrade(offer); trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText())); - /* if (!blockChainFacade.verifyAccountRegistration(offer.getAccountId())) + /* if (!blockChainFacade.verifyAccountRegistration(offer.getTakerAccountId())) { Popups.openErrorPopup("Offerers account ID not valid", "Offerers registration tx is not found in blockchain or does not match the requirements."); return; } - if (blockChainFacade.isAccountIDBlacklisted(offer.getAccountId())) + if (blockChainFacade.isAccountIDBlacklisted(offer.getTakerAccountId())) { Popups.openErrorPopup("Offerers account ID is blacklisted", "Offerers account ID is blacklisted."); return; diff --git a/src/main/java/io/bitsquare/gui/orders/pending/PendingTradeController.java b/src/main/java/io/bitsquare/gui/orders/pending/PendingTradeController.java index 860bc2a527..b3a1efc3a0 100644 --- a/src/main/java/io/bitsquare/gui/orders/pending/PendingTradeController.java +++ b/src/main/java/io/bitsquare/gui/orders/pending/PendingTradeController.java @@ -155,7 +155,9 @@ public class PendingTradeController implements Initializable, ChildController, H trading.getNewTradeProperty().addListener((observableValue, oldTradeId, newTradeId) -> { Trade newTrade = trading.getTrade(newTradeId); if (newTrade != null) + { tradeItems.add(new PendingTradesListItem(newTrade)); + } }); initCopyIcons(); @@ -163,7 +165,9 @@ public class PendingTradeController implements Initializable, ChildController, H // select Optional currentTradeItemOptional = tradeItems.stream().filter((e) -> e.getTrade().getId().equals(trading.getPendingTrade().getId())).findFirst(); if (currentTradeItemOptional.isPresent()) + { openTradesTable.getSelectionModel().select(currentTradeItemOptional.get()); + } tradeItems.addListener((ListChangeListener) change -> { if (openTradesTable.getSelectionModel().getSelectedItem() == null && tradeItems.size() > 0) diff --git a/src/main/java/io/bitsquare/gui/popups/Popups.java b/src/main/java/io/bitsquare/gui/popups/Popups.java index 71e1176eae..9d334be54e 100644 --- a/src/main/java/io/bitsquare/gui/popups/Popups.java +++ b/src/main/java/io/bitsquare/gui/popups/Popups.java @@ -22,12 +22,7 @@ public class Popups public static void openInformationPopup(String title, String message, String masthead) { - Dialogs.create() - .owner(BitSquare.getStage()) - .title(title) - .message(message) - .masthead(masthead) - .showInformation(); + Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showInformation(); } // Confirm @@ -41,13 +36,7 @@ public class Popups List actions = new ArrayList<>(); actions.add(Dialog.Actions.OK); actions.add(Dialog.Actions.CANCEL); - return Dialogs.create() - .owner(BitSquare.getStage()) - .title(title) - .message(message) - .masthead(masthead) - .actions(actions) - .showConfirm(); + return Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).actions(actions).showConfirm(); } // Warning @@ -63,12 +52,7 @@ public class Popups public static void openWarningPopup(String title, String message, String masthead) { - Dialogs.create() - .owner(BitSquare.getStage()) - .title(title) - .message(message) - .masthead(masthead) - .showWarning(); + Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showWarning(); } // Error @@ -84,12 +68,7 @@ public class Popups public static Action openErrorPopup(String title, String message, String masthead) { - return Dialogs.create() - .owner(BitSquare.getStage()) - .title(title) - .message(message) - .masthead(masthead) - .showError(); + return Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showError(); } // Exception @@ -105,12 +84,7 @@ public class Popups public static Action openExceptionPopup(Throwable throwable, String title, String message, String masthead) { - return Dialogs.create() - .owner(BitSquare.getStage()) - .title(title) - .message(message) - .masthead(masthead) - .showException(throwable); + return Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showException(throwable); } // Support handling of uncaught exception from any thread (also non gui thread) @@ -120,26 +94,36 @@ public class Popups // while dev throwable.printStackTrace(); - Runnable runnable = () -> - { + Runnable runnable = () -> { if (Throwables.getRootCause(throwable) instanceof BlockStoreException) { Action response = Popups.openErrorPopup("Application already running", "This application is already running and cannot be started twice.", ""); if (response == Dialog.Actions.OK) + { Platform.exit(); + } } else { - Action response = Popups.openExceptionPopup(throwable, "Exception", "", "A critical error has occurred.\nPlease copy the exception details and send a bug report to bugs@bitsquare.io."); + Action response = Popups.openExceptionPopup(throwable, + "Exception", + "", + "A critical error has occurred.\nPlease copy the exception details and send a bug report to bugs@bitsquare.io."); if (response == Dialog.Actions.OK) + { Platform.exit(); + } } }; if (Platform.isFxApplicationThread()) + { runnable.run(); + } else + { Platform.runLater(runnable); + } } @@ -152,11 +136,6 @@ public class Popups public static Action openRegistrationMissingPopup(String title, String message, String masthead, List commandLinks, int selectedIndex) { - return Dialogs.create() - .owner(BitSquare.getStage()) - .title(title) - .message(message) - .masthead(masthead) - .showCommandLinks(commandLinks.get(selectedIndex), commandLinks); + return Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showCommandLinks(commandLinks.get(selectedIndex), commandLinks); } } diff --git a/src/main/java/io/bitsquare/gui/settings/SettingsController.java b/src/main/java/io/bitsquare/gui/settings/SettingsController.java index ae79a7bfdc..2675ef7100 100644 --- a/src/main/java/io/bitsquare/gui/settings/SettingsController.java +++ b/src/main/java/io/bitsquare/gui/settings/SettingsController.java @@ -149,21 +149,20 @@ public class SettingsController implements Initializable, ChildController, Navig idVerifications.add(Arbitrator.ID_VERIFICATION.GOV_ID); Arbitrator arbitrator = new Arbitrator(pubKeyAsHex, - messagePubKeyAsHex, - "Manfred Karrer", - Arbitrator.ID_TYPE.REAL_LIFE_ID, - languages, - new Reputation(), - 1, - 0.01, - 0.001, - 10, - 0.1, - arbitrationMethods, - idVerifications, - "http://bitsquare.io/", - "Bla bla..." - ); + messagePubKeyAsHex, + "Manfred Karrer", + Arbitrator.ID_TYPE.REAL_LIFE_ID, + languages, + new Reputation(), + 1, + 0.01, + 0.001, + 10, + 0.1, + arbitrationMethods, + idVerifications, + "http://bitsquare.io/", + "Bla bla..."); arbitratorList.add(arbitrator); settings.addAcceptedArbitrator(arbitrator); @@ -207,7 +206,9 @@ public class SettingsController implements Initializable, ChildController, Navig { if (childController != null) + { childController.cleanup(); + } final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle()); try @@ -231,7 +232,9 @@ public class SettingsController implements Initializable, ChildController, Navig stage.setScene(scene); stage.setOnHidden(windowEvent -> { if (navigationItem == NavigationItem.ARBITRATOR_OVERVIEW) + { updateArbitrators(); + } }); stage.show(); @@ -351,52 +354,51 @@ public class SettingsController implements Initializable, ChildController, Navig private void initLanguage() { languagesListView.setCellFactory(new Callback, ListCell>() - { + { - @Override - public ListCell call(ListView list) - { - return new ListCell() - { - final HBox hBox = new HBox(); - final Label label = new Label(); - final Button removeButton = new Button(); - final ImageView icon = Icons.getIconImageView(Icons.REMOVE); + @Override + public ListCell call(ListView list) + { + return new ListCell() + { + final HBox hBox = new HBox(); + final Label label = new Label(); + final Button removeButton = new Button(); + final ImageView icon = Icons.getIconImageView(Icons.REMOVE); - { - label.setPrefWidth(565); + { + label.setPrefWidth(565); - icon.setMouseTransparent(true); + icon.setMouseTransparent(true); - removeButton.setGraphic(icon); - removeButton.setId("icon-button"); + removeButton.setGraphic(icon); + removeButton.setId("icon-button"); - hBox.setSpacing(3); - hBox.setAlignment(Pos.CENTER_LEFT); - hBox.getChildren().addAll(label, removeButton); - } + hBox.setSpacing(3); + hBox.setAlignment(Pos.CENTER_LEFT); + hBox.getChildren().addAll(label, removeButton); + } - @Override - public void updateItem(final Locale item, boolean empty) - { - super.updateItem(item, empty); - if (item != null && !empty) - { - label.setText(item.getDisplayName()); + @Override + public void updateItem(final Locale item, boolean empty) + { + super.updateItem(item, empty); + if (item != null && !empty) + { + label.setText(item.getDisplayName()); - removeButton.setOnAction(actionEvent -> removeLanguage(item)); + removeButton.setOnAction(actionEvent -> removeLanguage(item)); - setGraphic(hBox); - } - else - { - setGraphic(null); - } - } - }; - } - } - ); + setGraphic(hBox); + } + else + { + setGraphic(null); + } + } + }; + } + }); languagesListView.setItems(languageList); languageComboBox.setItems(FXCollections.observableArrayList(LanguageUtil.getAllLanguageLocales())); @@ -437,53 +439,52 @@ public class SettingsController implements Initializable, ChildController, Navig }); countriesListView.setCellFactory(new Callback, ListCell>() - { + { - @Override - public ListCell call(ListView list) - { - return new ListCell() - { - final HBox hBox = new HBox(); - final Label label = new Label(); - final Button removeButton = new Button(); - final ImageView icon = Icons.getIconImageView(Icons.REMOVE); + @Override + public ListCell call(ListView list) + { + return new ListCell() + { + final HBox hBox = new HBox(); + final Label label = new Label(); + final Button removeButton = new Button(); + final ImageView icon = Icons.getIconImageView(Icons.REMOVE); - { - label.setPrefWidth(565); + { + label.setPrefWidth(565); - icon.setMouseTransparent(true); + icon.setMouseTransparent(true); - removeButton.setGraphic(icon); - removeButton.setId("icon-button"); + removeButton.setGraphic(icon); + removeButton.setId("icon-button"); - hBox.setSpacing(3); - hBox.setAlignment(Pos.CENTER_LEFT); - hBox.getChildren().addAll(label, removeButton); - } + hBox.setSpacing(3); + hBox.setAlignment(Pos.CENTER_LEFT); + hBox.getChildren().addAll(label, removeButton); + } - @Override - public void updateItem(final Country item, boolean empty) - { - super.updateItem(item, empty); - if (item != null && !empty) - { - label.setText(item.getName()); + @Override + public void updateItem(final Country item, boolean empty) + { + super.updateItem(item, empty); + if (item != null && !empty) + { + label.setText(item.getName()); - removeButton.setOnAction(actionEvent -> removeCountry(item)); + removeButton.setOnAction(actionEvent -> removeCountry(item)); - setGraphic(hBox); - } - else - { - setGraphic(null); - } - } - }; - } - } - ); + setGraphic(hBox); + } + else + { + setGraphic(null); + } + } + }; + } + }); countriesListView.setItems(countryList); countryComboBox.setConverter(new StringConverter() @@ -508,53 +509,52 @@ public class SettingsController implements Initializable, ChildController, Navig private void initArbitrators() { arbitratorsListView.setCellFactory(new Callback, ListCell>() - { + { - @Override - public ListCell call(ListView list) - { - return new ListCell() - { - final HBox hBox = new HBox(); - final Label label = new Label(); - final Button removeButton = new Button(); - final ImageView icon = Icons.getIconImageView(Icons.REMOVE); + @Override + public ListCell call(ListView list) + { + return new ListCell() + { + final HBox hBox = new HBox(); + final Label label = new Label(); + final Button removeButton = new Button(); + final ImageView icon = Icons.getIconImageView(Icons.REMOVE); - { - label.setPrefWidth(565); + { + label.setPrefWidth(565); - icon.setMouseTransparent(true); + icon.setMouseTransparent(true); - removeButton.setGraphic(icon); - removeButton.setId("icon-button"); + removeButton.setGraphic(icon); + removeButton.setId("icon-button"); - hBox.setSpacing(3); - hBox.setAlignment(Pos.CENTER_LEFT); - hBox.getChildren().addAll(label, removeButton); - } + hBox.setSpacing(3); + hBox.setAlignment(Pos.CENTER_LEFT); + hBox.getChildren().addAll(label, removeButton); + } - @Override - public void updateItem(final Arbitrator item, boolean empty) - { - super.updateItem(item, empty); - if (item != null && !empty) - { - label.setText(item.getName()); + @Override + public void updateItem(final Arbitrator item, boolean empty) + { + super.updateItem(item, empty); + if (item != null && !empty) + { + label.setText(item.getName()); - removeButton.setOnAction(actionEvent -> removeArbitrator(item)); + removeButton.setOnAction(actionEvent -> removeArbitrator(item)); - setGraphic(hBox); - } - else - { - setGraphic(null); - } - } - }; - } - } - ); + setGraphic(hBox); + } + else + { + setGraphic(null); + } + } + }; + } + }); arbitratorsListView.setItems(arbitratorList); } @@ -645,7 +645,9 @@ public class SettingsController implements Initializable, ChildController, Navig bankAccountPrimaryIDTextField.setText("dummy"); bankAccountSecondaryIDTextField.setText("dummy"); if (user.getCurrentBankAccount() == null) + { onSaveBankAccount(); + } } private void resetBankAccountInput() @@ -809,14 +811,13 @@ public class SettingsController implements Initializable, ChildController, Navig { if (verifyBankAccountData()) { - BankAccount bankAccount = new BankAccount( - bankAccountTypesComboBox.getSelectionModel().getSelectedItem(), - bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem(), - bankAccountCountryComboBox.getSelectionModel().getSelectedItem(), - bankAccountTitleTextField.getText(), - bankAccountHolderNameTextField.getText(), - bankAccountPrimaryIDTextField.getText(), - bankAccountSecondaryIDTextField.getText()); + BankAccount bankAccount = new BankAccount(bankAccountTypesComboBox.getSelectionModel().getSelectedItem(), + bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem(), + bankAccountCountryComboBox.getSelectionModel().getSelectedItem(), + bankAccountTitleTextField.getText(), + bankAccountHolderNameTextField.getText(), + bankAccountPrimaryIDTextField.getText(), + bankAccountSecondaryIDTextField.getText()); user.addBankAccount(bankAccount); saveUser(); @@ -844,9 +845,10 @@ public class SettingsController implements Initializable, ChildController, Navig BitSquareValidator.textFieldBankAccountPrimaryIDIsValid(bankAccountPrimaryIDTextField, bankAccountTypeInfo); BitSquareValidator.textFieldBankAccountSecondaryIDIsValid(bankAccountSecondaryIDTextField, bankAccountTypeInfo); - return bankAccountTypesComboBox.getSelectionModel().getSelectedItem() != null - && bankAccountCountryComboBox.getSelectionModel().getSelectedItem() != null - && bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem() != null; + return bankAccountTypesComboBox.getSelectionModel().getSelectedItem() != null && bankAccountCountryComboBox.getSelectionModel() + .getSelectedItem() != null && bankAccountCurrencyComboBox.getSelectionModel() + .getSelectedItem() != + null; } catch (BitSquareValidator.ValidationException e) { return false; diff --git a/src/main/java/io/bitsquare/gui/util/BitSquareFormatter.java b/src/main/java/io/bitsquare/gui/util/BitSquareFormatter.java index c3bc5a6974..b1d8721f3e 100644 --- a/src/main/java/io/bitsquare/gui/util/BitSquareFormatter.java +++ b/src/main/java/io/bitsquare/gui/util/BitSquareFormatter.java @@ -50,9 +50,13 @@ public class BitSquareFormatter public static String formatAmountWithMinAmount(double amount, double minAmount, boolean useBTC) { if (useBTC) + { return formatDouble(amount) + " BTC (" + formatDouble(minAmount) + " BTC)"; + } else + { return formatDouble(amount) + " (" + formatDouble(minAmount) + ")"; + } } @@ -95,7 +99,9 @@ public class BitSquareFormatter { String result = (direction == Direction.BUY) ? "Buy" : "Sell"; if (allUpperCase) + { result = result.toUpperCase(); + } return result; } @@ -143,7 +149,9 @@ public class BitSquareFormatter result += country.getName(); i++; if (i < countries.size()) + { result += ", "; + } } return result; } @@ -157,7 +165,9 @@ public class BitSquareFormatter result += locale.getDisplayLanguage(); i++; if (i < languageLocales.size()) + { result += ", "; + } } return result; } @@ -172,7 +182,9 @@ public class BitSquareFormatter result += Localisation.get(item.toString()); i++; if (i < items.size()) + { result += ", "; + } } return result; } @@ -187,7 +199,9 @@ public class BitSquareFormatter result += Localisation.get(item.toString()); i++; if (i < items.size()) + { result += ", "; + } } return result; } diff --git a/src/main/java/io/bitsquare/gui/util/ConfidenceDisplay.java b/src/main/java/io/bitsquare/gui/util/ConfidenceDisplay.java index aa51c1054f..6bb21d2292 100644 --- a/src/main/java/io/bitsquare/gui/util/ConfidenceDisplay.java +++ b/src/main/java/io/bitsquare/gui/util/ConfidenceDisplay.java @@ -107,7 +107,9 @@ public class ConfidenceDisplay public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { if (tx.getHashAsString().equals(transaction.getHashAsString())) + { updateBalance(newBalance); + } // log.debug("onCoinsReceived " + newBalance); } @@ -115,7 +117,9 @@ public class ConfidenceDisplay public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) { if (tx.getHashAsString().equals(transaction.getHashAsString())) + { updateConfidence(transaction); + } // log.debug("onTransactionConfidenceChanged newTransaction " + newTransaction.getHashAsString()); } @@ -123,7 +127,9 @@ public class ConfidenceDisplay public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { if (tx.getHashAsString().equals(transaction.getHashAsString())) + { updateBalance(newBalance); + } } @Override @@ -155,7 +161,9 @@ public class ConfidenceDisplay progressIndicator.setProgress(0); confirmationLabel.setText(""); if (balanceTextField != null) + { balanceTextField.setText(""); + } } private void updateBalance(BigInteger balance) @@ -183,11 +191,15 @@ public class ConfidenceDisplay } } if (latestTransaction != null && (transaction == null || latestTransaction.getHashAsString().equals(transaction.getHashAsString()))) + { updateConfidence(latestTransaction); + } } if (balanceTextField != null) + { balanceTextField.setText(BtcFormatter.formatSatoshis(balance)); + } } private void updateConfidence(Transaction tx) diff --git a/src/main/java/io/bitsquare/locale/Country.java b/src/main/java/io/bitsquare/locale/Country.java index a973d1919b..1c862cd1cb 100644 --- a/src/main/java/io/bitsquare/locale/Country.java +++ b/src/main/java/io/bitsquare/locale/Country.java @@ -29,9 +29,13 @@ public class Country implements Serializable public boolean equals(Object obj) { if (!(obj instanceof Country)) + { return false; + } if (obj == this) + { return true; + } final Country other = (Country) obj; return code.equals(other.getCode()); diff --git a/src/main/java/io/bitsquare/locale/CountryUtil.java b/src/main/java/io/bitsquare/locale/CountryUtil.java index 8aaecf7297..52f8a7abb1 100644 --- a/src/main/java/io/bitsquare/locale/CountryUtil.java +++ b/src/main/java/io/bitsquare/locale/CountryUtil.java @@ -7,211 +7,17 @@ import java.util.stream.Collectors; public class CountryUtil { - private static final String[] countryCodes = new String[]{"AE", - "AL", - "AR", - "AT", - "AU", - "BA", - "BE", - "BG", - "BH", - "BO", - "BR", - "BY", - "CA", - "CH", - "CL", - "CN", - "CO", - "CR", - "CS", - "CU", - "CY", - "CZ", - "DE", - "DK", - "DO", - "DZ", - "EC", - "EE", - "EG", - "ES", - "FI", - "FR", - "GB", - "GR", - "GT", - "HK", - "HN", - "HR", - "HU", - "ID", - "IE", - "IL", - "IN", - "IQ", - "IS", - "IT", - "JO", - "JP", - "KR", - "KW", - "LB", - "LT", - "LU", - "LV", - "LY", - "MA", - "ME", - "MK", - "MT", - "MX", - "MY", - "NI", - "NL", - "NO", - "NZ", - "OM", - "PA", - "PE", - "PH", - "PL", - "PR", - "PT", - "PY", - "QA", - "RO", - "RS", - "RU", - "SA", - "SD", - "SE", - "SG", - "SI", - "SK", - "SV", - "SY", - "TH", - "TN", - "TR", - "TW", - "UA", - "US", - "UY", - "VE", - "VN", - "YE", - "ZA" - }; + private static final String[] countryCodes = new String[]{"AE", "AL", "AR", "AT", "AU", "BA", "BE", "BG", "BH", "BO", "BR", "BY", "CA", "CH", "CL", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", + "DE", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "FI", "FR", "GB", "GR", "GT", "HK", "HN", "HR", "HU", "ID", "IE", "IL", "IN", "IQ", "IS", "IT", "JO", "JP", "KR", "KW", "LB", "LT", "LU", + "LV", "LY", "MA", "ME", "MK", "MT", "MX", "MY", "NI", "NL", "NO", "NZ", "OM", "PA", "PE", "PH", "PL", "PR", "PT", "PY", "QA", "RO", "RS", "RU", "SA", "SD", "SE", "SG", "SI", "SK", "SV", + "SY", "TH", "TN", "TR", "TW", "UA", "US", "UY", "VE", "VN", "YE", "ZA"}; private static final List countryCodeList = Arrays.asList(countryCodes); - private static final String[] regionCodes = new String[]{ - "AS", - "EU", - "SA", - "EU", - "OC", - "EU", - "EU", - "EU", - "AS", - "SA", - "SA", - "EU", - "NA", - "EU", - "SA", - "AS", - "SA", - "NA", - "EU", - "NA", - "AS", - "EU", - "EU", - "EU", - "NA", - "AF", - "SA", - "EU", - "AF", - "EU", - "EU", - "EU", - "EU", - "EU", - "NA", - "AS", - "NA", - "EU", - "EU", - "AS", - "EU", - "AS", - "AS", - "AS", - "EU", - "EU", - "AS", - "AS", - "AS", - "AS", - "AS", - "EU", - "EU", - "EU", - "AF", - "AF", - "EU", - "EU", - "EU", - "NA", - "AS", - "NA", - "EU", - "EU", - "OC", - "AS", - "NA", - "SA", - "AS", - "EU", - "NA", - "EU", - "SA", - "AS", - "EU", - "EU", - "EU", - "AS", - "AF", - "EU", - "AS", - "EU", - "EU", - "NA", - "AS", - "AS", - "AF", - "AS", - "AS", - "EU", - "NA", - "SA", - "SA", - "AS", - "AS", - "AF" - }; + private static final String[] regionCodes = new String[]{"AS", "EU", "SA", "EU", "OC", "EU", "EU", "EU", "AS", "SA", "SA", "EU", "NA", "EU", "SA", "AS", "SA", "NA", "EU", "NA", "AS", "EU", + "EU", "EU", "NA", "AF", "SA", "EU", "AF", "EU", "EU", "EU", "EU", "EU", "NA", "AS", "NA", "EU", "EU", "AS", "EU", "AS", "AS", "AS", "EU", "EU", "AS", "AS", "AS", "AS", "AS", "EU", "EU", + "EU", "AF", "AF", "EU", "EU", "EU", "NA", "AS", "NA", "EU", "EU", "OC", "AS", "NA", "SA", "AS", "EU", "NA", "EU", "SA", "AS", "EU", "EU", "EU", "AS", "AF", "EU", "AS", "EU", "EU", "NA", + "AS", "AS", "AF", "AS", "AS", "EU", "NA", "SA", "SA", "AS", "AS", "AF"}; private static final List regionCodeList = Arrays.asList(regionCodes); - private static final String[][] regionCodeToName = new String[][]{ - {"NA", "North America"}, - {"SA", "South America"}, - {"AF", "Africa"}, - {"EU", "Europe"}, - {"AS", "Asia"}, - {"OC", "Oceania"} - }; + private static final String[][] regionCodeToName = new String[][]{{"NA", "North America"}, {"SA", "South America"}, {"AF", "Africa"}, {"EU", "Europe"}, {"AS", "Asia"}, {"OC", "Oceania"}}; public static List getAllRegions() @@ -279,7 +85,9 @@ public class CountryUtil for (final String[] regionName : regionCodeToName) { if (regionName[0].equals(regionCode)) + { return regionName[1]; + } } return regionCode; } @@ -310,9 +118,13 @@ public class CountryUtil private static String getRegionCode(String countryCode) { if (!countryCode.isEmpty() && countryCodeList.contains(countryCode)) + { return regionCodeList.get(countryCodeList.indexOf(countryCode)); + } else + { return "Undefined"; + } } } diff --git a/src/main/java/io/bitsquare/locale/Region.java b/src/main/java/io/bitsquare/locale/Region.java index 82b6fddee2..7a90771220 100644 --- a/src/main/java/io/bitsquare/locale/Region.java +++ b/src/main/java/io/bitsquare/locale/Region.java @@ -26,9 +26,13 @@ public class Region implements Serializable public boolean equals(Object obj) { if (!(obj instanceof Region)) + { return false; + } if (obj == this) + { return true; + } Region other = (Region) obj; return code.equals(other.getCode()); diff --git a/src/main/java/io/bitsquare/msg/MessageFacade.java b/src/main/java/io/bitsquare/msg/MessageFacade.java index 837f27e1ea..8738ea5a0c 100644 --- a/src/main/java/io/bitsquare/msg/MessageFacade.java +++ b/src/main/java/io/bitsquare/msg/MessageFacade.java @@ -72,9 +72,13 @@ public class MessageFacade { int port = Bindings.MAX_PORT - Math.abs(new Random().nextInt()) % (Bindings.MAX_PORT - Bindings.MIN_DYN_PORT); if (BitSquare.ID.contains("taker")) + { port = 4501; + } else if (BitSquare.ID.contains("offerer")) + { port = 4500; + } try { @@ -93,7 +97,9 @@ public class MessageFacade public void shutDown() { if (myPeer != null) + { myPeer.shutdown(); + } } @@ -219,17 +225,20 @@ public class MessageFacade final PeerConnection peerConnection = myPeer.createPeerConnection(peerAddress, 10); final FutureResponse sendFuture = myPeer.sendDirect(peerConnection).setObject(tradeMessage).start(); sendFuture.addListener(new BaseFutureAdapter() - { - @Override - public void operationComplete(BaseFuture baseFuture) throws Exception - { - if (sendFuture.isSuccess()) - Platform.runLater(() -> listener.onResult()); - else - Platform.runLater(() -> listener.onFailed()); - } - } - ); + { + @Override + public void operationComplete(BaseFuture baseFuture) throws Exception + { + if (sendFuture.isSuccess()) + { + Platform.runLater(() -> listener.onResult()); + } + else + { + Platform.runLater(() -> listener.onFailed()); + } + } + }); } @@ -319,7 +328,9 @@ public class MessageFacade private void onArbitratorsReceived(Map dataMap, boolean success) { for (ArbitratorListener arbitratorListener : arbitratorListeners) + { arbitratorListener.onArbitratorsReceived(dataMap, success); + } } /////////////////////////////////////////////////////////////////////////////////////////// @@ -346,7 +357,9 @@ public class MessageFacade { Object object = data.getObject(); if (object instanceof Long) + { Platform.runLater(() -> onGetDirtyFlag((Long) object)); + } } } @@ -366,9 +379,13 @@ public class MessageFacade isDirty.setValue(!isDirty.get()); } if (lastTimeStamp > 0) + { lastTimeStamp = timeStamp; + } else + { lastTimeStamp++; + } } private Number160 getDirtyLocationKey(Number160 locationKey) @@ -634,9 +651,13 @@ public class MessageFacade { myPeer.setObjectDataReply((sender, request) -> { if (!sender.equals(myPeer.getPeerAddress())) + { Platform.runLater(() -> onMessage(request, sender)); + } else + { log.error("Received msg from myself. That should never happen."); + } //noinspection ReturnOfNull return null; }); diff --git a/src/main/java/io/bitsquare/settings/Settings.java b/src/main/java/io/bitsquare/settings/Settings.java index 4aecfec65b..7cc32919cb 100644 --- a/src/main/java/io/bitsquare/settings/Settings.java +++ b/src/main/java/io/bitsquare/settings/Settings.java @@ -51,7 +51,9 @@ public class Settings implements Serializable public void addAcceptedLanguageLocale(Locale locale) { if (!acceptedLanguageLocales.contains(locale)) + { acceptedLanguageLocales.add(locale); + } } public void removeAcceptedLanguageLocale(Locale item) @@ -62,7 +64,9 @@ public class Settings implements Serializable public void addAcceptedCountry(Country locale) { if (!acceptedCountryLocales.contains(locale)) + { acceptedCountryLocales.add(locale); + } } public void removeAcceptedCountry(Country item) @@ -73,7 +77,9 @@ public class Settings implements Serializable public void addAcceptedArbitrator(Arbitrator arbitrator) { if (!acceptedArbitrators.contains(arbitrator)) + { acceptedArbitrators.add(arbitrator); + } } public void removeAcceptedArbitrator(Arbitrator item) diff --git a/src/main/java/io/bitsquare/storage/Storage.java b/src/main/java/io/bitsquare/storage/Storage.java index 1b1ce07250..ac67278ee3 100644 --- a/src/main/java/io/bitsquare/storage/Storage.java +++ b/src/main/java/io/bitsquare/storage/Storage.java @@ -237,9 +237,13 @@ public class Storage // Work around an issue on Windows whereby you can't rename over existing files. final File canonical = storageFile.getCanonicalFile(); if (canonical.exists() && !canonical.delete()) + { throw new IOException("Failed to delete canonical file for replacement with save"); + } if (!tempFile.renameTo(canonical)) + { throw new IOException("Failed to rename " + tempFile + " to " + canonical); + } } else if (!tempFile.renameTo(storageFile)) { @@ -255,7 +259,9 @@ public class Storage { log.warn("Temp file still exists after failed save."); if (!tempFile.delete()) + { log.warn("Cannot delete temp file."); + } } } } catch (IOException e) diff --git a/src/main/java/io/bitsquare/trade/Trading.java b/src/main/java/io/bitsquare/trade/Trading.java index 83f3f94cb8..1e89566c4b 100644 --- a/src/main/java/io/bitsquare/trade/Trading.java +++ b/src/main/java/io/bitsquare/trade/Trading.java @@ -12,15 +12,8 @@ import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.TradeMessage; import io.bitsquare.msg.listeners.TakeOfferRequestListener; import io.bitsquare.storage.Storage; -import io.bitsquare.trade.protocol.messages.offerer.*; -import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage; -import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage; -import io.bitsquare.trade.protocol.messages.taker.RequestTakeOfferMessage; -import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage; -import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocol; -import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocolListener; -import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocol; -import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocolListener; +import io.bitsquare.trade.protocol.offerer.*; +import io.bitsquare.trade.protocol.taker.*; import io.bitsquare.user.User; import java.io.IOException; import java.math.BigInteger; @@ -49,8 +42,10 @@ public class Trading private final CryptoFacade cryptoFacade; private final List takeOfferRequestListeners = new ArrayList<>(); - private final Map takerAsSellerProtocolMap = new HashMap<>(); - private final Map offererAsBuyerProtocolMap = new HashMap<>(); + + //TODO store TakerAsSellerProtocol in trade + private final Map takerAsSellerProtocolMap = new HashMap<>(); + private final Map offererAsBuyerProtocolMap = new HashMap<>(); private final StringProperty newTradeProperty = new SimpleStringProperty(); @@ -65,12 +60,7 @@ public class Trading /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public Trading(User user, - Storage storage, - MessageFacade messageFacade, - BlockChainFacade blockChainFacade, - WalletFacade walletFacade, - CryptoFacade cryptoFacade) + public Trading(User user, Storage storage, MessageFacade messageFacade, BlockChainFacade blockChainFacade, WalletFacade walletFacade, CryptoFacade cryptoFacade) { this.user = user; this.storage = storage; @@ -81,15 +71,23 @@ public class Trading Object offersObject = storage.read(storageKey + ".offers"); if (offersObject instanceof HashMap) + { offers = (Map) offersObject; + } else + { offers = new HashMap<>(); + } Object tradesObject = storage.read(storageKey + ".trades"); if (tradesObject instanceof HashMap) + { trades = (Map) tradesObject; + } else + { trades = new HashMap<>(); + } messageFacade.addIncomingTradeMessageListener(this::onIncomingTradeMessage); } @@ -127,7 +125,9 @@ public class Trading public void addOffer(Offer offer) throws IOException { if (offers.containsKey(offer.getId())) + { throw new IllegalStateException("offers contains already an offer with the ID " + offer.getId()); + } offers.put(offer.getId(), offer); saveOffers(); @@ -138,7 +138,9 @@ public class Trading public void removeOffer(Offer offer) { if (!offers.containsKey(offer.getId())) + { throw new IllegalStateException("offers does not contain the offer with the ID " + offer.getId()); + } offers.remove(offer.getId()); saveOffers(); @@ -146,14 +148,14 @@ public class Trading messageFacade.removeOffer(offer); } - public Trade takeOffer(BigInteger amount, Offer offer, TakerAsSellerProtocolListener listener) + public Trade takeOffer(BigInteger amount, Offer offer, ProtocolForTakerAsSellerListener listener) { Trade trade = createTrade(offer); trade.setTradeAmount(amount); - TakerAsSellerProtocol takerAsSellerProtocol = new TakerAsSellerProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user); - takerAsSellerProtocolMap.put(trade.getId(), takerAsSellerProtocol); - takerAsSellerProtocol.start(); + ProtocolForTakerAsSeller protocolForTakerAsSeller = new ProtocolForTakerAsSeller(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user); + takerAsSellerProtocolMap.put(trade.getId(), protocolForTakerAsSeller); + protocolForTakerAsSeller.start(); return trade; } @@ -166,7 +168,9 @@ public class Trading public Trade createTrade(Offer offer) { if (trades.containsKey(offer.getId())) + { throw new IllegalStateException("trades contains already an trade with the ID " + offer.getId()); + } Trade trade = new Trade(offer); trades.put(offer.getId(), trade); @@ -181,7 +185,9 @@ public class Trading public void removeTrade(Trade trade) { if (!trades.containsKey(trade.getId())) + { throw new IllegalStateException("trades does not contain the trade with the ID " + trade.getId()); + } trades.remove(trade.getId()); saveTrades(); @@ -205,70 +211,90 @@ public class Trading Trade trade = createTrade(offer); pendingTrade = trade; - OffererAsBuyerProtocol offererAsBuyerProtocol = new OffererAsBuyerProtocol(trade, sender, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user, new OffererAsBuyerProtocolListener() + ProtocolForOffererAsBuyer protocolForOffererAsBuyer = new ProtocolForOffererAsBuyer(trade, + sender, + messageFacade, + walletFacade, + blockChainFacade, + cryptoFacade, + user, + new ProtocolForOffererAsBuyerListener() + { + @Override + public void onOfferAccepted(Offer offer) + { + removeOffer(offer); + } + + @Override + public void onDepositTxPublished(String depositTxID) + { + log.trace("trading onDepositTxPublishedMessage " + depositTxID); + } + + @Override + public void onDepositTxConfirmedUpdate(TransactionConfidence confidence) + { + log.trace("trading onDepositTxConfirmedUpdate"); + } + + @Override + public void onPayoutTxPublished(String payoutTxAsHex) + { + Transaction payoutTx = new Transaction(walletFacade.getWallet().getParams(), + Utils.parseAsHexOrBase58(payoutTxAsHex)); + trade.setPayoutTransaction(payoutTx); + trade.setState(Trade.State.COMPLETED); + log.debug("trading onPayoutTxPublishedMessage"); + } + + @Override + public void onFault(Throwable throwable, ProtocolForOffererAsBuyer.State state) + { + log.error("Error while executing trade process at state: " + state + " / " + throwable); + Popups.openErrorPopup("Error while executing trade process", + "Error while executing trade process at state: " + state + " / " + + throwable); + } + + @Override + public void onWaitingForPeerResponse(ProtocolForOffererAsBuyer.State state) + { + log.debug("Waiting for peers response at state " + state); + } + + @Override + public void onCompleted(ProtocolForOffererAsBuyer.State state) + { + log.debug("Trade protocol completed at state " + state); + } + + @Override + public void onWaitingForUserInteraction(ProtocolForOffererAsBuyer.State state) + { + log.debug("Waiting for UI activity at state " + state); + } + + + @Override + public void onDepositTxConfirmedInBlockchain() + { + log.trace("trading onDepositTxConfirmedInBlockchain"); + } + + }); + + if (!offererAsBuyerProtocolMap.containsKey(trade.getId())) { - @Override - public void onOfferAccepted(Offer offer) - { - removeOffer(offer); - } + offererAsBuyerProtocolMap.put(trade.getId(), protocolForOffererAsBuyer); + } + else + { + // We don't store the protocol in case we have already a pending offer. The protocol is only temporary used to reply with a reject message. + log.trace("offererAsBuyerProtocol not stored as offer is already pending."); + } - @Override - public void onDepositTxPublished(String depositTxID) - { - log.trace("trading onDepositTxPublishedMessage " + depositTxID); - } - - @Override - public void onDepositTxConfirmedUpdate(TransactionConfidence confidence) - { - log.trace("trading onDepositTxConfirmedUpdate"); - } - - @Override - public void onPayoutTxPublished(String payoutTxAsHex) - { - Transaction payoutTx = new Transaction(walletFacade.getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex)); - trade.setPayoutTransaction(payoutTx); - trade.setState(Trade.State.COMPLETED); - log.debug("trading onPayoutTxPublishedMessage"); - } - - @Override - public void onFault(Throwable throwable, OffererAsBuyerProtocol.State state) - { - log.error("Error while executing trade process at state: " + state + " / " + throwable); - Popups.openErrorPopup("Error while executing trade process", "Error while executing trade process at state: " + state + " / " + throwable); - } - - @Override - public void onWaitingForPeerResponse(OffererAsBuyerProtocol.State state) - { - log.debug("Waiting for peers response at state " + state); - } - - @Override - public void onCompleted(OffererAsBuyerProtocol.State state) - { - log.debug("Trade protocol completed at state " + state); - } - - @Override - public void onWaitingForUserInteraction(OffererAsBuyerProtocol.State state) - { - log.debug("Waiting for UI activity at state " + state); - } - - - @Override - public void onDepositTxConfirmedInBlockchain() - { - log.trace("trading onDepositTxConfirmedInBlockchain"); - } - - }); - this.offererAsBuyerProtocolMap.put(trade.getId(), offererAsBuyerProtocol); - offererAsBuyerProtocol.start(); + protocolForOffererAsBuyer.start(); } else { @@ -305,13 +331,9 @@ public class Trading createOffererAsBuyerProtocol(tradeId, sender); takeOfferRequestListeners.stream().forEach(e -> e.onTakeOfferRequested(tradeId, sender)); } - else if (tradeMessage instanceof AcceptTakeOfferRequestMessage) + else if (tradeMessage instanceof RespondToTakeOfferRequestMessage) { - takerAsSellerProtocolMap.get(tradeId).onAcceptTakeOfferRequestMessage(); - } - else if (tradeMessage instanceof RejectTakeOfferRequestMessage) - { - takerAsSellerProtocolMap.get(tradeId).onRejectTakeOfferRequestMessage(); + takerAsSellerProtocolMap.get(tradeId).onRespondToTakeOfferRequestMessage((RespondToTakeOfferRequestMessage) tradeMessage); } else if (tradeMessage instanceof TakeOfferFeePayedMessage) { @@ -398,8 +420,12 @@ public class Trading public Trade getTrade(String tradeId) { if (trades.containsKey(tradeId)) + { return trades.get(trades); + } else + { return null; + } } } diff --git a/src/main/java/io/bitsquare/trade/orderbook/OrderBook.java b/src/main/java/io/bitsquare/trade/orderbook/OrderBook.java index 998d9dca13..07dcacaf09 100644 --- a/src/main/java/io/bitsquare/trade/orderbook/OrderBook.java +++ b/src/main/java/io/bitsquare/trade/orderbook/OrderBook.java @@ -70,9 +70,13 @@ public class OrderBook implements OrderBookListener public void loadOffers() { if (user.getCurrentBankAccount() != null) + { messageFacade.getOffers(user.getCurrentBankAccount().getCurrency().getCurrencyCode()); + } else + { messageFacade.getOffers(CurrencyUtil.getDefaultCurrency().getCurrencyCode()); + } } public void removeOffer(Offer offer) @@ -86,10 +90,10 @@ public class OrderBook implements OrderBookListener Offer offer = orderBookListItem.getOffer(); BankAccount currentBankAccount = user.getCurrentBankAccount(); - if (orderBookFilter == null - || currentBankAccount == null - || orderBookFilter.getDirection() == null) + if (orderBookFilter == null || currentBankAccount == null || orderBookFilter.getDirection() == null) + { return false; + } // The users current bank account currency must match the offer currency (1 to 1) boolean currencyResult = currentBankAccount.getCurrency().equals(offer.getCurrency()); @@ -104,7 +108,9 @@ public class OrderBook implements OrderBookListener // The requested amount must be lower or equal then the offer amount boolean amountResult = true; if (orderBookFilter.getAmount() > 0) + { amountResult = orderBookFilter.getAmount() <= offer.getAmount().doubleValue(); + } // The requested trade direction must be opposite of the offerList trade direction boolean directionResult = !orderBookFilter.getDirection().equals(offer.getDirection()); @@ -114,9 +120,13 @@ public class OrderBook implements OrderBookListener if (orderBookFilter.getPrice() > 0) { if (offer.getDirection() == Direction.SELL) + { priceResult = orderBookFilter.getPrice() >= offer.getPrice(); + } else + { priceResult = orderBookFilter.getPrice() <= offer.getPrice(); + } } // The arbitrator defined in the offer must match one of the accepted arbitrators defined in the settings (1 to n) @@ -124,13 +134,7 @@ public class OrderBook implements OrderBookListener //noinspection UnnecessaryLocalVariable - boolean result = currencyResult - && countryResult - && languageResult - && amountResult - && directionResult - && priceResult - && arbitratorResult; + boolean result = currencyResult && countryResult && languageResult && amountResult && directionResult && priceResult && arbitratorResult; /* log.debug("result = " + result + @@ -260,7 +264,9 @@ public class OrderBook implements OrderBookListener for (Country country : list) { if (country.getCode().equals(countryToMatch.getCode())) + { return true; + } } return false; } @@ -272,7 +278,9 @@ public class OrderBook implements OrderBookListener for (Locale locale2 : list1) { if (locale1.getLanguage().equals(locale2.getLanguage())) + { return true; + } } } return false; @@ -287,7 +295,9 @@ public class OrderBook implements OrderBookListener try { if (arbitrator.getId().equals(arbitratorToMatch.getId())) + { return true; + } } catch (Exception e) { log.error(e.toString()); diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/FaultHandler.java b/src/main/java/io/bitsquare/trade/protocol/FaultHandler.java similarity index 63% rename from src/main/java/io/bitsquare/trade/protocol/tasks/FaultHandler.java rename to src/main/java/io/bitsquare/trade/protocol/FaultHandler.java index f2d4a6ce2d..e2ff5b0da4 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/FaultHandler.java +++ b/src/main/java/io/bitsquare/trade/protocol/FaultHandler.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.tasks; +package io.bitsquare.trade.protocol; public interface FaultHandler { diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/ResultHandler.java b/src/main/java/io/bitsquare/trade/protocol/ResultHandler.java similarity index 57% rename from src/main/java/io/bitsquare/trade/protocol/tasks/ResultHandler.java rename to src/main/java/io/bitsquare/trade/protocol/ResultHandler.java index 9d9670e880..e4d774f4dc 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/ResultHandler.java +++ b/src/main/java/io/bitsquare/trade/protocol/ResultHandler.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.tasks; +package io.bitsquare.trade.protocol; public interface ResultHandler { diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/AcceptTakeOfferRequestMessage.java b/src/main/java/io/bitsquare/trade/protocol/messages/offerer/AcceptTakeOfferRequestMessage.java deleted file mode 100644 index f4876bf212..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/AcceptTakeOfferRequestMessage.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.bitsquare.trade.protocol.messages.offerer; - -import io.bitsquare.msg.TradeMessage; -import java.io.Serializable; - -public class AcceptTakeOfferRequestMessage implements Serializable, TradeMessage -{ - private static final long serialVersionUID = 6177387534087739018L; - private final String tradeId; - - public AcceptTakeOfferRequestMessage(String tradeId) - { - this.tradeId = tradeId; - } - - - @Override - public String getTradeId() - { - return tradeId; - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/RejectTakeOfferRequestMessage.java b/src/main/java/io/bitsquare/trade/protocol/messages/offerer/RejectTakeOfferRequestMessage.java deleted file mode 100644 index 78ee7255d5..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/RejectTakeOfferRequestMessage.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.bitsquare.trade.protocol.messages.offerer; - -import io.bitsquare.msg.TradeMessage; -import java.io.Serializable; - -public class RejectTakeOfferRequestMessage implements Serializable, TradeMessage -{ - private static final long serialVersionUID = -8088557759642128139L; - private final String tradeId; - - public RejectTakeOfferRequestMessage(String tradeId) - { - this.tradeId = tradeId; - } - - @Override - public String getTradeId() - { - return tradeId; - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/BankTransferInitedMessage.java b/src/main/java/io/bitsquare/trade/protocol/offerer/BankTransferInitedMessage.java similarity index 92% rename from src/main/java/io/bitsquare/trade/protocol/messages/offerer/BankTransferInitedMessage.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/BankTransferInitedMessage.java index c658da20bf..346dc45bc6 100644 --- a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/BankTransferInitedMessage.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/BankTransferInitedMessage.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.messages.offerer; +package io.bitsquare.trade.protocol.offerer; import io.bitsquare.msg.TradeMessage; import java.io.Serializable; @@ -16,7 +16,8 @@ public class BankTransferInitedMessage implements Serializable, TradeMessage private BigInteger takerPaybackAmount; private String offererPayoutAddress; - public BankTransferInitedMessage(String tradeId, String depositTxAsHex, + public BankTransferInitedMessage(String tradeId, + String depositTxAsHex, String offererSignatureR, String offererSignatureS, BigInteger offererPaybackAmount, diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/CreateDepositTx.java b/src/main/java/io/bitsquare/trade/protocol/offerer/CreateDepositTx.java similarity index 85% rename from src/main/java/io/bitsquare/trade/protocol/tasks/offerer/CreateDepositTx.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/CreateDepositTx.java index 19711509e1..15e755fc0f 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/CreateDepositTx.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/CreateDepositTx.java @@ -1,10 +1,10 @@ -package io.bitsquare.trade.protocol.tasks.offerer; +package io.bitsquare.trade.protocol.offerer; import com.google.bitcoin.core.InsufficientMoneyException; import com.google.bitcoin.core.Transaction; import com.google.bitcoin.core.Utils; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; +import io.bitsquare.trade.protocol.FaultHandler; import java.math.BigInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,11 +24,7 @@ public class CreateDepositTx try { String offererPubKey = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString(); - Transaction transaction = walletFacade.offererCreatesMSTxAndAddPayment(collateralAmount, - offererPubKey, - takerMultiSigPubKey, - arbitratorPubKeyAsHex, - tradeId); + Transaction transaction = walletFacade.offererCreatesMSTxAndAddPayment(collateralAmount, offererPubKey, takerMultiSigPubKey, arbitratorPubKeyAsHex, tradeId); String preparedOffererDepositTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize()); long offererTxOutIndex = transaction.getInput(0).getOutpoint().getIndex(); diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/DepositTxPublishedMessage.java b/src/main/java/io/bitsquare/trade/protocol/offerer/DepositTxPublishedMessage.java similarity index 92% rename from src/main/java/io/bitsquare/trade/protocol/messages/offerer/DepositTxPublishedMessage.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/DepositTxPublishedMessage.java index fbbc92d7d0..198cf26182 100644 --- a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/DepositTxPublishedMessage.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/DepositTxPublishedMessage.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.messages.offerer; +package io.bitsquare.trade.protocol.offerer; import io.bitsquare.msg.TradeMessage; import java.io.Serializable; diff --git a/src/main/java/io/bitsquare/trade/protocol/offerer/HandleTakeOfferRequest.java b/src/main/java/io/bitsquare/trade/protocol/offerer/HandleTakeOfferRequest.java new file mode 100644 index 0000000000..7a5996e4da --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/HandleTakeOfferRequest.java @@ -0,0 +1,44 @@ +package io.bitsquare.trade.protocol.offerer; + +import io.bitsquare.msg.MessageFacade; +import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.protocol.FaultHandler; +import net.tomp2p.peers.PeerAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HandleTakeOfferRequest +{ + private static final Logger log = LoggerFactory.getLogger(HandleTakeOfferRequest.class); + + public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade.State tradeState, String tradeId) + { + boolean takeOfferRequestAccepted = tradeState == Trade.State.OPEN; + if (!takeOfferRequestAccepted) + { + log.info("Received take offer request but the offer not marked as open anymore."); + } + messageFacade.sendTradeMessage(peerAddress, new RespondToTakeOfferRequestMessage(tradeId, takeOfferRequestAccepted), new OutgoingTradeMessageListener() + { + @Override + public void onResult() + { + log.trace("RespondToTakeOfferRequestMessage successfully arrived at peer"); + resultHandler.onResult(takeOfferRequestAccepted); + } + + @Override + public void onFailed() + { + log.error("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer"); + faultHandler.onFault(new Exception("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer")); + } + }); + } + + public interface ResultHandler + { + void onResult(boolean takeOfferRequestAccepted); + } +} diff --git a/src/main/java/io/bitsquare/trade/protocol/offerer/OffererAsBuyerProtocol.java b/src/main/java/io/bitsquare/trade/protocol/offerer/ProtocolForOffererAsBuyer.java similarity index 57% rename from src/main/java/io/bitsquare/trade/protocol/offerer/OffererAsBuyerProtocol.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/ProtocolForOffererAsBuyer.java index 60761aff2c..a31a220141 100644 --- a/src/main/java/io/bitsquare/trade/protocol/offerer/OffererAsBuyerProtocol.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/ProtocolForOffererAsBuyer.java @@ -10,368 +10,39 @@ import io.bitsquare.msg.MessageFacade; import io.bitsquare.trade.Contract; import io.bitsquare.trade.Offer; import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage; -import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage; -import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage; -import io.bitsquare.trade.protocol.tasks.offerer.*; +import io.bitsquare.trade.protocol.taker.PayoutTxPublishedMessage; +import io.bitsquare.trade.protocol.taker.RequestOffererPublishDepositTxMessage; +import io.bitsquare.trade.protocol.taker.TakeOfferFeePayedMessage; import io.bitsquare.user.User; import java.math.BigInteger; import net.tomp2p.peers.PeerAddress; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Preconditions.*; import static io.bitsquare.util.Validator.*; /** * Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing from the peer. - * That class handles the role of the offerer as the Bitcoin buyer. + *

+ * This class handles the role of the offerer as the Bitcoin buyer. + *

* It uses sub tasks to not pollute the main class too much with all the async result/fault handling. - * Any data from incoming messages as well data used to send to the peer need to be validated before further processing. + * Any data from incoming messages need to be validated before further processing. */ -public class OffererAsBuyerProtocol +public class ProtocolForOffererAsBuyer { - private static final Logger log = LoggerFactory.getLogger(OffererAsBuyerProtocol.class); - public final PeerAddress peerAddress; - // provided data - private final String id; - private final Trade trade; - private final OffererAsBuyerProtocolListener listener; - private final MessageFacade messageFacade; - private final WalletFacade walletFacade; - private final BlockChainFacade blockChainFacade; - private final CryptoFacade cryptoFacade; - private final User user; - private final String tradeId; - private final Offer offer; - - // data written/read by tasks - private String preparedOffererDepositTxAsHex; - private long offererTxOutIndex; - // data written by messages, read by tasks - private String takeOfferFeeTxId; - private String takerMultiSigPubKey; - private String takerPayoutAddress; - private String peersAccountId; - private BankAccount peersBankAccount; - private String takerMessagePubKey; - private String peersContractAsJson; - private String signedTakerDepositTxAsHex; - private String txConnOutAsHex; - private String txScriptSigAsHex; - private long takerTxOutIndex; - // private - private State state; - - public OffererAsBuyerProtocol(Trade trade, - PeerAddress peerAddress, - MessageFacade messageFacade, - WalletFacade walletFacade, - BlockChainFacade blockChainFacade, - CryptoFacade cryptoFacade, - User user, - OffererAsBuyerProtocolListener listener) - { - this.trade = trade; - this.peerAddress = peerAddress; - this.listener = listener; - this.messageFacade = messageFacade; - this.walletFacade = walletFacade; - this.blockChainFacade = blockChainFacade; - this.cryptoFacade = cryptoFacade; - this.user = user; - - id = trade.getId(); - - tradeId = trade.getId(); - offer = trade.getOffer(); - - state = State.Init; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor - /////////////////////////////////////////////////////////////////////////////////////////// - - public void start() - { - log.debug("start"); - HandleTakeOfferRequest.run(this::onResultHandleTakeOfferRequest, this::onFault, peerAddress, messageFacade, trade.getState(), tradeId); - state = State.HandleTakeOfferRequest; - } - - public void onResultHandleTakeOfferRequest(Trade.State tradeState) - { - log.debug("onResultHandleTakeOfferRequest"); - trade.setState(tradeState); - messageFacade.removeOffer(offer); - listener.onOfferAccepted(offer); - listener.onWaitingForPeerResponse(state); - } - - public void onTakeOfferFeePayedMessage(TakeOfferFeePayedMessage message) - { - log.debug("onTakeOfferFeePayedMessage"); - - // validation - checkState(state == State.HandleTakeOfferRequest); - checkNotNull(message); - String takeOfferFeeTxId = nonEmptyStringOf(message.getTakeOfferFeeTxId()); - BigInteger tradeAmount = nonNegativeBigIntegerOf(nonZeroBigIntegerOf(message.getTradeAmount())); - String takerMultiSigPubKey = nonEmptyStringOf(message.getTakerMultiSigPubKey()); - - // apply new state - state = State.onTakeOfferFeePayedMessage; - this.takeOfferFeeTxId = takeOfferFeeTxId; - this.takerMultiSigPubKey = takerMultiSigPubKey; - trade.setTakeOfferFeeTxID(takeOfferFeeTxId); - trade.setTradeAmount(tradeAmount); - - // next task - VerifyTakeOfferFeePayment.run(this::onResultVerifyTakeOfferFeePayment, this::onFault, walletFacade, takeOfferFeeTxId); - state = State.VerifyTakeOfferFeePayment; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onResultVerifyTakeOfferFeePayment() - { - log.debug("onResultVerifyTakeOfferFeePayment"); - BigInteger collateralAmount = trade.getCollateralAmount(); - String arbitratorPubKeyAsHex = offer.getArbitrator().getPubKeyAsHex(); - - CreateDepositTx.run(this::onResultCreateDepositTx, - this::onFault, - walletFacade, - tradeId, - collateralAmount, - takerMultiSigPubKey, - arbitratorPubKeyAsHex); - - state = State.CreateDepositTx; - } - - public void onResultCreateDepositTx(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex) - { - log.debug("onResultCreateDepositTx"); - this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex; - this.offererTxOutIndex = offererTxOutIndex; - - BankAccount bankAccount = user.getBankAccount(trade.getOffer().getBankAccountId()); - String accountId = user.getAccountId(); - - RequestTakerDepositPayment.run(this::onResultRequestTakerDepositPayment, - this::onFault, - peerAddress, - messageFacade, - tradeId, - bankAccount, - accountId, - offererPubKey, - preparedOffererDepositTxAsHex, - offererTxOutIndex); - - state = State.RequestTakerDepositPayment; - } - - public void onResultRequestTakerDepositPayment() - { - log.debug("onResultRequestTakerDepositPayment"); - listener.onWaitingForPeerResponse(state); - } - - public void onRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message) - { - log.debug("onRequestOffererPublishDepositTxMessage"); - - // validation - checkState(state == State.RequestTakerDepositPayment); - checkNotNull(message); - String takerPayoutAddress = nonEmptyStringOf(message.getTakerPayoutAddress()); - String peersAccountId = nonEmptyStringOf(message.getAccountId()); - BankAccount peersBankAccount = checkNotNull(message.getBankAccount()); - String takerMessagePubKey = nonEmptyStringOf(message.getTakerMessagePubKey()); - String peersContractAsJson = nonEmptyStringOf(message.getContractAsJson()); - String signedTakerDepositTxAsHex = nonEmptyStringOf(message.getSignedTakerDepositTxAsHex()); - String txConnOutAsHex = nonEmptyStringOf(message.getTxConnOutAsHex()); - String txScriptSigAsHex = nonEmptyStringOf(message.getTxScriptSigAsHex()); - long takerTxOutIndex = nonNegativeLongOf(message.getTakerTxOutIndex()); - - // apply new state - state = State.onRequestOffererPublishDepositTxMessage; - this.takerPayoutAddress = takerPayoutAddress; - this.peersAccountId = peersAccountId; - this.peersBankAccount = peersBankAccount; - this.takerMessagePubKey = takerMessagePubKey; - this.peersContractAsJson = peersContractAsJson; - this.signedTakerDepositTxAsHex = signedTakerDepositTxAsHex; - this.txConnOutAsHex = txConnOutAsHex; - this.txScriptSigAsHex = txScriptSigAsHex; - this.takerTxOutIndex = takerTxOutIndex; - - // next task - VerifyTakerAccount.run(this::onResultVerifyTakerAccount, this::onFault, blockChainFacade, peersAccountId, peersBankAccount); - state = State.VerifyTakerAccount; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onResultVerifyTakerAccount() - { - log.debug("onResultVerifyTakerAccount"); - - String accountId = user.getAccountId(); - BigInteger tradeAmount = trade.getTradeAmount(); - String messagePubKeyAsHex = user.getMessagePubKeyAsHex(); - BankAccount bankAccount = user.getBankAccount(offer.getBankAccountId()); - ECKey registrationKey = walletFacade.getRegistrationAddressInfo().getKey(); - - VerifyAndSignContract.run(this::onResultVerifyAndSignContract, - this::onFault, - cryptoFacade, - accountId, - tradeAmount, - takeOfferFeeTxId, - messagePubKeyAsHex, - offer, - peersAccountId, - bankAccount, - peersBankAccount, - takerMessagePubKey, - peersContractAsJson, - registrationKey); - - state = State.VerifyAndSignContract; - } - - public void onResultVerifyAndSignContract(Contract contract, String contractAsJson, String signature) - { - log.debug("onResultVerifyAndSignContract"); - - trade.setContract(contract); - trade.setContractAsJson(contractAsJson); - trade.setContractTakerSignature(signature); - - SignAndPublishDepositTx.run(this::onResultSignAndPublishDepositTx, - this::onFault, - walletFacade, - preparedOffererDepositTxAsHex, - signedTakerDepositTxAsHex, - txConnOutAsHex, - txScriptSigAsHex, - offererTxOutIndex, - takerTxOutIndex); - state = State.SignAndPublishDepositTx; - } - - public void onResultSignAndPublishDepositTx(Transaction transaction) - { - log.debug("onResultSignAndPublishDepositTx"); - - trade.setDepositTransaction(transaction); - listener.onDepositTxPublished(transaction.getHashAsString()); - - Transaction depositTransaction = trade.getDepositTransaction(); - SendDepositTxIdToTaker.run(this::onResultSendDepositTxIdToTaker, this::onFault, peerAddress, messageFacade, tradeId, depositTransaction); - state = State.SendDepositTxIdToTaker; - } - - public void onResultSendDepositTxIdToTaker() - { - log.debug("onResultSendDepositTxIdToTaker"); - - SetupListenerForBlockChainConfirmation.run(this::onResultSetupListenerForBlockChainConfirmation, this::onFault, trade.getDepositTransaction(), listener); - state = State.SetupListenerForBlockChainConfirmation; - } - - public void onResultSetupListenerForBlockChainConfirmation() - { - log.debug("onResultSetupListenerForBlockChainConfirmation"); - - state = State.onResultSetupListenerForBlockChainConfirmation; - listener.onWaitingForUserInteraction(state); - } - - // Triggered from UI event: Button click "Bank transfer inited" - public void onUIEventBankTransferInited() - { - log.debug("onUIEventBankTransferInited"); - - // validation - checkState(state == State.onResultSetupListenerForBlockChainConfirmation); - - state = State.onUIEventBankTransferInited; - - // next task - String depositTransactionId = trade.getDepositTransaction().getHashAsString(); - String offererPayoutAddress = walletFacade.getAddressInfoByTradeID(tradeId).getAddressString(); - BigInteger collateral = trade.getCollateralAmount(); - BigInteger tradeAmount = trade.getTradeAmount(); - SendSignedPayoutTx.run(this::onResultSendSignedPayoutTx, this::onFault, peerAddress, messageFacade, walletFacade, tradeId, takerPayoutAddress, offererPayoutAddress, depositTransactionId, collateral, tradeAmount); - state = State.SendSignedPayoutTx; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Triggered UI event - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onResultSendSignedPayoutTx() - { - log.debug("onResultSendSignedPayoutTx"); - - listener.onWaitingForPeerResponse(state); - } - - public void onPayoutTxPublishedMessage(PayoutTxPublishedMessage tradeMessage) - { - log.debug("onPayoutTxPublishedMessage"); - - // validation - checkState(state == State.SendSignedPayoutTx); - String payoutTxAsHex = nonEmptyStringOf(tradeMessage.getPayoutTxAsHex()); - - state = State.onPayoutTxPublishedMessage; - - // next task - listener.onPayoutTxPublished(payoutTxAsHex); - listener.onCompleted(state); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - public String getId() - { - return id; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Getters, Setters - /////////////////////////////////////////////////////////////////////////////////////////// - - // generic fault handler - private void onFault(Throwable throwable) - { - listener.onFault(throwable, state); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Private - /////////////////////////////////////////////////////////////////////////////////////////// + private static final Logger log = LoggerFactory.getLogger(ProtocolForOffererAsBuyer.class); + private final String arbitratorPubKey; + private final BigInteger collateral; + private final BankAccount bankAccount; + private final String accountId; + private final BigInteger tradeAmount; + private final String messagePubKey; + private final ECKey accountKey; + private final String payoutAddress; public enum State { @@ -397,4 +68,351 @@ public class OffererAsBuyerProtocol onPayoutTxPublishedMessage } + private final Trade trade; + private final PeerAddress peerAddress; + private final MessageFacade messageFacade; + private final WalletFacade walletFacade; + private final BlockChainFacade blockChainFacade; + private final CryptoFacade cryptoFacade; + private final ProtocolForOffererAsBuyerListener listener; + + private final String id; + private final String tradeId; + private final Offer offer; + + private State state; + + // data written/read by tasks + private String preparedOffererDepositTxAsHex; + private long offererTxOutIndex; + + // data written by messages, read by tasks + private String takeOfferFeeTxId; + private String takerPubKey; + private String peersPayoutAddress; + private String peersAccountId; + private BankAccount peersBankAccount; + private String peersMessagePubKey; + private String peersContractAsJson; + private String signedTakerDepositTxAsHex; + private String txConnOutAsHex; + private String txScriptSigAsHex; + private long takerTxOutIndex; + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + + public ProtocolForOffererAsBuyer(Trade trade, + PeerAddress peerAddress, + MessageFacade messageFacade, + WalletFacade walletFacade, + BlockChainFacade blockChainFacade, + CryptoFacade cryptoFacade, + User user, + ProtocolForOffererAsBuyerListener listener) + { + this.trade = trade; + this.peerAddress = peerAddress; + this.listener = listener; + this.messageFacade = messageFacade; + this.walletFacade = walletFacade; + this.blockChainFacade = blockChainFacade; + this.cryptoFacade = cryptoFacade; + + id = trade.getId(); + + tradeId = trade.getId(); + offer = trade.getOffer(); + arbitratorPubKey = offer.getArbitrator().getPubKeyAsHex(); + collateral = trade.getCollateralAmount(); + bankAccount = user.getBankAccount(trade.getOffer().getBankAccountId()); + accountId = user.getAccountId(); + tradeAmount = trade.getTradeAmount(); + messagePubKey = user.getMessagePubKeyAsHex(); + accountKey = walletFacade.getRegistrationAddressInfo().getKey(); + payoutAddress = walletFacade.getAddressInfoByTradeID(tradeId).getAddressString(); + state = State.Init; + } + + + public void start() + { + log.debug("start called "); + HandleTakeOfferRequest.run(this::onResultHandleTakeOfferRequest, this::onFault, peerAddress, messageFacade, trade.getState(), tradeId); + state = State.HandleTakeOfferRequest; + } + + public void onResultHandleTakeOfferRequest(boolean takeOfferRequestAccepted) + { + log.debug("onResultHandleTakeOfferRequest called "); + if (takeOfferRequestAccepted) + { + trade.setState(Trade.State.ACCEPTED); + messageFacade.removeOffer(offer); + listener.onOfferAccepted(offer); + listener.onWaitingForPeerResponse(state); + } + else + { + log.info("Finish here as we have already the offer accepted."); + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message from peer + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onTakeOfferFeePayedMessage(@NotNull TakeOfferFeePayedMessage message) + { + log.debug("onTakeOfferFeePayedMessage called "); + + // validation + checkState(state == State.HandleTakeOfferRequest); + checkArgument(tradeId.equals(message.getTradeId())); + String takeOfferFeeTxId = nonEmptyStringOf(message.getTakeOfferFeeTxId()); + BigInteger tradeAmount = nonNegativeBigIntegerOf(nonZeroBigIntegerOf(message.getTradeAmount())); + String takerPubKey = nonEmptyStringOf(message.getTakerPubKey()); + + // apply new state + state = State.onTakeOfferFeePayedMessage; + this.takeOfferFeeTxId = takeOfferFeeTxId; + this.takerPubKey = takerPubKey; + trade.setTakeOfferFeeTxID(takeOfferFeeTxId); + trade.setTradeAmount(tradeAmount); + + // next task + VerifyTakeOfferFeePayment.run(this::onResultVerifyTakeOfferFeePayment, this::onFault, walletFacade, this.takeOfferFeeTxId); + state = State.VerifyTakeOfferFeePayment; + } + + public void onResultVerifyTakeOfferFeePayment() + { + log.debug("onResultVerifyTakeOfferFeePayment called "); + + CreateDepositTx.run(this::onResultCreateDepositTx, this::onFault, walletFacade, tradeId, collateral, takerPubKey, arbitratorPubKey); + + state = State.CreateDepositTx; + } + + public void onResultCreateDepositTx(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex) + { + log.debug("onResultCreateDepositTx called "); + this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex; + this.offererTxOutIndex = offererTxOutIndex; + + + RequestTakerDepositPayment.run(this::onResultRequestTakerDepositPayment, + this::onFault, + peerAddress, + messageFacade, + tradeId, + bankAccount, + accountId, + offererPubKey, + preparedOffererDepositTxAsHex, + offererTxOutIndex); + + state = State.RequestTakerDepositPayment; + } + + public void onResultRequestTakerDepositPayment() + { + log.debug("onResultRequestTakerDepositPayment called "); + listener.onWaitingForPeerResponse(state); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message from peer + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message) + { + log.debug("onRequestOffererPublishDepositTxMessage called "); + + // validation + checkState(state == State.RequestTakerDepositPayment); + checkArgument(tradeId.equals(message.getTradeId())); + String peersPayoutAddress = nonEmptyStringOf(message.getTakerPayoutAddress()); + String peersAccountId = nonEmptyStringOf(message.getTakerAccountId()); + BankAccount peersBankAccount = checkNotNull(message.getTakerBankAccount()); + String peersMessagePubKey = nonEmptyStringOf(message.getTakerMessagePubKey()); + String peersContractAsJson = nonEmptyStringOf(message.getTakerContractAsJson()); + String signedTakerDepositTxAsHex = nonEmptyStringOf(message.getSignedTakerDepositTxAsHex()); + String txConnOutAsHex = nonEmptyStringOf(message.getTxConnOutAsHex()); + String txScriptSigAsHex = nonEmptyStringOf(message.getTxScriptSigAsHex()); + long takerTxOutIndex = nonNegativeLongOf(message.getTakerTxOutIndex()); + + // apply new state + state = State.onRequestOffererPublishDepositTxMessage; + this.peersPayoutAddress = peersPayoutAddress; + this.peersAccountId = peersAccountId; + this.peersBankAccount = peersBankAccount; + this.peersMessagePubKey = peersMessagePubKey; + this.peersContractAsJson = peersContractAsJson; + this.signedTakerDepositTxAsHex = signedTakerDepositTxAsHex; + this.txConnOutAsHex = txConnOutAsHex; + this.txScriptSigAsHex = txScriptSigAsHex; + this.takerTxOutIndex = takerTxOutIndex; + + // next task + VerifyTakerAccount.run(this::onResultVerifyTakerAccount, this::onFault, blockChainFacade, this.peersAccountId, this.peersBankAccount); + state = State.VerifyTakerAccount; + } + + public void onResultVerifyTakerAccount() + { + log.debug("onResultVerifyTakerAccount called "); + + VerifyAndSignContract.run(this::onResultVerifyAndSignContract, + this::onFault, + cryptoFacade, + accountId, + tradeAmount, + takeOfferFeeTxId, + messagePubKey, + offer, + peersAccountId, + bankAccount, + peersBankAccount, + peersMessagePubKey, + peersContractAsJson, + accountKey); + + state = State.VerifyAndSignContract; + } + + public void onResultVerifyAndSignContract(Contract contract, String contractAsJson, String signature) + { + log.debug("onResultVerifyAndSignContract called "); + + trade.setContract(contract); + trade.setContractAsJson(contractAsJson); + trade.setContractTakerSignature(signature); + + SignAndPublishDepositTx.run(this::onResultSignAndPublishDepositTx, + this::onFault, + walletFacade, + preparedOffererDepositTxAsHex, + signedTakerDepositTxAsHex, + txConnOutAsHex, + txScriptSigAsHex, + offererTxOutIndex, + takerTxOutIndex); + state = State.SignAndPublishDepositTx; + } + + public void onResultSignAndPublishDepositTx(Transaction depositTransaction) + { + log.debug("onResultSignAndPublishDepositTx called "); + + trade.setDepositTransaction(depositTransaction); + listener.onDepositTxPublished(depositTransaction.getHashAsString()); + + SendDepositTxIdToTaker.run(this::onResultSendDepositTxIdToTaker, this::onFault, peerAddress, messageFacade, tradeId, depositTransaction); + state = State.SendDepositTxIdToTaker; + } + + public void onResultSendDepositTxIdToTaker() + { + log.debug("onResultSendDepositTxIdToTaker called "); + + SetupListenerForBlockChainConfirmation.run(this::onResultSetupListenerForBlockChainConfirmation, this::onFault, trade.getDepositTransaction(), listener); + state = State.SetupListenerForBlockChainConfirmation; + } + + public void onResultSetupListenerForBlockChainConfirmation() + { + log.debug("onResultSetupListenerForBlockChainConfirmation called "); + + state = State.onResultSetupListenerForBlockChainConfirmation; + listener.onWaitingForUserInteraction(state); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Triggered UI event + /////////////////////////////////////////////////////////////////////////////////////////// + + // Triggered from UI event: Button click "Bank transfer inited" + public void onUIEventBankTransferInited() + { + log.debug("onUIEventBankTransferInited called "); + + // validation + checkState(state == State.onResultSetupListenerForBlockChainConfirmation); + + + state = State.onUIEventBankTransferInited; + + // next task + String depositTransactionId = trade.getDepositTransaction().getHashAsString(); + + SendSignedPayoutTx.run(this::onResultSendSignedPayoutTx, + this::onFault, + peerAddress, + messageFacade, + walletFacade, + tradeId, + peersPayoutAddress, + payoutAddress, + depositTransactionId, + collateral, + tradeAmount); + state = State.SendSignedPayoutTx; + } + + public void onResultSendSignedPayoutTx() + { + log.debug("onResultSendSignedPayoutTx called "); + + listener.onWaitingForPeerResponse(state); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message from peer + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onPayoutTxPublishedMessage(PayoutTxPublishedMessage message) + { + log.debug("onPayoutTxPublishedMessage called "); + + // validation + checkState(state == State.SendSignedPayoutTx); + checkArgument(tradeId.equals(message.getTradeId())); + String payoutTxAsHex = nonEmptyStringOf(message.getPayoutTxAsHex()); + + state = State.onPayoutTxPublishedMessage; + + // next task + listener.onPayoutTxPublished(payoutTxAsHex); + listener.onCompleted(state); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Getters, Setters + /////////////////////////////////////////////////////////////////////////////////////////// + + public String getId() + { + return id; + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Private + /////////////////////////////////////////////////////////////////////////////////////////// + + // generic fault handler + private void onFault(Throwable throwable) + { + listener.onFault(throwable, state); + } + + } diff --git a/src/main/java/io/bitsquare/trade/protocol/offerer/OffererAsBuyerProtocolListener.java b/src/main/java/io/bitsquare/trade/protocol/offerer/ProtocolForOffererAsBuyerListener.java similarity index 55% rename from src/main/java/io/bitsquare/trade/protocol/offerer/OffererAsBuyerProtocolListener.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/ProtocolForOffererAsBuyerListener.java index 1d062d28db..ac851d7434 100644 --- a/src/main/java/io/bitsquare/trade/protocol/offerer/OffererAsBuyerProtocolListener.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/ProtocolForOffererAsBuyerListener.java @@ -3,7 +3,7 @@ package io.bitsquare.trade.protocol.offerer; import com.google.bitcoin.core.TransactionConfidence; import io.bitsquare.trade.Offer; -public interface OffererAsBuyerProtocolListener +public interface ProtocolForOffererAsBuyerListener { void onOfferAccepted(Offer offer); @@ -15,11 +15,11 @@ public interface OffererAsBuyerProtocolListener void onPayoutTxPublished(String payoutTxID); - void onFault(Throwable throwable, OffererAsBuyerProtocol.State state); + void onFault(Throwable throwable, ProtocolForOffererAsBuyer.State state); - void onWaitingForPeerResponse(OffererAsBuyerProtocol.State state); + void onWaitingForPeerResponse(ProtocolForOffererAsBuyer.State state); - void onCompleted(OffererAsBuyerProtocol.State state); + void onCompleted(ProtocolForOffererAsBuyer.State state); - void onWaitingForUserInteraction(OffererAsBuyerProtocol.State state); + void onWaitingForUserInteraction(ProtocolForOffererAsBuyer.State state); } diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/RequestTakerDepositPayment.java b/src/main/java/io/bitsquare/trade/protocol/offerer/RequestTakerDepositPayment.java similarity index 78% rename from src/main/java/io/bitsquare/trade/protocol/tasks/offerer/RequestTakerDepositPayment.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/RequestTakerDepositPayment.java index 888b2e846f..858d0ec58f 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/RequestTakerDepositPayment.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/RequestTakerDepositPayment.java @@ -1,11 +1,10 @@ -package io.bitsquare.trade.protocol.tasks.offerer; +package io.bitsquare.trade.protocol.offerer; import io.bitsquare.bank.BankAccount; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; -import io.bitsquare.trade.protocol.messages.offerer.RequestTakerDepositPaymentMessage; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; import net.tomp2p.peers.PeerAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,12 +24,7 @@ public class RequestTakerDepositPayment String preparedOffererDepositTxAsHex, long offererTxOutIndex) { - RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(tradeId, - bankAccount, - accountId, - offererPubKey, - preparedOffererDepositTxAsHex, - offererTxOutIndex); + RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(tradeId, bankAccount, accountId, offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex); messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener() { @Override diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/RequestTakerDepositPaymentMessage.java b/src/main/java/io/bitsquare/trade/protocol/offerer/RequestTakerDepositPaymentMessage.java similarity index 94% rename from src/main/java/io/bitsquare/trade/protocol/messages/offerer/RequestTakerDepositPaymentMessage.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/RequestTakerDepositPaymentMessage.java index 8fc0366e30..69579b1ae8 100644 --- a/src/main/java/io/bitsquare/trade/protocol/messages/offerer/RequestTakerDepositPaymentMessage.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/RequestTakerDepositPaymentMessage.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.messages.offerer; +package io.bitsquare.trade.protocol.offerer; import io.bitsquare.bank.BankAccount; import io.bitsquare.msg.TradeMessage; @@ -9,7 +9,6 @@ public class RequestTakerDepositPaymentMessage implements Serializable, TradeMes private static final long serialVersionUID = -3988720410493712913L; private final String tradeId; - private BankAccount bankAccount; private String accountID; private String offererPubKey; @@ -37,7 +36,7 @@ public class RequestTakerDepositPaymentMessage implements Serializable, TradeMes return bankAccount; } - public String getAccountID() + public String getAccountId() { return accountID; } diff --git a/src/main/java/io/bitsquare/trade/protocol/offerer/RespondToTakeOfferRequestMessage.java b/src/main/java/io/bitsquare/trade/protocol/offerer/RespondToTakeOfferRequestMessage.java new file mode 100644 index 0000000000..3636b7c7e2 --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/RespondToTakeOfferRequestMessage.java @@ -0,0 +1,28 @@ +package io.bitsquare.trade.protocol.offerer; + +import io.bitsquare.msg.TradeMessage; +import java.io.Serializable; + +public class RespondToTakeOfferRequestMessage implements Serializable, TradeMessage +{ + private static final long serialVersionUID = 6177387534087739018L; + private final String tradeId; + private boolean takeOfferRequestAccepted; + + public RespondToTakeOfferRequestMessage(String tradeId, boolean takeOfferRequestAccepted) + { + this.tradeId = tradeId; + this.takeOfferRequestAccepted = takeOfferRequestAccepted; + } + + @Override + public String getTradeId() + { + return tradeId; + } + + public boolean isTakeOfferRequestAccepted() + { + return takeOfferRequestAccepted; + } +} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SendDepositTxIdToTaker.java b/src/main/java/io/bitsquare/trade/protocol/offerer/SendDepositTxIdToTaker.java similarity index 85% rename from src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SendDepositTxIdToTaker.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/SendDepositTxIdToTaker.java index d9349cb716..4945723c76 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SendDepositTxIdToTaker.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/SendDepositTxIdToTaker.java @@ -1,12 +1,11 @@ -package io.bitsquare.trade.protocol.tasks.offerer; +package io.bitsquare.trade.protocol.offerer; import com.google.bitcoin.core.Transaction; import com.google.bitcoin.core.Utils; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; -import io.bitsquare.trade.protocol.messages.offerer.DepositTxPublishedMessage; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; import net.tomp2p.peers.PeerAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SendSignedPayoutTx.java b/src/main/java/io/bitsquare/trade/protocol/offerer/SendSignedPayoutTx.java similarity index 73% rename from src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SendSignedPayoutTx.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/SendSignedPayoutTx.java index 2374451ab9..a6b3f90f74 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SendSignedPayoutTx.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/SendSignedPayoutTx.java @@ -1,12 +1,11 @@ -package io.bitsquare.trade.protocol.tasks.offerer; +package io.bitsquare.trade.protocol.offerer; import com.google.bitcoin.core.ECKey; import io.bitsquare.btc.WalletFacade; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; -import io.bitsquare.trade.protocol.messages.offerer.BankTransferInitedMessage; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; import java.math.BigInteger; import javafx.util.Pair; import net.tomp2p.peers.PeerAddress; @@ -34,11 +33,7 @@ public class SendSignedPayoutTx BigInteger offererPaybackAmount = tradeAmount.add(collateral); BigInteger takerPaybackAmount = collateral; - Pair result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransactionId, - offererPaybackAmount, - takerPaybackAmount, - takerPayoutAddress, - tradeId); + Pair result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransactionId, offererPaybackAmount, takerPaybackAmount, takerPayoutAddress, tradeId); ECKey.ECDSASignature offererSignature = result.getKey(); String offererSignatureR = offererSignature.r.toString(); @@ -46,12 +41,12 @@ public class SendSignedPayoutTx String depositTxAsHex = result.getValue(); BankTransferInitedMessage tradeMessage = new BankTransferInitedMessage(tradeId, - depositTxAsHex, - offererSignatureR, - offererSignatureS, - offererPaybackAmount, - takerPaybackAmount, - offererPayoutAddress); + depositTxAsHex, + offererSignatureR, + offererSignatureS, + offererPaybackAmount, + takerPaybackAmount, + offererPayoutAddress); messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener() { diff --git a/src/main/java/io/bitsquare/trade/protocol/offerer/SetupListenerForBlockChainConfirmation.java b/src/main/java/io/bitsquare/trade/protocol/offerer/SetupListenerForBlockChainConfirmation.java new file mode 100644 index 0000000000..c9276834be --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/SetupListenerForBlockChainConfirmation.java @@ -0,0 +1,38 @@ +package io.bitsquare.trade.protocol.offerer; + +import com.google.bitcoin.core.Transaction; +import com.google.bitcoin.core.TransactionConfidence; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SetupListenerForBlockChainConfirmation +{ + private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class); + + public static void run(ResultHandler resultHandler, FaultHandler faultHandler, Transaction depositTransaction, ProtocolForOffererAsBuyerListener listener) + { //TODO + // sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain(); + + depositTransaction.getConfidence().addEventListener(new TransactionConfidence.Listener() + { + @Override + public void onConfidenceChanged(Transaction tx, ChangeReason reason) + { + log.trace("onConfidenceChanged " + tx.getConfidence()); + if (reason == ChangeReason.SEEN_PEERS) + { + listener.onDepositTxConfirmedUpdate(tx.getConfidence()); + } + if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) + { + listener.onDepositTxConfirmedInBlockchain(); + depositTransaction.getConfidence().removeEventListener(this); + log.trace("Tx is in blockchain"); + resultHandler.onResult(); + } + } + }); + } +} diff --git a/src/main/java/io/bitsquare/trade/protocol/offerer/SignAndPublishDepositTx.java b/src/main/java/io/bitsquare/trade/protocol/offerer/SignAndPublishDepositTx.java new file mode 100644 index 0000000000..cdb0dc8b6f --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/SignAndPublishDepositTx.java @@ -0,0 +1,60 @@ +package io.bitsquare.trade.protocol.offerer; + +import com.google.bitcoin.core.Transaction; +import com.google.common.util.concurrent.FutureCallback; +import io.bitsquare.btc.WalletFacade; +import io.bitsquare.trade.protocol.FaultHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SignAndPublishDepositTx +{ + private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class); + + public static void run(ResultHandler resultHandler, + FaultHandler faultHandler, + WalletFacade walletFacade, + String preparedOffererDepositTxAsHex, + String signedTakerDepositTxAsHex, + String txConnOutAsHex, + String txScriptSigAsHex, + long offererTxOutIndex, + long takerTxOutIndex) + { + try + { + walletFacade.offererSignAndPublishTx(preparedOffererDepositTxAsHex, + signedTakerDepositTxAsHex, + txConnOutAsHex, + txScriptSigAsHex, + offererTxOutIndex, + takerTxOutIndex, + new FutureCallback() + { + @Override + public void onSuccess(Transaction transaction) + { + log.trace("offererSignAndPublishTx succeeded " + transaction); + resultHandler.onResult(transaction); + } + + @Override + public void onFailure(Throwable t) + { + log.error("offererSignAndPublishTx faultHandler.onFault:" + t); + faultHandler.onFault(t); + } + }); + } catch (Exception e) + { + log.error("offererSignAndPublishTx faultHandler.onFault:" + e); + faultHandler.onFault(e); + } + } + + public interface ResultHandler + { + void onResult(Transaction depositTransaction); + } + +} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyAndSignContract.java b/src/main/java/io/bitsquare/trade/protocol/offerer/VerifyAndSignContract.java similarity index 84% rename from src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyAndSignContract.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/VerifyAndSignContract.java index 284f4d2ba0..cf659f9d46 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyAndSignContract.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/VerifyAndSignContract.java @@ -1,11 +1,11 @@ -package io.bitsquare.trade.protocol.tasks.offerer; +package io.bitsquare.trade.protocol.offerer; import com.google.bitcoin.core.ECKey; import io.bitsquare.bank.BankAccount; import io.bitsquare.crypto.CryptoFacade; import io.bitsquare.trade.Contract; import io.bitsquare.trade.Offer; -import io.bitsquare.trade.protocol.tasks.FaultHandler; +import io.bitsquare.trade.protocol.FaultHandler; import io.bitsquare.util.Utilities; import java.math.BigInteger; import org.slf4j.Logger; @@ -30,15 +30,7 @@ public class VerifyAndSignContract String peersContractAsJson, ECKey registrationKey) { - Contract contract = new Contract(offer, - tradeAmount, - takeOfferFeeTxId, - accountId, - peersAccountId, - bankAccount, - peersBankAccount, - messagePubKeyAsHex, - takerMessagePubKey); + Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, accountId, peersAccountId, bankAccount, peersBankAccount, messagePubKeyAsHex, takerMessagePubKey); String contractAsJson = Utilities.objectToJson(contract); // log.trace("Offerer contract created: " + contract); diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyTakeOfferFeePayment.java b/src/main/java/io/bitsquare/trade/protocol/offerer/VerifyTakeOfferFeePayment.java similarity index 79% rename from src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyTakeOfferFeePayment.java rename to src/main/java/io/bitsquare/trade/protocol/offerer/VerifyTakeOfferFeePayment.java index d6923290cb..fc14c28635 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyTakeOfferFeePayment.java +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/VerifyTakeOfferFeePayment.java @@ -1,8 +1,8 @@ -package io.bitsquare.trade.protocol.tasks.offerer; +package io.bitsquare.trade.protocol.offerer; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/bitsquare/trade/protocol/offerer/VerifyTakerAccount.java b/src/main/java/io/bitsquare/trade/protocol/offerer/VerifyTakerAccount.java new file mode 100644 index 0000000000..ff5f598a79 --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/offerer/VerifyTakerAccount.java @@ -0,0 +1,20 @@ +package io.bitsquare.trade.protocol.offerer; + +import io.bitsquare.bank.BankAccount; +import io.bitsquare.btc.BlockChainFacade; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; +import io.bitsquare.trade.protocol.shared.VerifyPeerAccount; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VerifyTakerAccount +{ + private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class); + + public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount) + { + VerifyPeerAccount.run(resultHandler, faultHandler, blockChainFacade, peersAccountId, peersBankAccount); + } + +} diff --git a/src/main/java/io/bitsquare/trade/protocol/mock/BuyOffererPaymentProcess.java b/src/main/java/io/bitsquare/trade/protocol/old/BuyOffererPaymentProcess.java similarity index 95% rename from src/main/java/io/bitsquare/trade/protocol/mock/BuyOffererPaymentProcess.java rename to src/main/java/io/bitsquare/trade/protocol/old/BuyOffererPaymentProcess.java index 9acc86d0de..c2bb983dd2 100644 --- a/src/main/java/io/bitsquare/trade/protocol/mock/BuyOffererPaymentProcess.java +++ b/src/main/java/io/bitsquare/trade/protocol/old/BuyOffererPaymentProcess.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.mock; +package io.bitsquare.trade.protocol.old; //TODO not used but let it for reference until all use cases are impl. class BuyOffererPaymentProcess extends PaymentProcess diff --git a/src/main/java/io/bitsquare/trade/protocol/mock/BuyTakerPaymentProcess.java b/src/main/java/io/bitsquare/trade/protocol/old/BuyTakerPaymentProcess.java similarity index 95% rename from src/main/java/io/bitsquare/trade/protocol/mock/BuyTakerPaymentProcess.java rename to src/main/java/io/bitsquare/trade/protocol/old/BuyTakerPaymentProcess.java index 28c44db0f9..0c4e20efcc 100644 --- a/src/main/java/io/bitsquare/trade/protocol/mock/BuyTakerPaymentProcess.java +++ b/src/main/java/io/bitsquare/trade/protocol/old/BuyTakerPaymentProcess.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.mock; +package io.bitsquare.trade.protocol.old; //TODO not used but let it for reference until all use cases are impl. public class BuyTakerPaymentProcess extends PaymentProcess diff --git a/src/main/java/io/bitsquare/trade/protocol/mock/PaymentProcess.java b/src/main/java/io/bitsquare/trade/protocol/old/PaymentProcess.java similarity index 99% rename from src/main/java/io/bitsquare/trade/protocol/mock/PaymentProcess.java rename to src/main/java/io/bitsquare/trade/protocol/old/PaymentProcess.java index 078c838505..b3726ab795 100644 --- a/src/main/java/io/bitsquare/trade/protocol/mock/PaymentProcess.java +++ b/src/main/java/io/bitsquare/trade/protocol/old/PaymentProcess.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.mock; +package io.bitsquare.trade.protocol.old; import com.google.inject.Inject; import io.bitsquare.btc.BlockChainFacade; diff --git a/src/main/java/io/bitsquare/trade/protocol/mock/SellOffererPaymentProcess.java b/src/main/java/io/bitsquare/trade/protocol/old/SellOffererPaymentProcess.java similarity index 95% rename from src/main/java/io/bitsquare/trade/protocol/mock/SellOffererPaymentProcess.java rename to src/main/java/io/bitsquare/trade/protocol/old/SellOffererPaymentProcess.java index e643a4f85f..8a4a9f7553 100644 --- a/src/main/java/io/bitsquare/trade/protocol/mock/SellOffererPaymentProcess.java +++ b/src/main/java/io/bitsquare/trade/protocol/old/SellOffererPaymentProcess.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.mock; +package io.bitsquare.trade.protocol.old; //TODO not used but let it for reference until all use cases are impl. class SellOffererPaymentProcess extends PaymentProcess diff --git a/src/main/java/io/bitsquare/trade/protocol/mock/SellTakerPaymentProcess.java b/src/main/java/io/bitsquare/trade/protocol/old/SellTakerPaymentProcess.java similarity index 95% rename from src/main/java/io/bitsquare/trade/protocol/mock/SellTakerPaymentProcess.java rename to src/main/java/io/bitsquare/trade/protocol/old/SellTakerPaymentProcess.java index e265638f5d..7e78d70c43 100644 --- a/src/main/java/io/bitsquare/trade/protocol/mock/SellTakerPaymentProcess.java +++ b/src/main/java/io/bitsquare/trade/protocol/old/SellTakerPaymentProcess.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.mock; +package io.bitsquare.trade.protocol.old; //TODO not used but let it for reference until all use cases are impl. class SellTakerPaymentProcess extends PaymentProcess diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyTakerAccount.java b/src/main/java/io/bitsquare/trade/protocol/shared/VerifyPeerAccount.java similarity index 82% rename from src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyTakerAccount.java rename to src/main/java/io/bitsquare/trade/protocol/shared/VerifyPeerAccount.java index 44f19ff4de..3842bce48a 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/VerifyTakerAccount.java +++ b/src/main/java/io/bitsquare/trade/protocol/shared/VerifyPeerAccount.java @@ -1,15 +1,15 @@ -package io.bitsquare.trade.protocol.tasks.offerer; +package io.bitsquare.trade.protocol.shared; import io.bitsquare.bank.BankAccount; import io.bitsquare.btc.BlockChainFacade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VerifyTakerAccount +public class VerifyPeerAccount { - private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class); + private static final Logger log = LoggerFactory.getLogger(VerifyPeerAccount.class); public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount) { diff --git a/src/main/java/io/bitsquare/trade/protocol/taker/CreateAndSignContract.java b/src/main/java/io/bitsquare/trade/protocol/taker/CreateAndSignContract.java new file mode 100644 index 0000000000..26cebbf816 --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/taker/CreateAndSignContract.java @@ -0,0 +1,51 @@ +package io.bitsquare.trade.protocol.taker; + +import com.google.bitcoin.core.ECKey; +import io.bitsquare.bank.BankAccount; +import io.bitsquare.crypto.CryptoFacade; +import io.bitsquare.trade.Contract; +import io.bitsquare.trade.Offer; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.util.Utilities; +import java.math.BigInteger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CreateAndSignContract +{ + private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class); + + public static void run(ResultHandler resultHandler, + FaultHandler faultHandler, + CryptoFacade cryptoFacade, + Offer offer, + BigInteger tradeAmount, + String takeOfferFeeTxId, + String accountId, + BankAccount bankAccount, + String peersMessagePubKeyAsHex, + String messagePubKeyAsHex, + String peersAccountId, + BankAccount peersBankAccount, + ECKey registrationKey) + { + try + { + Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, peersAccountId, accountId, peersBankAccount, bankAccount, peersMessagePubKeyAsHex, messagePubKeyAsHex); + + String contractAsJson = Utilities.objectToJson(contract); + String signature = cryptoFacade.signContract(registrationKey, contractAsJson); + resultHandler.onResult(contract, contractAsJson, signature); + } catch (Throwable t) + { + log.error("Exception at sign contract " + t); + faultHandler.onFault(t); + } + } + + public interface ResultHandler + { + void onResult(Contract contract, String contractAsJson, String signature); + } + +} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/GetPeerAddress.java b/src/main/java/io/bitsquare/trade/protocol/taker/GetPeerAddress.java similarity index 91% rename from src/main/java/io/bitsquare/trade/protocol/tasks/taker/GetPeerAddress.java rename to src/main/java/io/bitsquare/trade/protocol/taker/GetPeerAddress.java index 7738ad5cee..c2c2ffe9ca 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/GetPeerAddress.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/GetPeerAddress.java @@ -1,8 +1,8 @@ -package io.bitsquare.trade.protocol.tasks.taker; +package io.bitsquare.trade.protocol.taker; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.GetPeerAddressListener; -import io.bitsquare.trade.protocol.tasks.FaultHandler; +import io.bitsquare.trade.protocol.FaultHandler; import net.tomp2p.peers.PeerAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/bitsquare/trade/protocol/taker/PayDeposit.java b/src/main/java/io/bitsquare/trade/protocol/taker/PayDeposit.java new file mode 100644 index 0000000000..bcda8a516d --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/taker/PayDeposit.java @@ -0,0 +1,54 @@ +package io.bitsquare.trade.protocol.taker; + +import com.google.bitcoin.core.InsufficientMoneyException; +import com.google.bitcoin.core.Transaction; +import io.bitsquare.btc.WalletFacade; +import io.bitsquare.trade.protocol.FaultHandler; +import java.math.BigInteger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PayDeposit +{ + private static final Logger log = LoggerFactory.getLogger(PayDeposit.class); + + public static void run(ResultHandler resultHandler, + FaultHandler faultHandler, + WalletFacade walletFacade, + BigInteger collateral, + BigInteger tradeAmount, + String tradeId, + String pubKeyForThatTrade, + String arbitratorPubKey, + String offererPubKey, + String preparedOffererDepositTxAsHex) + { + try + { + BigInteger amountToPay = tradeAmount.add(collateral); + BigInteger msOutputAmount = amountToPay.add(collateral); + + Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSignTx(amountToPay, + msOutputAmount, + offererPubKey, + pubKeyForThatTrade, + arbitratorPubKey, + preparedOffererDepositTxAsHex, + tradeId); + + log.trace("sharedModel.signedTakerDepositTx: " + signedTakerDepositTx); + resultHandler.onResult(signedTakerDepositTx); + } catch (InsufficientMoneyException e) + { + log.error("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e); + faultHandler.onFault(new Exception("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e)); + } + } + + public interface ResultHandler + { + void onResult(Transaction signedTakerDepositTx); + } + + +} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/PayTakeOfferFee.java b/src/main/java/io/bitsquare/trade/protocol/taker/PayTakeOfferFee.java similarity index 88% rename from src/main/java/io/bitsquare/trade/protocol/tasks/taker/PayTakeOfferFee.java rename to src/main/java/io/bitsquare/trade/protocol/taker/PayTakeOfferFee.java index 7078d1fd72..4d6d366c37 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/PayTakeOfferFee.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/PayTakeOfferFee.java @@ -1,10 +1,10 @@ -package io.bitsquare.trade.protocol.tasks.taker; +package io.bitsquare.trade.protocol.taker; import com.google.bitcoin.core.InsufficientMoneyException; import com.google.bitcoin.core.Transaction; import com.google.common.util.concurrent.FutureCallback; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; +import io.bitsquare.trade.protocol.FaultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,7 +23,7 @@ public class PayTakeOfferFee public void onSuccess(Transaction transaction) { log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString()); - resultHandler.onResult(transaction); + resultHandler.onResult(transaction.getHashAsString()); } @Override @@ -42,7 +42,7 @@ public class PayTakeOfferFee public interface ResultHandler { - void onResult(Transaction transaction); + void onResult(String takeOfferFeeTxId); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/taker/PayoutTxPublishedMessage.java b/src/main/java/io/bitsquare/trade/protocol/taker/PayoutTxPublishedMessage.java similarity index 92% rename from src/main/java/io/bitsquare/trade/protocol/messages/taker/PayoutTxPublishedMessage.java rename to src/main/java/io/bitsquare/trade/protocol/taker/PayoutTxPublishedMessage.java index f758bf0c1a..b4c0bb39a3 100644 --- a/src/main/java/io/bitsquare/trade/protocol/messages/taker/PayoutTxPublishedMessage.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/PayoutTxPublishedMessage.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.messages.taker; +package io.bitsquare.trade.protocol.taker; import io.bitsquare.msg.TradeMessage; import java.io.Serializable; diff --git a/src/main/java/io/bitsquare/trade/protocol/taker/ProtocolForTakerAsSeller.java b/src/main/java/io/bitsquare/trade/protocol/taker/ProtocolForTakerAsSeller.java new file mode 100644 index 0000000000..7d0461a629 --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/taker/ProtocolForTakerAsSeller.java @@ -0,0 +1,400 @@ +package io.bitsquare.trade.protocol.taker; + +import com.google.bitcoin.core.ECKey; +import com.google.bitcoin.core.Transaction; +import io.bitsquare.bank.BankAccount; +import io.bitsquare.btc.BlockChainFacade; +import io.bitsquare.btc.WalletFacade; +import io.bitsquare.crypto.CryptoFacade; +import io.bitsquare.msg.MessageFacade; +import io.bitsquare.trade.Contract; +import io.bitsquare.trade.Offer; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.protocol.offerer.BankTransferInitedMessage; +import io.bitsquare.trade.protocol.offerer.DepositTxPublishedMessage; +import io.bitsquare.trade.protocol.offerer.RequestTakerDepositPaymentMessage; +import io.bitsquare.trade.protocol.offerer.RespondToTakeOfferRequestMessage; +import io.bitsquare.user.User; +import java.math.BigInteger; +import net.tomp2p.peers.PeerAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.google.common.base.Preconditions.*; +import static io.bitsquare.util.Validator.*; + +/** + * Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing from the peer. + * That class handles the role of the taker as the Bitcoin seller. + * It uses sub tasks to not pollute the main class too much with all the async result/fault handling. + * Any data from incoming messages as well data used to send to the peer need to be validated before further processing. + */ +public class ProtocolForTakerAsSeller +{ + private static final Logger log = LoggerFactory.getLogger(ProtocolForTakerAsSeller.class); + + + public enum State + { + Init, + GetPeerAddress, + RequestTakeOffer, + PayTakeOfferFee, + + onRequestTakerDepositPaymentMessage, + + SendTakeOfferFeePayedTxId, + VerifyOffererAccount, + CreateAndSignContract, + PayDeposit, + SendSignedTakerDepositTxAsHex, + onDepositTxPublishedMessage, + onBankTransferInitedMessage, + onUIEventFiatReceived, + SignAndPublishPayoutTx, + SendPayoutTxToOfferer + } + + // provided data + private final Trade trade; + private final ProtocolForTakerAsSellerListener listener; + private final MessageFacade messageFacade; + private final WalletFacade walletFacade; + private final BlockChainFacade blockChainFacade; + private final CryptoFacade cryptoFacade; + + // derived + private final String id; + private final Offer offer; + private final String tradeId; + private final BankAccount bankAccount; + private final String accountId; + private final String messagePubKey; + private final BigInteger tradeAmount; + private final String pubKeyForThatTrade; + private final ECKey accountKey; + private final String peersMessagePubKey; + private final BigInteger collateral; + private final String arbitratorPubKey; + + // written/read by task + private PeerAddress peerAddress; + + // written by messages, read by tasks + private String peersAccountId; + private BankAccount peersBankAccount; + private String peersPubKey; + private String preparedPeersDepositTxAsHex; + private long peersTxOutIndex; + + private String depositTxAsHex; + private String offererSignatureR; + private String offererSignatureS; + private BigInteger offererPaybackAmount; + private BigInteger takerPaybackAmount; + private String offererPayoutAddress; + + + // state + private State state; + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + + public ProtocolForTakerAsSeller(Trade trade, + ProtocolForTakerAsSellerListener listener, + MessageFacade messageFacade, + WalletFacade walletFacade, + BlockChainFacade blockChainFacade, + CryptoFacade cryptoFacade, + User user) + { + this.trade = trade; + this.listener = listener; + this.messageFacade = messageFacade; + this.walletFacade = walletFacade; + this.blockChainFacade = blockChainFacade; + this.cryptoFacade = cryptoFacade; + + offer = trade.getOffer(); + tradeId = trade.getId(); + tradeAmount = trade.getTradeAmount(); + collateral = trade.getCollateralAmount(); + arbitratorPubKey = trade.getOffer().getArbitrator().getPubKeyAsHex(); + + pubKeyForThatTrade = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString(); + + bankAccount = user.getBankAccount(offer.getBankAccountId()); + accountId = user.getAccountId(); + messagePubKey = user.getMessagePubKeyAsHex(); + + peersMessagePubKey = offer.getMessagePubKeyAsHex(); + accountKey = walletFacade.getRegistrationAddressInfo().getKey(); + + id = trade.getId(); + + state = State.Init; + } + + public void start() + { + log.debug("start called"); + GetPeerAddress.run(this::onResultGetPeerAddress, this::onFault, messageFacade, peersMessagePubKey); + state = State.GetPeerAddress; + } + + public void onResultGetPeerAddress(PeerAddress peerAddress) + { + log.debug(" called"); + this.peerAddress = peerAddress; + + RequestTakeOffer.run(this::onResultRequestTakeOffer, this::onFault, peerAddress, messageFacade, tradeId); + state = State.RequestTakeOffer; + } + + public void onResultRequestTakeOffer() + { + log.debug(" called"); + listener.onWaitingForPeerResponse(state); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message from peer + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onRespondToTakeOfferRequestMessage(RespondToTakeOfferRequestMessage message) + { + log.debug("onRespondToTakeOfferRequestMessage called"); + checkState(state == State.RequestTakeOffer); + checkArgument(tradeId.equals(message.getTradeId())); + + if (message.isTakeOfferRequestAccepted()) + { + PayTakeOfferFee.run(this::onResultPayTakeOfferFee, this::onFault, walletFacade, tradeId); + state = State.PayTakeOfferFee; + } + else + { + listener.onTakeOfferRequestRejected(trade); + } + } + + public void onResultPayTakeOfferFee(String takeOfferFeeTxId) + { + log.debug("onResultPayTakeOfferFee called"); + trade.setTakeOfferFeeTxID(takeOfferFeeTxId); + + SendTakeOfferFeePayedTxId.run(this::onResultSendTakeOfferFeePayedTxId, this::onFault, peerAddress, messageFacade, tradeId, takeOfferFeeTxId, tradeAmount, pubKeyForThatTrade); + state = State.SendTakeOfferFeePayedTxId; + } + + public void onResultSendTakeOfferFeePayedTxId() + { + log.debug("onResultSendTakeOfferFeePayedTxId called"); + listener.onWaitingForPeerResponse(state); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message from peer + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onRequestTakerDepositPaymentMessage(RequestTakerDepositPaymentMessage message) + { + log.debug("onRequestTakerDepositPaymentMessage called"); + + // validation + checkState(state == State.SendTakeOfferFeePayedTxId); + checkArgument(tradeId.equals(message.getTradeId())); + String peersAccountId = nonEmptyStringOf(message.getAccountId()); + BankAccount peersBankAccount = checkNotNull(message.getBankAccount()); + String offererPubKey = nonEmptyStringOf(message.getOffererPubKey()); + String preparedOffererDepositTxAsHex = nonEmptyStringOf(message.getPreparedOffererDepositTxAsHex()); + long offererTxOutIndex = nonNegativeLongOf(message.getOffererTxOutIndex()); + + // apply new state + state = State.onRequestTakerDepositPaymentMessage; + this.peersAccountId = peersAccountId; + this.peersBankAccount = peersBankAccount; + this.peersPubKey = offererPubKey; + this.preparedPeersDepositTxAsHex = preparedOffererDepositTxAsHex; + this.peersTxOutIndex = offererTxOutIndex; + + // next task + VerifyOffererAccount.run(this::onResultVerifyOffererAccount, this::onFault, blockChainFacade, peersAccountId, peersBankAccount); + state = State.VerifyOffererAccount; + } + + public void onResultVerifyOffererAccount() + { + log.debug("onResultVerifyOffererAccount called"); + String takeOfferFeeTxId = trade.getTakeOfferFeeTxId(); + CreateAndSignContract.run(this::onResultCreateAndSignContract, + this::onFault, + cryptoFacade, + offer, + tradeAmount, + takeOfferFeeTxId, + accountId, + bankAccount, + peersMessagePubKey, + messagePubKey, + peersAccountId, + peersBankAccount, + accountKey); + state = State.CreateAndSignContract; + } + + public void onResultCreateAndSignContract(Contract contract, String contractAsJson, String signature) + { + log.debug("onResultCreateAndSignContract called"); + + trade.setContract(contract); + trade.setContractAsJson(contractAsJson); + trade.setContractTakerSignature(signature); + + PayDeposit.run(this::onResultPayDeposit, this::onFault, walletFacade, collateral, tradeAmount, tradeId, pubKeyForThatTrade, arbitratorPubKey, peersPubKey, preparedPeersDepositTxAsHex); + state = State.PayDeposit; + } + + public void onResultPayDeposit(Transaction signedTakerDepositTx) + { + log.debug("onResultPayDeposit called"); + String contractAsJson = trade.getContractAsJson(); + String takerSignature = trade.getTakerSignature(); + + SendSignedTakerDepositTxAsHex.run(this::onResultSendSignedTakerDepositTxAsHex, + this::onFault, + peerAddress, + messageFacade, + walletFacade, + bankAccount, + accountId, + messagePubKey, + tradeId, + contractAsJson, + takerSignature, + signedTakerDepositTx, + peersTxOutIndex); + state = State.SendSignedTakerDepositTxAsHex; + } + + public void onResultSendSignedTakerDepositTxAsHex() + { + log.debug(" called"); + listener.onWaitingForPeerResponse(state); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message from peer + /////////////////////////////////////////////////////////////////////////////////////////// + + // informational, does only trigger UI feedback/update + public void onDepositTxPublishedMessage(DepositTxPublishedMessage message) + { + log.debug("onDepositTxPublishedMessage called"); + checkState(state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal()); + checkArgument(tradeId.equals(message.getTradeId())); + state = State.onDepositTxPublishedMessage; + listener.onDepositTxPublished(walletFacade.takerCommitDepositTx(message.getDepositTxAsHex())); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message from peer + /////////////////////////////////////////////////////////////////////////////////////////// + + // informational, store data for later, does only trigger UI feedback/update + public void onBankTransferInitedMessage(BankTransferInitedMessage message) + { + log.debug("onBankTransferInitedMessage called"); + + // validate + checkState(state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal()); + checkArgument(tradeId.equals(message.getTradeId())); + String depositTxAsHex = nonEmptyStringOf(message.getDepositTxAsHex()); + String offererSignatureR = nonEmptyStringOf(message.getOffererSignatureR()); + String offererSignatureS = nonEmptyStringOf(message.getOffererSignatureS()); + BigInteger offererPaybackAmount = nonNegativeBigIntegerOf(nonZeroBigIntegerOf(message.getOffererPaybackAmount())); + BigInteger takerPaybackAmount = nonNegativeBigIntegerOf(nonZeroBigIntegerOf(message.getTakerPaybackAmount())); + String offererPayoutAddress = nonEmptyStringOf(message.getOffererPayoutAddress()); + + // apply state + state = State.onBankTransferInitedMessage; + this.depositTxAsHex = depositTxAsHex; + this.offererSignatureR = offererSignatureR; + this.offererSignatureS = offererSignatureS; + this.offererPaybackAmount = offererPaybackAmount; + this.takerPaybackAmount = takerPaybackAmount; + this.offererPayoutAddress = offererPayoutAddress; + + listener.onBankTransferInited(message.getTradeId()); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Triggered UI event + /////////////////////////////////////////////////////////////////////////////////////////// + + // User clicked the "bank transfer received" button, so we release the funds for pay out + public void onUIEventFiatReceived() + { + log.debug("onUIEventFiatReceived called"); + + checkState(state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal()); + state = State.onUIEventFiatReceived; + + SignAndPublishPayoutTx.run(this::onResultSignAndPublishPayoutTx, + this::onFault, + walletFacade, + tradeId, + depositTxAsHex, + offererSignatureR, + offererSignatureS, + offererPaybackAmount, + takerPaybackAmount, + offererPayoutAddress); + state = State.SignAndPublishPayoutTx; + } + + public void onResultSignAndPublishPayoutTx(String transactionId, String payoutTxAsHex) + { + log.debug("onResultSignAndPublishPayoutTx called"); + listener.onPayoutTxPublished(trade, transactionId); + + SendPayoutTxToOfferer.run(this::onResultSendPayoutTxToOfferer, this::onFault, peerAddress, messageFacade, tradeId, payoutTxAsHex); + state = State.SendPayoutTxToOfferer; + } + + public void onResultSendPayoutTxToOfferer() + { + log.debug("onResultSendPayoutTxToOfferer called"); + listener.onCompleted(state); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Getters, Setters + /////////////////////////////////////////////////////////////////////////////////////////// + + public String getId() + { + return id; + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Private + /////////////////////////////////////////////////////////////////////////////////////////// + + // generic fault handler + private void onFault(Throwable throwable) + { + listener.onFault(throwable, state); + } + +} diff --git a/src/main/java/io/bitsquare/trade/protocol/taker/TakerAsSellerProtocolListener.java b/src/main/java/io/bitsquare/trade/protocol/taker/ProtocolForTakerAsSellerListener.java similarity index 53% rename from src/main/java/io/bitsquare/trade/protocol/taker/TakerAsSellerProtocolListener.java rename to src/main/java/io/bitsquare/trade/protocol/taker/ProtocolForTakerAsSellerListener.java index 20f75789e6..20bfe7f723 100644 --- a/src/main/java/io/bitsquare/trade/protocol/taker/TakerAsSellerProtocolListener.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/ProtocolForTakerAsSellerListener.java @@ -2,7 +2,7 @@ package io.bitsquare.trade.protocol.taker; import io.bitsquare.trade.Trade; -public interface TakerAsSellerProtocolListener +public interface ProtocolForTakerAsSellerListener { void onDepositTxPublished(String depositTxId); @@ -10,11 +10,11 @@ public interface TakerAsSellerProtocolListener void onPayoutTxPublished(Trade trade, String hashAsString); - void onFault(Throwable throwable, TakerAsSellerProtocol.State state); + void onFault(Throwable throwable, ProtocolForTakerAsSeller.State state); - void onWaitingForPeerResponse(TakerAsSellerProtocol.State state); + void onWaitingForPeerResponse(ProtocolForTakerAsSeller.State state); - void onCompleted(TakerAsSellerProtocol.State state); + void onCompleted(ProtocolForTakerAsSeller.State state); void onTakeOfferRequestRejected(Trade trade); } diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/taker/RequestOffererPublishDepositTxMessage.java b/src/main/java/io/bitsquare/trade/protocol/taker/RequestOffererPublishDepositTxMessage.java similarity index 94% rename from src/main/java/io/bitsquare/trade/protocol/messages/taker/RequestOffererPublishDepositTxMessage.java rename to src/main/java/io/bitsquare/trade/protocol/taker/RequestOffererPublishDepositTxMessage.java index 40405e2e8c..c06dc90cae 100644 --- a/src/main/java/io/bitsquare/trade/protocol/messages/taker/RequestOffererPublishDepositTxMessage.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/RequestOffererPublishDepositTxMessage.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.messages.taker; +package io.bitsquare.trade.protocol.taker; import io.bitsquare.bank.BankAccount; import io.bitsquare.msg.TradeMessage; @@ -62,12 +62,12 @@ public class RequestOffererPublishDepositTxMessage implements Serializable, Trad return offererTxOutIndex; } - public BankAccount getBankAccount() + public BankAccount getTakerBankAccount() { return bankAccount; } - public String getAccountId() + public String getTakerAccountId() { return accountID; } @@ -92,7 +92,7 @@ public class RequestOffererPublishDepositTxMessage implements Serializable, Trad return txConnOutAsHex; } - public String getContractAsJson() + public String getTakerContractAsJson() { return contractAsJson; } diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/RequestTakeOffer.java b/src/main/java/io/bitsquare/trade/protocol/taker/RequestTakeOffer.java similarity index 82% rename from src/main/java/io/bitsquare/trade/protocol/tasks/taker/RequestTakeOffer.java rename to src/main/java/io/bitsquare/trade/protocol/taker/RequestTakeOffer.java index 6814d09d24..e97633ab4b 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/RequestTakeOffer.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/RequestTakeOffer.java @@ -1,10 +1,9 @@ -package io.bitsquare.trade.protocol.tasks.taker; +package io.bitsquare.trade.protocol.taker; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; -import io.bitsquare.trade.protocol.messages.taker.RequestTakeOfferMessage; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; import net.tomp2p.peers.PeerAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/taker/RequestTakeOfferMessage.java b/src/main/java/io/bitsquare/trade/protocol/taker/RequestTakeOfferMessage.java similarity index 89% rename from src/main/java/io/bitsquare/trade/protocol/messages/taker/RequestTakeOfferMessage.java rename to src/main/java/io/bitsquare/trade/protocol/taker/RequestTakeOfferMessage.java index df30ef586d..6e7884468d 100644 --- a/src/main/java/io/bitsquare/trade/protocol/messages/taker/RequestTakeOfferMessage.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/RequestTakeOfferMessage.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.messages.taker; +package io.bitsquare.trade.protocol.taker; import io.bitsquare.msg.TradeMessage; import java.io.Serializable; diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendPayoutTxToOfferer.java b/src/main/java/io/bitsquare/trade/protocol/taker/SendPayoutTxToOfferer.java similarity index 76% rename from src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendPayoutTxToOfferer.java rename to src/main/java/io/bitsquare/trade/protocol/taker/SendPayoutTxToOfferer.java index 987a29bee4..c85aeffa33 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendPayoutTxToOfferer.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/SendPayoutTxToOfferer.java @@ -1,11 +1,9 @@ -package io.bitsquare.trade.protocol.tasks.taker; +package io.bitsquare.trade.protocol.taker; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; import net.tomp2p.peers.PeerAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,9 +12,9 @@ public class SendPayoutTxToOfferer { private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class); - public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade trade, String payoutTxAsHex) + public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, String tradeId, String payoutTxAsHex) { - PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(trade.getId(), payoutTxAsHex); + PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(tradeId, payoutTxAsHex); messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener() { @Override diff --git a/src/main/java/io/bitsquare/trade/protocol/taker/SendSignedTakerDepositTxAsHex.java b/src/main/java/io/bitsquare/trade/protocol/taker/SendSignedTakerDepositTxAsHex.java new file mode 100644 index 0000000000..2336e0d52f --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/taker/SendSignedTakerDepositTxAsHex.java @@ -0,0 +1,67 @@ +package io.bitsquare.trade.protocol.taker; + +import com.google.bitcoin.core.Transaction; +import com.google.bitcoin.core.Utils; +import io.bitsquare.bank.BankAccount; +import io.bitsquare.btc.WalletFacade; +import io.bitsquare.msg.MessageFacade; +import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; +import net.tomp2p.peers.PeerAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SendSignedTakerDepositTxAsHex +{ + private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class); + + public static void run(ResultHandler resultHandler, + FaultHandler faultHandler, + PeerAddress peerAddress, + MessageFacade messageFacade, + WalletFacade walletFacade, + BankAccount bankAccount, + String accountId, + String messagePubKeyAsHex, + String tradeId, + String contractAsJson, + String takerSignature, + Transaction signedTakerDepositTx, + long offererTxOutIndex) + { + long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex(); + + RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(tradeId, + bankAccount, + accountId, + messagePubKeyAsHex, + Utils.bytesToHexString(signedTakerDepositTx.bitcoinSerialize()), + Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes()), + Utils.bytesToHexString(signedTakerDepositTx.getInput(1) + .getConnectedOutput() + .getParentTransaction() + .bitcoinSerialize()), + contractAsJson, + takerSignature, + walletFacade.getAddressInfoByTradeID(tradeId).getAddressString(), + takerTxOutIndex, + offererTxOutIndex); + messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener() + { + @Override + public void onResult() + { + log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer"); + resultHandler.onResult(); + } + + @Override + public void onFailed() + { + log.error("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer"); + faultHandler.onFault(new Exception("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer")); + } + }); + } +} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendTakeOfferFeePayedTxId.java b/src/main/java/io/bitsquare/trade/protocol/taker/SendTakeOfferFeePayedTxId.java similarity index 78% rename from src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendTakeOfferFeePayedTxId.java rename to src/main/java/io/bitsquare/trade/protocol/taker/SendTakeOfferFeePayedTxId.java index 02aef821ca..454b040796 100644 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendTakeOfferFeePayedTxId.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/SendTakeOfferFeePayedTxId.java @@ -1,10 +1,9 @@ -package io.bitsquare.trade.protocol.tasks.taker; +package io.bitsquare.trade.protocol.taker; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; -import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; import java.math.BigInteger; import net.tomp2p.peers.PeerAddress; import org.slf4j.Logger; @@ -21,12 +20,9 @@ public class SendTakeOfferFeePayedTxId String tradeId, String takeOfferFeeTxId, BigInteger tradeAmount, - String pubKeyAsHexString) + String pubKeyForThatTradeAsHex) { - TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(tradeId, - takeOfferFeeTxId, - tradeAmount, - pubKeyAsHexString); + TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(tradeId, takeOfferFeeTxId, tradeAmount, pubKeyForThatTradeAsHex); messageFacade.sendTradeMessage(peerAddress, msg, new OutgoingTradeMessageListener() { diff --git a/src/main/java/io/bitsquare/trade/protocol/taker/SignAndPublishPayoutTx.java b/src/main/java/io/bitsquare/trade/protocol/taker/SignAndPublishPayoutTx.java new file mode 100644 index 0000000000..a09f27868f --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/taker/SignAndPublishPayoutTx.java @@ -0,0 +1,66 @@ +package io.bitsquare.trade.protocol.taker; + +import com.google.bitcoin.core.Transaction; +import com.google.bitcoin.core.Utils; +import com.google.common.util.concurrent.FutureCallback; +import io.bitsquare.btc.WalletFacade; +import io.bitsquare.trade.protocol.FaultHandler; +import java.math.BigInteger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SignAndPublishPayoutTx +{ + private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class); + + public static void run(ResultHandler resultHandler, + FaultHandler faultHandler, + WalletFacade walletFacade, + String tradeId, + String depositTxAsHex, + String offererSignatureR, + String offererSignatureS, + BigInteger offererPaybackAmount, + BigInteger takerPaybackAmount, + String offererPayoutAddress) + { + try + { + + walletFacade.takerSignsAndSendsTx(depositTxAsHex, + offererSignatureR, + offererSignatureS, + offererPaybackAmount, + takerPaybackAmount, + offererPayoutAddress, + tradeId, + new FutureCallback() + { + @Override + public void onSuccess(Transaction transaction) + { + log.debug("takerSignsAndSendsTx " + transaction); + String payoutTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize()); + resultHandler.onResult(transaction.getHashAsString(), payoutTxAsHex); + } + + @Override + public void onFailure(Throwable t) + { + log.error("Exception at takerSignsAndSendsTx " + t); + faultHandler.onFault(t); + } + }); + } catch (Exception e) + { + log.error("Exception at takerSignsAndSendsTx " + e); + faultHandler.onFault(e); + } + } + + public interface ResultHandler + { + void onResult(String transactionId, String payoutTxAsHex); + } + +} diff --git a/src/main/java/io/bitsquare/trade/protocol/messages/taker/TakeOfferFeePayedMessage.java b/src/main/java/io/bitsquare/trade/protocol/taker/TakeOfferFeePayedMessage.java similarity index 73% rename from src/main/java/io/bitsquare/trade/protocol/messages/taker/TakeOfferFeePayedMessage.java rename to src/main/java/io/bitsquare/trade/protocol/taker/TakeOfferFeePayedMessage.java index 1974bb542c..44a218d3c3 100644 --- a/src/main/java/io/bitsquare/trade/protocol/messages/taker/TakeOfferFeePayedMessage.java +++ b/src/main/java/io/bitsquare/trade/protocol/taker/TakeOfferFeePayedMessage.java @@ -1,4 +1,4 @@ -package io.bitsquare.trade.protocol.messages.taker; +package io.bitsquare.trade.protocol.taker; import io.bitsquare.msg.TradeMessage; import java.io.Serializable; @@ -11,14 +11,14 @@ public class TakeOfferFeePayedMessage implements Serializable, TradeMessage private BigInteger tradeAmount; private String takeOfferFeeTxID; - private String takerMultiSigPubKey; + private String takerPubKey; - public TakeOfferFeePayedMessage(String tradeId, String takeOfferFeeTxID, BigInteger tradeAmount, String takerMultiSigPubKey) + public TakeOfferFeePayedMessage(String tradeId, String takeOfferFeeTxID, BigInteger tradeAmount, String takerPubKey) { this.tradeId = tradeId; this.takeOfferFeeTxID = takeOfferFeeTxID; this.tradeAmount = tradeAmount; - this.takerMultiSigPubKey = takerMultiSigPubKey; + this.takerPubKey = takerPubKey; } @Override @@ -37,9 +37,9 @@ public class TakeOfferFeePayedMessage implements Serializable, TradeMessage return takeOfferFeeTxID; } - public String getTakerMultiSigPubKey() + public String getTakerPubKey() { - return takerMultiSigPubKey; + return takerPubKey; } } diff --git a/src/main/java/io/bitsquare/trade/protocol/taker/TakerAsSellerProtocol.java b/src/main/java/io/bitsquare/trade/protocol/taker/TakerAsSellerProtocol.java deleted file mode 100644 index 709a328aa3..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/taker/TakerAsSellerProtocol.java +++ /dev/null @@ -1,882 +0,0 @@ -package io.bitsquare.trade.protocol.taker; - -import com.google.bitcoin.core.Transaction; -import io.bitsquare.bank.BankAccount; -import io.bitsquare.btc.BlockChainFacade; -import io.bitsquare.btc.WalletFacade; -import io.bitsquare.crypto.CryptoFacade; -import io.bitsquare.msg.MessageFacade; -import io.bitsquare.trade.Offer; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.messages.offerer.BankTransferInitedMessage; -import io.bitsquare.trade.protocol.messages.offerer.DepositTxPublishedMessage; -import io.bitsquare.trade.protocol.messages.offerer.RequestTakerDepositPaymentMessage; -import io.bitsquare.trade.protocol.tasks.taker.*; -import io.bitsquare.user.User; -import java.math.BigInteger; -import net.tomp2p.peers.PeerAddress; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static io.bitsquare.util.Validator.nonEmptyStringOf; -import static io.bitsquare.util.Validator.nonNegativeLongOf; - -/** - * Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing from the peer. - * That class handles the role of the taker as the Bitcoin seller. - * It uses sub tasks to not pollute the main class too much with all the async result/fault handling. - * Any data from incoming messages as well data used to send to the peer need to be validated before further processing. - */ -public class TakerAsSellerProtocol -{ - private static final Logger log = LoggerFactory.getLogger(TakerAsSellerProtocol.class); - // provided data - private final Trade trade; - private final TakerAsSellerProtocolListener listener; - private final MessageFacade messageFacade; - private final WalletFacade walletFacade; - private final BlockChainFacade blockChainFacade; - private final CryptoFacade cryptoFacade; - private final User user; - private final String id; - private final Offer offer; - private final String tradeId; - // written/read by task - private String payoutTxAsHex; - private PeerAddress peerAddress; - private Transaction signedTakerDepositTx; - private long takerTxOutIndex; - // written by message, read by tasks - private String peersAccountId; - private BankAccount peersBankAccount; - private String offererPubKey; - private String preparedOffererDepositTxAsHex; - private long offererTxOutIndex; - private String depositTxAsHex; - private String offererSignatureR; - private String offererSignatureS; - private BigInteger offererPaybackAmount; - private BigInteger takerPaybackAmount; - private String offererPayoutAddress; - //private - private State state; - - public TakerAsSellerProtocol(Trade trade, - TakerAsSellerProtocolListener listener, - MessageFacade messageFacade, - WalletFacade walletFacade, - BlockChainFacade blockChainFacade, - CryptoFacade cryptoFacade, - User user) - { - this.trade = trade; - this.listener = listener; - this.messageFacade = messageFacade; - this.walletFacade = walletFacade; - this.blockChainFacade = blockChainFacade; - this.cryptoFacade = cryptoFacade; - this.user = user; - - offer = trade.getOffer(); - tradeId = trade.getId(); - - id = trade.getId(); - state = State.Init; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor - /////////////////////////////////////////////////////////////////////////////////////////// - - // generic fault handler - public void onFault(Throwable throwable) - { - listener.onFault(throwable, state); - } - - public void start() - { - String messagePubKeyAsHex = nonEmptyStringOf(offer.getMessagePubKeyAsHex()); - - GetPeerAddress.run(this::onResultGetPeerAddress, this::onFault, messageFacade, messagePubKeyAsHex); - state = State.GetPeerAddress; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Tasks - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onResultGetPeerAddress(PeerAddress peerAddress) - { - this.peerAddress = checkNotNull(peerAddress); - - RequestTakeOffer.run(this::onResultRequestTakeOffer, this::onFault, this.peerAddress, messageFacade, tradeId); - state = State.RequestTakeOffer; - } - - public void onResultRequestTakeOffer() - { - listener.onWaitingForPeerResponse(state); - } - - public void onAcceptTakeOfferRequestMessage() - { - log.debug("onAcceptTakeOfferRequestMessage"); - checkState(state == State.RequestTakeOffer); - - PayTakeOfferFee.run(this::onResultPayTakeOfferFee, this::onFault, walletFacade, tradeId); - state = State.PayTakeOfferFee; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - // OR - public void onRejectTakeOfferRequestMessage() - { - log.debug("onRejectTakeOfferRequestMessage"); - checkState(state == State.RequestTakeOffer); - - state = State.onRejectTakeOfferRequestMessage; - listener.onTakeOfferRequestRejected(trade); - } - - public void onResultPayTakeOfferFee(Transaction transaction) - { - checkNotNull(transaction); - String transactionId = nonEmptyStringOf(transaction.getHashAsString()); - - trade.setTakeOfferFeeTxID(transactionId); - - String takeOfferFeeTxId = trade.getTakeOfferFeeTxId(); - BigInteger tradeAmount = trade.getTradeAmount(); - String pubKeyAsHexString = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString(); - - SendTakeOfferFeePayedTxId.run(this::onResultSendTakeOfferFeePayedTxId, - this::onFault, - peerAddress, - messageFacade, - tradeId, - takeOfferFeeTxId, - tradeAmount, - pubKeyAsHexString); - state = State.SendTakeOfferFeePayedTxId; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Tasks - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onResultSendTakeOfferFeePayedTxId() - { - listener.onWaitingForPeerResponse(state); - } - - public void onRequestTakerDepositPaymentMessage(RequestTakerDepositPaymentMessage message) - { - log.debug("onRequestTakerDepositPaymentMessage"); - - checkState(state == State.SendTakeOfferFeePayedTxId); - - peersAccountId = nonEmptyStringOf(message.getAccountID()); - peersBankAccount = checkNotNull(message.getBankAccount()); - offererPubKey = nonEmptyStringOf(message.getOffererPubKey()); - preparedOffererDepositTxAsHex = nonEmptyStringOf(message.getPreparedOffererDepositTxAsHex()); - offererTxOutIndex = nonNegativeLongOf(message.getOffererTxOutIndex()); - - VerifyOffererAccount.run(this::onResultVerifyOffererAccount, - this::onFault, - blockChainFacade, - peersAccountId, - peersBankAccount); - state = State.VerifyOffererAccount; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onResultVerifyOffererAccount() - { - CreateAndSignContract.run(this::onResultCreateAndSignContract, - this::onFault, - cryptoFacade, - trade, - user, - peersAccountId, - peersBankAccount, - walletFacade.getRegistrationAddressInfo().getKey()); - state = State.CreateAndSignContract; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Tasks - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onResultCreateAndSignContract() - { - PayDeposit.run(this::onResultPayDeposit, this::onFault, walletFacade, trade, offererPubKey, preparedOffererDepositTxAsHex); - state = State.PayDeposit; - } - - public void onResultPayDeposit(Transaction signedTakerDepositTx, long takerTxOutIndex) - { - SendSignedTakerDepositTxAsHex.run(this::onResultSendSignedTakerDepositTxAsHex, - this::onFault, - peerAddress, - messageFacade, - walletFacade, - trade, - user, - signedTakerDepositTx, - takerTxOutIndex, - offererTxOutIndex); - state = State.SendSignedTakerDepositTxAsHex; - } - - public void onResultSendSignedTakerDepositTxAsHex() - { - listener.onWaitingForPeerResponse(state); - } - - // informational, does only trigger UI feedback/update - public void onDepositTxPublishedMessage(DepositTxPublishedMessage message) - { - log.debug("onDepositTxPublishedMessage"); - if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal()) - { - state = State.onDepositTxPublishedMessage; - - listener.onDepositTxPublished(walletFacade.takerCommitDepositTx(message.getDepositTxAsHex())); - } - else - { - log.error("Invalid state. Actual state is: " + state); - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - // informational, store data for later, does only trigger UI feedback/update - public void onBankTransferInitedMessage(BankTransferInitedMessage tradeMessage) - { - log.debug("onBankTransferInitedMessage"); - - if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal()) - { - state = State.onBankTransferInitedMessage; - - depositTxAsHex = tradeMessage.getDepositTxAsHex(); - offererSignatureR = tradeMessage.getOffererSignatureR(); - offererSignatureS = tradeMessage.getOffererSignatureS(); - offererPaybackAmount = tradeMessage.getOffererPaybackAmount(); - takerPaybackAmount = tradeMessage.getTakerPaybackAmount(); - offererPayoutAddress = tradeMessage.getOffererPayoutAddress(); - - listener.onBankTransferInited(tradeMessage.getTradeId()); - } - else - { - log.error("Invalid state. Actual state is: " + state); - } - } - - // User clicked the "bank transfer received" button, so we release the funds for pay out - public void onUIEventFiatReceived() - { - log.debug("onUIEventFiatReceived"); - - if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal()) - { - state = State.onUIEventFiatReceived; - - SignAndPublishPayoutTx.run(this::onResultSignAndPublishPayoutTx, - this::onFault, - walletFacade, - trade, - depositTxAsHex, - offererSignatureR, - offererSignatureS, - offererPaybackAmount, - takerPaybackAmount, - offererPayoutAddress); - state = State.SignAndPublishPayoutTx; - } - else - { - log.error("Invalid state. Actual state is: " + state); - } - } - - public void onResultSignAndPublishPayoutTx(Transaction transaction, String payoutTxAsHex) - { - listener.onPayoutTxPublished(trade, transaction.getHashAsString()); - - SendPayoutTxToOfferer.run(this::onResultSendPayoutTxToOfferer, this::onFault, peerAddress, messageFacade, trade, payoutTxAsHex); - state = State.SendPayoutTxToOfferer; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Tasks - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onResultSendPayoutTxToOfferer() - { - checkState(state == State.SendPayoutTxToOfferer); - listener.onCompleted(state); - } - - public String getId() - { - return id; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Getters, Setters - /////////////////////////////////////////////////////////////////////////////////////////// - - public enum State - { - Init, - GetPeerAddress, - RequestTakeOffer, - PayTakeOfferFee, - onRejectTakeOfferRequestMessage, - SendTakeOfferFeePayedTxId, - VerifyOffererAccount, - CreateAndSignContract, - PayDeposit, - SendSignedTakerDepositTxAsHex, - onDepositTxPublishedMessage, - onBankTransferInitedMessage, - onUIEventFiatReceived, - SignAndPublishPayoutTx, - SendPayoutTxToOfferer - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 1.1 - /////////////////////////////////////////////////////////////////////////////////////////// - - - /* private void findPeerAddress() - { - log.debug("1.1 findPeerAddress"); - AddressLookupListener addressLookupListener = new AddressLookupListener() - { - @Override - public void onResult(PeerAddress address) - { - log.debug("1.1 findPeerAddress onResult"); - // We got the peer address - peerAddress = address; - - takerPaymentProtocolListener.onProgress(getProgress()); - - // next - requestTakeOffer(); - } - - @Override - public void onFailed() - { - log.debug("1.1 findPeerAddress onFailed"); - takerPaymentProtocolListener.onFailure("onGetPeerAddressFailed"); - } - }; - - takerPaymentProtocolListener.onProgress(getProgress()); - - // Request the peers address from the DHT - messageFacade.getPeerAddress(offer.getMessagePubKeyAsHex(), addressLookupListener); - } */ - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 1.2 - /////////////////////////////////////////////////////////////////////////////////////////// - - /* private void requestTakeOffer() - { - log.debug("1.2 requestTakeOffer"); - TradeMessageListener listener = new TradeMessageListener() - { - @Override - public void onResult() - { - log.debug("1.2 requestTakeOffer onResult"); - // Our message has arrived - // We don't know yet if the offerer has accepted - // the take request (if offer is not already reserved for another user) - // We await for an incoming message from the offerer with the accept msg - takerPaymentProtocolListener.onProgress(getProgress()); - - // Wait for message from offerer... - } - - @Override - public void onFailed() - { - log.debug("1.2 requestTakeOffer onFailed"); - takerPaymentProtocolListener.onFailure("sendTakeOfferRequest onSendTradingMessageFailed"); - } - }; - - takerPaymentProtocolListener.onProgress(getProgress()); - - // Send the take offer request - TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKE_OFFER, trade.getId()); - messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener); - } */ - - - //************************************************************************************************ - // 1.3. Offerers tasks, we are in waiting mode - //************************************************************************************************ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 1.4 - /////////////////////////////////////////////////////////////////////////////////////////// - - - // 1.4a offerer has accepted the take offer request. Move on to step 2. - /* public void onAcceptTakeOfferRequestMessage() - { - log.debug("1.4a onAcceptTakeOfferRequestMessage"); - // listener.onProgress(getProgress()); - - payOfferFee(trade); - } - - // 1.4b Offerer has rejected the take offer request. The UI controller will onResult the case. - public void onRejectTakeOfferRequestMessage() - { - log.debug("1.4b onRejectTakeOfferRequestMessage"); - // listener.onProgress(getProgress()); - } */ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 2.1 - /////////////////////////////////////////////////////////////////////////////////////////// - - /* private void payOfferFee(Trade trade) - { - log.debug("2.1 payTakeOfferFee"); - FutureCallback callback = new FutureCallback() - { - @Override - public void onSuccess(@javax.annotation.Nullable Transaction transaction) - { - log.debug("2.1 payTakeOfferFee onSuccess"); - log.info("sendResult onSuccess txid:" + transaction.getHashAsString()); - - // Offer fee payed successfully. - trade.setTakeOfferFeeTxID(transaction.getHashAsString()); - - // listener.onProgress(getProgress()); - - // move on - sendTakerOfferFeeTxID(transaction.getHashAsString()); - } - - @Override - public void onFailure(Throwable t) - { - log.debug("2.1 payTakeOfferFee onFailure"); - // listener.onFailure("payTakeOfferFee onFailure " + t.getMessage()); - } - }; - try - { - // Pay the offer fee - // listener.onProgress(getProgress()); - walletFacade.payTakeOfferFee(trade.getId(), callback); - } catch (InsufficientMoneyException e) - { - // listener.onProgress(getProgress()); - } - } */ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 2.2 - /////////////////////////////////////////////////////////////////////////////////////////// - - // Request peers account details. At that moment private data (bank account nr.) of the offerer get visible to the taker. - // We send also the tx id of the fee payment, so the offerer can confirm that the payment is seen in the network - // 0 block confirmation is acceptable for the fee to not block the process - // The offerer will wait until a minimum of peers seen the tx before sending his data. - // We also get the multisig tx delivered - /* private void sendTakerOfferFeeTxID(String takeOfferFeeTxID) - { - log.debug("2.2 sendTakerOfferFeeTxID"); - TradeMessageListener listener = new TradeMessageListener() - { - @Override - public void onResult() - { - log.debug("2.2 sendTakerOfferFeeTxID onResult"); - // Message has arrived - //listener.onProgress(getProgress()); - - // We wait until the offerer send us the data - } - - @Override - public void onFailed() - { - log.debug("2.2 sendTakerOfferFeeTxID onFailed"); - // //TakerAsSellerProtocol.this. listener.onFailure("requestAccountDetails onSendTradingMessageFailed"); - } - }; - - // this.listener.onProgress(getProgress()); - - // 2.3. send request for the account details and send fee tx id so offerer can verify that the fee has been paid. - TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.TAKE_OFFER_FEE_PAYED, - trade.getId(), - trade.getTradeAmount(), - takeOfferFeeTxID, - walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString()); - messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener); - } - */ - - //************************************************************************************************ - // 2.3 - 2.6 Offerers tasks, we are in waiting mode - //************************************************************************************************ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 2.7 Incoming msg from offerer - /////////////////////////////////////////////////////////////////////////////////////////// - - /*public void onRequestTakerDepositPaymentMessage(TradeMessageOld requestTradeMessage) - { - log.debug("2.7 onRequestTakerDepositPaymentMessage"); - verifyOfferer(requestTradeMessage); - } */ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 2.8 Verify offerers account registration and against the blacklist - /////////////////////////////////////////////////////////////////////////////////////////// - - /*private void verifyOfferer(TradeMessageOld requestTradeMessage) - { - log.debug("2.8 verifyOfferer"); - log.debug("2.8.1 verifyAccountRegistration"); - if (blockChainFacade.verifyAccountRegistration()) - { - log.debug("2.8.2 isAccountBlackListed"); - if (blockChainFacade.isAccountBlackListed(requestTradeMessage.getAccountId(), requestTradeMessage.getBankAccount())) - { - // listener.onFailure("Offerer is blacklisted."); - } - else - { - createAndSignContract(requestTradeMessage); - } - } - else - { - // listener.onFailure("Offerers account registration is invalid."); - } - } */ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 2.9 Create and sign the contract - /////////////////////////////////////////////////////////////////////////////////////////// - - /* private void createAndSignContract(TradeMessageOld requestTradeMessage) - { - log.debug("2.9 createAndSignContract"); - checkNotNull(trade.getOffer()); - checkNotNull(trade.getTradeAmount()); - checkNotNull(trade.getTakeOfferFeeTxId()); - checkNotNull(requestTradeMessage.getAccountId()); - checkNotNull(user.getAccountId()); - checkNotNull(requestTradeMessage.getBankAccount()); - checkNotNull(user.getCurrentBankAccount()); - checkNotNull(user.getMessagePubKeyAsHex()); - - Contract contract = new Contract(trade.getOffer(), - trade.getTradeAmount(), - trade.getTakeOfferFeeTxId(), - requestTradeMessage.getAccountId(), - user.getAccountId(), - requestTradeMessage.getBankAccount(), - user.getCurrentBankAccount(), - trade.getOffer().getMessagePubKeyAsHex(), - user.getMessagePubKeyAsHex() - ); - - log.debug("2.9 contract created: " + contract); - String contractAsJson = Utilities.objectToJson(contract); - String signature = cryptoFacade.signContract(walletFacade.getRegistrationAddressInfo().getKey(), contractAsJson); - - //log.debug("2.9 contractAsJson: " + contractAsJson); - log.debug("2.9 contract signature: " + signature); - - trade.setContract(contract); - trade.setContractAsJson(contractAsJson); - trade.setContractTakerSignature(signature); - - payDeposit(requestTradeMessage); - } */ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 2.10 Pay in the funds to the deposit tx and sign it - /////////////////////////////////////////////////////////////////////////////////////////// - - /*private void payDeposit(TradeMessageOld requestTradeMessage) - { - log.debug("2.10 payDeposit"); - - BigInteger collateralAmount = trade.getCollateralAmount(); - BigInteger takerInputAmount = trade.getTradeAmount().add(collateralAmount); - BigInteger msOutputAmount = trade.getTradeAmount().add(collateralAmount).add(collateralAmount); - - String offererPubKey = requestTradeMessage.getOffererPubKey(); - String takerPubKey = walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString(); - String arbitratorPubKey = trade.getOffer().getArbitrator().getPubKeyAsHex(); - String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex(); - - checkNotNull(takerInputAmount); - checkNotNull(msOutputAmount); - checkNotNull(offererPubKey); - checkNotNull(takerPubKey); - checkNotNull(arbitratorPubKey); - checkNotNull(preparedOffererDepositTxAsHex); - - log.debug("2.10 offererCreatesMSTxAndAddPayment"); - log.debug("takerAmount " + BtcFormatter.formatSatoshis(takerInputAmount)); - log.debug("msOutputAmount " + BtcFormatter.formatSatoshis(msOutputAmount)); - log.debug("offerer pubkey " + offererPubKey); - log.debug("taker pubkey " + takerPubKey); - log.debug("arbitrator pubkey " + arbitratorPubKey); - log.debug("preparedOffererDepositTxAsHex " + preparedOffererDepositTxAsHex); - try - { - Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSignTx(takerInputAmount, msOutputAmount, offererPubKey, takerPubKey, arbitratorPubKey, preparedOffererDepositTxAsHex, trade.getId()); - log.debug("2.10 deposit tx created: " + signedTakerDepositTx); - long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex(); - sendSignedTakerDepositTxAsHex(signedTakerDepositTx, takerTxOutIndex, requestTradeMessage.getOffererTxOutIndex()); - } catch (InsufficientMoneyException e) - { - log.error("2.10 error at walletFacade.takerAddPaymentAndSign: " + e.getMessage()); - } - } */ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 2.11 Send the tx to the offerer - /////////////////////////////////////////////////////////////////////////////////////////// - - /* private void sendSignedTakerDepositTxAsHex(Transaction signedTakerDepositTx, long takerTxOutIndex, long offererTxOutIndex) - { - log.debug("2.11 sendSignedTakerDepositTxAsHex"); - - TradeMessageListener listener = new TradeMessageListener() - { - @Override - public void onResult() - { - log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onResult"); - // Message arrived at taker - // //TakerAsSellerProtocol.this. listener.onFailure(getProgress()); - } - - @Override - public void onFailed() - { - log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onFailed"); - ////TakerAsSellerProtocol.this. listener.onFailure("sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onFailed"); - } - }; - - // this.listener.onProgress(getProgress()); - - BankAccount bankAccount = user.getCurrentBankAccount(); - String accountID = user.getAccountId(); - String messagePubKey = user.getMessagePubKeyAsHex(); - String contractAsJson = trade.getContractAsJson(); - String signature = trade.getTakerSignature(); - - String signedTakerDepositTxAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.bitcoinSerialize()); - String txScriptSigAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes()); - String txConnOutAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()); - //TODO just 1 address supported yet - String payoutAddress = walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString(); - log.debug("2.10 deposit txAsHex: " + signedTakerDepositTxAsHex); - log.debug("2.10 txScriptSigAsHex: " + txScriptSigAsHex); - log.debug("2.10 txConnOutAsHex: " + txConnOutAsHex); - log.debug("2.10 payoutAddress: " + payoutAddress); - - TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.REQUEST_OFFERER_DEPOSIT_PUBLICATION, - trade.getId(), - bankAccount, - accountID, - messagePubKey, - signedTakerDepositTxAsHex, - txScriptSigAsHex, - txConnOutAsHex, - contractAsJson, - signature, - payoutAddress, - takerTxOutIndex, - offererTxOutIndex - ); - - log.debug("2.11 sendTradingMessage"); - messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener); - } */ - - - //************************************************************************************************ - // 3.1 - 3.5 Offerers tasks, we are in waiting mode - //************************************************************************************************ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 3.6 Incoming msg from offerer - /////////////////////////////////////////////////////////////////////////////////////////// - - /* public void onDepositTxPublishedMessage(TradeMessageOld tradeMessage) - { - log.debug("3.6 DepositTxID received: " + tradeMessage.getDepositTxAsHex()); - - String txID = walletFacade.takerCommitDepositTx(tradeMessage.getDepositTxAsHex()); - // listener.onProgress(getProgress()); - listener.onDepositTxPublishedMessage(txID); - } */ - - - //************************************************************************************************ - // 3.7-3.10 Offerers tasks, we are in waiting mode - //************************************************************************************************ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 3.11 Incoming msg from offerer - /////////////////////////////////////////////////////////////////////////////////////////// - - /* public void onBankTransferInitedMessage(BankTransferInitedMessage tradeMessage) - { - log.debug("3.11 Bank transfer inited msg received"); - listener.onBankTransferInitedMessage(tradeMessage); - } */ - - //************************************************************************************************ - // Taker will check periodically his bank account until he received the money. That might take a while... - //************************************************************************************************ - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 3.12 User clicked the "bank transfer received" button, so we release the funds for pay out - /////////////////////////////////////////////////////////////////////////////////////////// - - /* public void onUIEventFiatReceived(TradeMessageOld tradeMessage) - { - log.debug("3.12 onUIEventFiatReceived"); - FutureCallback callback = new FutureCallback() - { - @Override - public void onSuccess(@javax.annotation.Nullable Transaction transaction) - { - System.out.println("######### 3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction); - log.debug("3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction); - listener.onPayoutTxPublished(transaction.getHashAsString()); - - sendPayoutTxToOfferer(Utils.bytesToHexString(transaction.bitcoinSerialize())); - } - - @Override - public void onFailure(Throwable t) - { - log.error("######### 3.12 onFailure walletFacade.takerSignsAndSendsTx"); - System.err.println("3.12 onFailure walletFacade.takerSignsAndSendsTx"); - // listener.onFailure("takerSignsAndSendsTx failed " + t.getMessage()); - } - }; - try - { - String depositTxAsHex = tradeMessage.getDepositTxAsHex(); - String offererSignatureR = tradeMessage.getOffererSignatureR(); - String offererSignatureS = tradeMessage.getOffererSignatureS(); - BigInteger offererPaybackAmount = tradeMessage.getOffererPaybackAmount(); - BigInteger takerPaybackAmount = tradeMessage.getTakerPaybackAmount(); - String offererPayoutAddress = tradeMessage.getOffererPayoutAddress(); - - log.debug("3.12 walletFacade.takerSignsAndSendsTx"); - walletFacade.takerSignsAndSendsTx(depositTxAsHex, - offererSignatureR, - offererSignatureS, - offererPaybackAmount, - takerPaybackAmount, - offererPayoutAddress, - trade.getId(), - callback); - } catch (AddressFormatException e) - { - log.error("3.12 offererCreatesAndSignsPayoutTx onFailed AddressFormatException " + e.getMessage()); - } - } */ - - /////////////////////////////////////////////////////////////////////////////////////////// - // Step 3.13 Send payout txID to offerer - /////////////////////////////////////////////////////////////////////////////////////////// - - /*void sendPayoutTxToOfferer(String payoutTxAsHex) - { - log.debug("3.13 sendPayoutTxToOfferer "); - TradeMessageListener listener = new TradeMessageListener() - { - @Override - public void onResult() - { - log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onResult"); - log.debug("3.13 TRADE COMPLETE!!!!!!!!!!!"); - //TakerAsSellerProtocol.this. listener.onFailure(getProgress()); - } - - @Override - public void onFailed() - { - log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed"); - //TakerAsSellerProtocol.this. listener.onFailure("sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed"); - } - }; - - TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.PAYOUT_TX_PUBLISHED, trade.getId()); - tradeMessage.setPayoutTxAsHex(payoutTxAsHex); - log.debug("3.13 sendTradeMessage PAYOUT_TX_PUBLISHED"); - messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener); - } */ - - /* private double getProgress() - { - currentStep++; - int numberOfSteps = 10; - return (double) currentStep / (double) numberOfSteps; - } */ - -} diff --git a/src/main/java/io/bitsquare/trade/protocol/taker/VerifyOffererAccount.java b/src/main/java/io/bitsquare/trade/protocol/taker/VerifyOffererAccount.java new file mode 100644 index 0000000000..32c88d056f --- /dev/null +++ b/src/main/java/io/bitsquare/trade/protocol/taker/VerifyOffererAccount.java @@ -0,0 +1,19 @@ +package io.bitsquare.trade.protocol.taker; + +import io.bitsquare.bank.BankAccount; +import io.bitsquare.btc.BlockChainFacade; +import io.bitsquare.trade.protocol.FaultHandler; +import io.bitsquare.trade.protocol.ResultHandler; +import io.bitsquare.trade.protocol.shared.VerifyPeerAccount; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VerifyOffererAccount +{ + private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class); + + public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount) + { + VerifyPeerAccount.run(resultHandler, faultHandler, blockChainFacade, peersAccountId, peersBankAccount); + } +} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/HandleTakeOfferRequest.java b/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/HandleTakeOfferRequest.java deleted file mode 100644 index 08fff63d62..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/HandleTakeOfferRequest.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.bitsquare.trade.protocol.tasks.offerer; - -import io.bitsquare.msg.MessageFacade; -import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.messages.offerer.AcceptTakeOfferRequestMessage; -import io.bitsquare.trade.protocol.messages.offerer.RejectTakeOfferRequestMessage; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import net.tomp2p.peers.PeerAddress; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class HandleTakeOfferRequest -{ - private static final Logger log = LoggerFactory.getLogger(HandleTakeOfferRequest.class); - - public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade.State tradeState, String tradeId) - { - if (tradeState == Trade.State.OPEN) - { - messageFacade.sendTradeMessage(peerAddress, new AcceptTakeOfferRequestMessage(tradeId), new OutgoingTradeMessageListener() - { - @Override - public void onResult() - { - log.trace("AcceptTakeOfferRequestMessage successfully arrived at peer"); - resultHandler.onResult(Trade.State.ACCEPTED); - } - - @Override - public void onFailed() - { - log.error("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer"); - faultHandler.onFault(new Exception("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer")); - } - }); - } - else - { - RejectTakeOfferRequestMessage msg = new RejectTakeOfferRequestMessage(tradeId); - messageFacade.sendTradeMessage(peerAddress, msg, new OutgoingTradeMessageListener() - { - @Override - public void onResult() - { - log.trace("RejectTakeOfferRequestMessage successfully arrived at peer"); - } - - @Override - public void onFailed() - { - log.error("RejectTakeOfferRequestMessage faultHandler.onFault to arrive at peer"); - } - }); - - log.error("Offer not marked as open."); - faultHandler.onFault(new Exception("Offer not marked as open.")); - } - } - - public interface ResultHandler - { - void onResult(Trade.State tradeState); - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SetupListenerForBlockChainConfirmation.java b/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SetupListenerForBlockChainConfirmation.java deleted file mode 100644 index 0ba260a5fe..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SetupListenerForBlockChainConfirmation.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.bitsquare.trade.protocol.tasks.offerer; - -import com.google.bitcoin.core.Transaction; -import com.google.bitcoin.core.TransactionConfidence; -import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocolListener; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SetupListenerForBlockChainConfirmation -{ - private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class); - - public static void run(ResultHandler resultHandler, FaultHandler faultHandler, Transaction depositTransaction, OffererAsBuyerProtocolListener listener) - { //TODO - // sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain(); - - depositTransaction.getConfidence().addEventListener(new TransactionConfidence.Listener() - { - @Override - public void onConfidenceChanged(Transaction tx, ChangeReason reason) - { - log.trace("onConfidenceChanged " + tx.getConfidence()); - if (reason == ChangeReason.SEEN_PEERS) - { - listener.onDepositTxConfirmedUpdate(tx.getConfidence()); - } - if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) - { - listener.onDepositTxConfirmedInBlockchain(); - depositTransaction.getConfidence().removeEventListener(this); - log.trace("Tx is in blockchain"); - resultHandler.onResult(); - } - } - } - ); - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SignAndPublishDepositTx.java b/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SignAndPublishDepositTx.java deleted file mode 100644 index 02cb1478b4..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/offerer/SignAndPublishDepositTx.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.bitsquare.trade.protocol.tasks.offerer; - -import com.google.bitcoin.core.Transaction; -import com.google.common.util.concurrent.FutureCallback; -import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SignAndPublishDepositTx -{ - private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class); - - public static void run(ResultHandler resultHandler, - FaultHandler faultHandler, - WalletFacade walletFacade, - String preparedOffererDepositTxAsHex, - String signedTakerDepositTxAsHex, - String txConnOutAsHex, - String txScriptSigAsHex, - long offererTxOutIndex, - long takerTxOutIndex) - { - try - { - walletFacade.offererSignAndPublishTx(preparedOffererDepositTxAsHex, - signedTakerDepositTxAsHex, - txConnOutAsHex, - txScriptSigAsHex, - offererTxOutIndex, - takerTxOutIndex, - new FutureCallback() - { - @Override - public void onSuccess(Transaction transaction) - { - log.trace("offererSignAndPublishTx succeeded " + transaction); - resultHandler.onResult(transaction); - } - - @Override - public void onFailure(Throwable t) - { - log.error("offererSignAndPublishTx faultHandler.onFault:" + t); - faultHandler.onFault(t); - } - }); - } catch (Exception e) - { - log.error("offererSignAndPublishTx faultHandler.onFault:" + e); - faultHandler.onFault(e); - } - } - - public interface ResultHandler - { - void onResult(Transaction transaction); - } - -} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/CreateAndSignContract.java b/src/main/java/io/bitsquare/trade/protocol/tasks/taker/CreateAndSignContract.java deleted file mode 100644 index ce4c71d89f..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/CreateAndSignContract.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.bitsquare.trade.protocol.tasks.taker; - -import com.google.bitcoin.core.ECKey; -import io.bitsquare.bank.BankAccount; -import io.bitsquare.crypto.CryptoFacade; -import io.bitsquare.trade.Contract; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; -import io.bitsquare.user.User; -import io.bitsquare.util.Utilities; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CreateAndSignContract -{ - private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class); - - public static void run(ResultHandler resultHandler, - FaultHandler faultHandler, - CryptoFacade cryptoFacade, - Trade trade, - User user, - String peersAccountId, - BankAccount peersBankAccount, - ECKey registrationKey) - { - try - { - Contract contract = new Contract(trade.getOffer(), - trade.getTradeAmount(), - trade.getTakeOfferFeeTxId(), - peersAccountId, - user.getAccountId(), - peersBankAccount, - user.getCurrentBankAccount(), - trade.getOffer().getMessagePubKeyAsHex(), - user.getMessagePubKeyAsHex() - ); - - String contractAsJson = Utilities.objectToJson(contract); - String signature = cryptoFacade.signContract(registrationKey, contractAsJson); - //log.trace("contract: " + contract); - //log.debug("contractAsJson: " + contractAsJson); - //log.trace("contract signature: " + signature); - - trade.setContract(contract); - trade.setContractAsJson(contractAsJson); - trade.setContractTakerSignature(signature); - - resultHandler.onResult(); - } catch (Throwable t) - { - log.error("Exception at sign contract " + t); - faultHandler.onFault(t); - } - } - - -} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/PayDeposit.java b/src/main/java/io/bitsquare/trade/protocol/tasks/taker/PayDeposit.java deleted file mode 100644 index 5e67be8f73..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/PayDeposit.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.bitsquare.trade.protocol.tasks.taker; - -import com.google.bitcoin.core.InsufficientMoneyException; -import com.google.bitcoin.core.Transaction; -import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import java.math.BigInteger; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PayDeposit -{ - private static final Logger log = LoggerFactory.getLogger(PayDeposit.class); - - public static void run(ResultHandler resultHandler, FaultHandler faultHandler, WalletFacade walletFacade, Trade trade, String offererPubKey, String preparedOffererDepositTxAsHex) - { - try - { - BigInteger collateralAmount = trade.getCollateralAmount(); - Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSignTx(trade.getTradeAmount().add(collateralAmount), - trade.getTradeAmount().add(collateralAmount).add(collateralAmount), - offererPubKey, - walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString(), - trade.getOffer().getArbitrator().getPubKeyAsHex(), - preparedOffererDepositTxAsHex, - trade.getId()); - - log.trace("sharedModel.signedTakerDepositTx: " + signedTakerDepositTx); - long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex(); - - resultHandler.onResult(signedTakerDepositTx, takerTxOutIndex); - } catch (InsufficientMoneyException e) - { - log.error("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e); - faultHandler.onFault(new Exception("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e)); - } - } - - public interface ResultHandler - { - void onResult(Transaction signedTakerDepositTx, long takerTxOutIndex); - } - - -} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendSignedTakerDepositTxAsHex.java b/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendSignedTakerDepositTxAsHex.java deleted file mode 100644 index 38e4bc30a0..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SendSignedTakerDepositTxAsHex.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.bitsquare.trade.protocol.tasks.taker; - -import com.google.bitcoin.core.Transaction; -import com.google.bitcoin.core.Utils; -import io.bitsquare.btc.WalletFacade; -import io.bitsquare.msg.MessageFacade; -import io.bitsquare.msg.listeners.OutgoingTradeMessageListener; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; -import io.bitsquare.user.User; -import net.tomp2p.peers.PeerAddress; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SendSignedTakerDepositTxAsHex -{ - private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class); - - public static void run(ResultHandler resultHandler, - FaultHandler faultHandler, - PeerAddress peerAddress, - MessageFacade messageFacade, - WalletFacade walletFacade, - Trade trade, - User user, - Transaction signedTakerDepositTx, - long takerTxOutIndex, - long offererTxOutIndex) - { - RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(trade.getId(), - user.getCurrentBankAccount(), - user.getAccountId(), - user.getMessagePubKeyAsHex(), - Utils.bytesToHexString(signedTakerDepositTx.bitcoinSerialize()), - Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes()), - Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()), - trade.getContractAsJson(), - trade.getTakerSignature(), - walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString(), - takerTxOutIndex, - offererTxOutIndex); - messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener() - { - @Override - public void onResult() - { - log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer"); - resultHandler.onResult(); - } - - @Override - public void onFailed() - { - log.error("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer"); - faultHandler.onFault(new Exception("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer")); - } - }); - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SignAndPublishPayoutTx.java b/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SignAndPublishPayoutTx.java deleted file mode 100644 index ef342a303f..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/SignAndPublishPayoutTx.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.bitsquare.trade.protocol.tasks.taker; - -import com.google.bitcoin.core.Transaction; -import com.google.bitcoin.core.Utils; -import com.google.common.util.concurrent.FutureCallback; -import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import java.math.BigInteger; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SignAndPublishPayoutTx -{ - private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class); - - public static void run(ResultHandler resultHandler, - FaultHandler faultHandler, - WalletFacade walletFacade, - Trade trade, - String depositTxAsHex, - String offererSignatureR, - String offererSignatureS, - BigInteger offererPaybackAmount, - BigInteger takerPaybackAmount, - String offererPayoutAddress - ) - { - try - { - - walletFacade.takerSignsAndSendsTx(depositTxAsHex, - offererSignatureR, - offererSignatureS, - offererPaybackAmount, - takerPaybackAmount, - offererPayoutAddress, - trade.getId(), - new FutureCallback() - { - @Override - public void onSuccess(Transaction transaction) - { - log.debug("takerSignsAndSendsTx " + transaction); - String payoutTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize()); - resultHandler.onResult(transaction, payoutTxAsHex); - } - - @Override - public void onFailure(Throwable t) - { - log.error("Exception at takerSignsAndSendsTx " + t); - faultHandler.onFault(t); - } - }); - } catch (Exception e) - { - log.error("Exception at takerSignsAndSendsTx " + e); - faultHandler.onFault(e); - } - } - - public interface ResultHandler - { - void onResult(Transaction transaction, String payoutTxAsHex); - } - -} diff --git a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/VerifyOffererAccount.java b/src/main/java/io/bitsquare/trade/protocol/tasks/taker/VerifyOffererAccount.java deleted file mode 100644 index f4ce650d6f..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/tasks/taker/VerifyOffererAccount.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.bitsquare.trade.protocol.tasks.taker; - -import io.bitsquare.bank.BankAccount; -import io.bitsquare.btc.BlockChainFacade; -import io.bitsquare.trade.protocol.tasks.FaultHandler; -import io.bitsquare.trade.protocol.tasks.ResultHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class VerifyOffererAccount -{ - private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class); - - public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount) - { - //TODO mocked yet - if (blockChainFacade.verifyAccountRegistration()) - { - if (blockChainFacade.isAccountBlackListed(peersAccountId, peersBankAccount)) - { - log.error("Offerer is blacklisted"); - faultHandler.onFault(new Exception("Offerer is blacklisted")); - } - else - { - resultHandler.onResult(); - } - } - else - { - log.error("Account Registration for peer faultHandler.onFault."); - faultHandler.onFault(new Exception("Account Registration for peer faultHandler.onFault.")); - } - } -} diff --git a/src/main/java/io/bitsquare/user/Arbitrator.java b/src/main/java/io/bitsquare/user/Arbitrator.java index ee8d821ba7..56effa061f 100644 --- a/src/main/java/io/bitsquare/user/Arbitrator.java +++ b/src/main/java/io/bitsquare/user/Arbitrator.java @@ -94,18 +94,26 @@ public class Arbitrator implements Serializable public int hashCode() { if (id != null) + { return Objects.hashCode(id); + } else + { return 0; + } } @SuppressWarnings("NonFinalFieldReferenceInEquals") public boolean equals(Object obj) { if (!(obj instanceof Arbitrator)) + { return false; + } if (obj == this) + { return true; + } Arbitrator other = (Arbitrator) obj; return id != null && id.equals(other.getId()); diff --git a/src/main/java/io/bitsquare/user/User.java b/src/main/java/io/bitsquare/user/User.java index a2ca1d9195..4c98bbf262 100644 --- a/src/main/java/io/bitsquare/user/User.java +++ b/src/main/java/io/bitsquare/user/User.java @@ -46,17 +46,28 @@ public class User implements Serializable public void addBankAccount(BankAccount bankAccount) { if (!bankAccounts.contains(bankAccount)) + { bankAccounts.add(bankAccount); + } currentBankAccount = bankAccount; } public void removeCurrentBankAccount() { - if (currentBankAccount != null) bankAccounts.remove(currentBankAccount); + if (currentBankAccount != null) + { + bankAccounts.remove(currentBankAccount); + } - if (bankAccounts.isEmpty()) currentBankAccount = null; - else currentBankAccount = bankAccounts.get(0); + if (bankAccounts.isEmpty()) + { + currentBankAccount = null; + } + else + { + currentBankAccount = bankAccounts.get(0); + } } @@ -74,7 +85,9 @@ public class User implements Serializable bankAccountUIDs += bankAccount.toString(); if (i < bankAccounts.size() - 1) + { bankAccountUIDs += ", "; + } } return bankAccountUIDs; @@ -136,7 +149,9 @@ public class User implements Serializable for (final BankAccount bankAccount : bankAccounts) { if (bankAccount.getUid().equals(bankAccountId)) + { return bankAccount; + } } return null; } diff --git a/src/main/java/io/bitsquare/util/DSAKeyUtil.java b/src/main/java/io/bitsquare/util/DSAKeyUtil.java index 72c2362c2a..a246be4293 100755 --- a/src/main/java/io/bitsquare/util/DSAKeyUtil.java +++ b/src/main/java/io/bitsquare/util/DSAKeyUtil.java @@ -60,9 +60,13 @@ public class DSAKeyUtil } catch (Throwable throwable) { if (throwable instanceof FileNotFoundException) + { log.debug("Files not found. That is ok for the first execute."); + } else + { log.error("Could not read key files. " + throwable); + } try { @@ -114,15 +118,23 @@ public class DSAKeyUtil // Work around an issue on Windows whereby you can't rename over existing files. final File pubKeyCanonicalFile = pubKeyFile.getCanonicalFile(); if (pubKeyCanonicalFile.exists() && !pubKeyCanonicalFile.delete()) + { throw new IOException("Failed to delete pubKeyCanonicalFile for replacement with save"); + } if (!pubKeyTempFile.renameTo(pubKeyCanonicalFile)) + { throw new IOException("Failed to rename " + pubKeyTempFile + " to " + pubKeyCanonicalFile); + } final File privKeyCanonicalFile = privKeyFile.getCanonicalFile(); if (privKeyCanonicalFile.exists() && !privKeyCanonicalFile.delete()) + { throw new IOException("Failed to delete privKeyCanonicalFile for replacement with save"); + } if (!privKeyTempFile.renameTo(privKeyCanonicalFile)) + { throw new IOException("Failed to rename " + privKeyTempFile + " to " + privKeyCanonicalFile); + } } else { @@ -141,13 +153,17 @@ public class DSAKeyUtil { log.warn("PubKeyTempFile still exists after failed save."); if (!pubKeyTempFile.delete()) + { log.warn("Cannot delete pubKeyTempFile."); + } } if (privKeyTempFile.exists()) { log.warn("PrivKeyTempFile still exists after failed save."); if (!privKeyTempFile.delete()) + { log.warn("Cannot delete privKeyTempFile."); + } } lock.unlock(); diff --git a/src/main/java/io/bitsquare/util/FileUtil.java b/src/main/java/io/bitsquare/util/FileUtil.java index 5851d22121..0e600c588a 100644 --- a/src/main/java/io/bitsquare/util/FileUtil.java +++ b/src/main/java/io/bitsquare/util/FileUtil.java @@ -33,7 +33,9 @@ public class FileUtil if (!dir.exists()) { if (!dir.mkdir()) + { log.error("Could not create directory. " + dir.getAbsolutePath()); + } } return dir; diff --git a/src/main/java/io/bitsquare/util/Utilities.java b/src/main/java/io/bitsquare/util/Utilities.java index c5acd39c14..6bd9822b92 100644 --- a/src/main/java/io/bitsquare/util/Utilities.java +++ b/src/main/java/io/bitsquare/util/Utilities.java @@ -82,7 +82,9 @@ public class Utilities private static void printElapsedTime(String msg) { if (!msg.isEmpty()) + { msg += " / "; + } long timeStamp = System.currentTimeMillis(); log.debug(msg + "Elapsed: " + String.valueOf(timeStamp - lastTimeStamp)); lastTimeStamp = timeStamp;