diff --git a/core/src/main/java/io/bitsquare/btc/AddressEntry.java b/core/src/main/java/io/bitsquare/btc/AddressEntry.java index 703ac9dc30..64de13fc02 100644 --- a/core/src/main/java/io/bitsquare/btc/AddressEntry.java +++ b/core/src/main/java/io/bitsquare/btc/AddressEntry.java @@ -23,6 +23,8 @@ import org.bitcoinj.crypto.DeterministicKey; import java.io.Serializable; +import java.util.Arrays; + /** * Is a minimalistic wallet abstraction used to separate transactions between different activities like: * Registration, trade and arbiter deposit. @@ -31,9 +33,11 @@ public class AddressEntry implements Serializable { // That object is saved to disc. We need to take care of changes to not break deserialization. private static final long serialVersionUID = 1L; + // that will be restored from the wallet at deserialisation + private transient DeterministicKey keyPair; + private final String offerId; private final Context context; - private transient DeterministicKey keyPair; private final byte[] pubKey; private final byte[] pubKeyHash; private final NetworkParameters params; @@ -93,8 +97,11 @@ public class AddressEntry implements Serializable { @Override public String toString() { return "AddressEntry{" + - "offerId='" + offerId + - ", addressContext=" + context + + "offerId='" + offerId + '\'' + + ", context=" + context + + ", pubKey=" + Arrays.toString(pubKey) + + ", pubKeyHash=" + Arrays.toString(pubKeyHash) + + ", params=" + params + '}'; } } diff --git a/core/src/main/java/io/bitsquare/btc/AddressEntryList.java b/core/src/main/java/io/bitsquare/btc/AddressEntryList.java index 0e9a2ddd49..34c4ebde65 100644 --- a/core/src/main/java/io/bitsquare/btc/AddressEntryList.java +++ b/core/src/main/java/io/bitsquare/btc/AddressEntryList.java @@ -46,13 +46,14 @@ public class AddressEntryList extends ArrayList implements Seriali this.storage = storage; } - public void init(Wallet wallet) { + public void onWalletReady(Wallet wallet) { this.wallet = wallet; AddressEntryList persisted = storage.initAndGetPersisted(this); if (persisted != null) { for (AddressEntry addressEntry : persisted) { addressEntry.setDeterministicKey((DeterministicKey) wallet.findKeyFromPubHash(addressEntry.getPubKeyHash())); + this.add(addressEntry); } } else { diff --git a/core/src/main/java/io/bitsquare/btc/BitcoinModule.java b/core/src/main/java/io/bitsquare/btc/BitcoinModule.java index fe2af83c32..64e308708b 100644 --- a/core/src/main/java/io/bitsquare/btc/BitcoinModule.java +++ b/core/src/main/java/io/bitsquare/btc/BitcoinModule.java @@ -37,8 +37,7 @@ public class BitcoinModule extends BitsquareModule { @Override protected void configure() { - bind(BitcoinNetwork.class).toInstance( - env.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT)); + bind(BitcoinNetwork.class).toInstance(env.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT)); bind(FeePolicy.class).in(Singleton.class); bindConstant().annotatedWith(named(UserAgent.NAME_KEY)).to(env.getRequiredProperty(UserAgent.NAME_KEY)); @@ -47,10 +46,11 @@ public class BitcoinModule extends BitsquareModule { File walletDir = new File(env.getRequiredProperty(WalletService.DIR_KEY)); bind(File.class).annotatedWith(named(WalletService.DIR_KEY)).toInstance(walletDir); - bindConstant().annotatedWith(named(WalletService.PREFIX_KEY)).to( - env.getRequiredProperty(WalletService.PREFIX_KEY)); - bind(WalletService.class).in(Singleton.class); + bindConstant().annotatedWith(named(WalletService.PREFIX_KEY)).to(env.getRequiredProperty(WalletService.PREFIX_KEY)); + bind(AddressEntryList.class).in(Singleton.class); + bind(TradeWalletService.class).in(Singleton.class); + bind(WalletService.class).in(Singleton.class); bind(BlockChainService.class).in(Singleton.class); } diff --git a/core/src/main/java/io/bitsquare/btc/TradeWalletService.java b/core/src/main/java/io/bitsquare/btc/TradeWalletService.java index 4908bd7cf6..447dd14faa 100644 --- a/core/src/main/java/io/bitsquare/btc/TradeWalletService.java +++ b/core/src/main/java/io/bitsquare/btc/TradeWalletService.java @@ -48,6 +48,8 @@ import com.google.common.util.concurrent.ListenableFuture; import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,17 +83,21 @@ public class TradeWalletService { private static final Logger log = LoggerFactory.getLogger(TradeWalletService.class); private final NetworkParameters params; - private final Wallet wallet; - private final WalletAppKit walletAppKit; + private Wallet wallet; + private WalletAppKit walletAppKit; private final FeePolicy feePolicy; - public TradeWalletService(NetworkParameters params, Wallet wallet, WalletAppKit walletAppKit, FeePolicy feePolicy) { - this.params = params; - this.wallet = wallet; - this.walletAppKit = walletAppKit; + @Inject + public TradeWalletService(BitcoinNetwork bitcoinNetwork, FeePolicy feePolicy) { + this.params = bitcoinNetwork.getParameters(); this.feePolicy = feePolicy; } + public void setWalletAppKit(WalletAppKit walletAppKit) { + this.walletAppKit = walletAppKit; + wallet = walletAppKit.wallet(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Trade fee /////////////////////////////////////////////////////////////////////////////////////////// @@ -142,12 +148,28 @@ public class TradeWalletService { // Trade /////////////////////////////////////////////////////////////////////////////////////////// + private Coin getBalance(List transactionOutputs, Address address) { + Coin balance = Coin.ZERO; + for (TransactionOutput transactionOutput : transactionOutputs) { + if (transactionOutput.getScriptPubKey().isSentToAddress() || transactionOutput.getScriptPubKey().isPayToScriptHash()) { + Address addressOutput = transactionOutput.getScriptPubKey().getToAddress(params); + if (addressOutput.equals(address)) + balance = balance.add(transactionOutput.getValue()); + } + } + return balance; + } + + public Result createOffererDepositTxInputs(Coin offererInputAmount, AddressEntry offererAddressEntry) throws TransactionVerificationException, WalletException { log.trace("createOffererDepositTxInputs called"); log.trace("offererInputAmount " + offererInputAmount.toFriendlyString()); log.trace("offererAddressEntry " + offererAddressEntry.toString()); + Coin balance = getBalance(wallet.calculateAllSpendCandidates(true), offererAddressEntry.getAddress()); + log.trace("balance " + balance.toFriendlyString()); + // We pay the tx fee 2 times to the deposit tx: // 1. Will be spent when publishing the deposit tx (paid by offerer) // 2. Will be added to the MS amount, so when publishing the payout tx the fee is already there and the outputs are not changed by fee reduction diff --git a/core/src/main/java/io/bitsquare/btc/WalletService.java b/core/src/main/java/io/bitsquare/btc/WalletService.java index e4c3ae4854..746356ef10 100644 --- a/core/src/main/java/io/bitsquare/btc/WalletService.java +++ b/core/src/main/java/io/bitsquare/btc/WalletService.java @@ -87,6 +87,8 @@ public class WalletService { private final Observable downloadProgress = downloadListener.getObservable(); private final WalletEventListener walletEventListener = new BitsquareWalletEventListener(); + private final TradeWalletService tradeWalletService; + private final AddressEntryList addressEntryList; private final NetworkParameters params; private final FeePolicy feePolicy; private final SignatureService signatureService; @@ -98,9 +100,7 @@ public class WalletService { private Wallet wallet; private AddressEntry registrationAddressEntry; private AddressEntry arbitratorDepositAddressEntry; - private AddressEntryList addressEntryList; - private TradeWalletService tradeWalletService; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -108,8 +108,9 @@ public class WalletService { @Inject public WalletService(BitcoinNetwork bitcoinNetwork, FeePolicy feePolicy, SignatureService signatureService, - AddressEntryList addressEntryList, UserAgent userAgent, + TradeWalletService tradeWalletService, AddressEntryList addressEntryList, UserAgent userAgent, @Named(DIR_KEY) File walletDir, @Named(PREFIX_KEY) String walletPrefix) { + this.tradeWalletService = tradeWalletService; this.addressEntryList = addressEntryList; this.params = bitcoinNetwork.getParameters(); this.feePolicy = feePolicy; @@ -145,7 +146,8 @@ public class WalletService { walletAppKit.peerGroup().setBloomFilterFalsePositiveRate(0.00001); initWallet(); - tradeWalletService = new TradeWalletService(params, wallet, walletAppKit, feePolicy); + // set after wallet is ready + tradeWalletService.setWalletAppKit(walletAppKit); status.onCompleted(); } @@ -200,7 +202,7 @@ public class WalletService { wallet = walletAppKit.wallet(); wallet.addEventListener(walletEventListener); - addressEntryList.init(wallet); + addressEntryList.onWalletReady(wallet); registrationAddressEntry = addressEntryList.getRegistrationAddressEntry(); } diff --git a/core/src/main/java/io/bitsquare/gui/GuiModule.java b/core/src/main/java/io/bitsquare/gui/GuiModule.java index 754574691f..8e7ab1dd8c 100644 --- a/core/src/main/java/io/bitsquare/gui/GuiModule.java +++ b/core/src/main/java/io/bitsquare/gui/GuiModule.java @@ -62,8 +62,9 @@ public class GuiModule extends BitsquareModule { bind(ViewLoader.class).to(FxmlViewLoader.class).in(Singleton.class); bind(CachingViewLoader.class).in(Singleton.class); - bind(OfferBook.class).in(Singleton.class); bind(Navigation.class).in(Singleton.class); + + bind(OfferBook.class).in(Singleton.class); bind(OverlayManager.class).in(Singleton.class); bind(BSFormatter.class).in(Singleton.class); diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java index 6a56ae1b47..1dbcfccc2e 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java @@ -112,24 +112,18 @@ class PendingTradesDataModel implements Activatable, DataModel { removeListenerFromSelectedTrade(); selectedItem = item; + isOfferer = getTrade().getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey()); - if (selectedItem != null) { - isOfferer = getTrade().getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey()); + Trade trade = getTrade(); + if (trade instanceof TakerTrade) + takerProcessState.bind(((TakerTrade) trade).processStateProperty()); + else + offererProcessState.bind(((OffererTrade) trade).processStateProperty()); - Trade trade = getTrade(); - if (trade instanceof TakerTrade) - takerProcessState.bind(((TakerTrade) trade).processStateProperty()); - else - offererProcessState.bind(((OffererTrade) trade).processStateProperty()); + log.trace("selectTrade trade.stateProperty().get() " + trade.processStateProperty().get()); - log.trace("selectTrade trade.stateProperty().get() " + trade.processStateProperty().get()); - - if (trade.getDepositTx() != null) - txId.set(trade.getDepositTx().getHashAsString()); - } - else { - txId.set(null); - } + if (trade.getDepositTx() != null) + txId.set(trade.getDepositTx().getHashAsString()); } void fiatPaymentStarted() { diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java index 5a02173971..f142c839ba 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java @@ -139,8 +139,10 @@ public class PendingTradesView extends ActivatableViewAndModel { - model.selectTrade(newValue); - updateScreen(); + if (newValue != null) { + model.selectTrade(newValue); + updateScreen(); + } }; withdrawAddressTextField.setValidator(model.getBtcAddressValidator()); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/placeoffer/PlaceOfferProtocol.java b/core/src/main/java/io/bitsquare/trade/protocol/placeoffer/PlaceOfferProtocol.java index 7d57f3e8c3..6e4e7b256a 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/placeoffer/PlaceOfferProtocol.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/placeoffer/PlaceOfferProtocol.java @@ -53,6 +53,7 @@ public class PlaceOfferProtocol { /////////////////////////////////////////////////////////////////////////////////////////// public void placeOffer() { + log.debug("model.offer.id" + model.offer.getId()); TaskRunner taskRunner = new TaskRunner<>(model, () -> { log.debug("sequence at handleRequestTakeOfferMessage completed"); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/CreateOffererDepositTxInputs.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/CreateOffererDepositTxInputs.java index 8f5fd993fb..3af8ffe31d 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/CreateOffererDepositTxInputs.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/CreateOffererDepositTxInputs.java @@ -38,6 +38,7 @@ public class CreateOffererDepositTxInputs extends Task { @Override protected void doRun() { try { + log.debug("model.trade.id" + model.trade.getId()); Coin offererInputAmount = model.trade.getSecurityDeposit().add(FeePolicy.TX_FEE); TradeWalletService.Result result = model.tradeWalletService.createOffererDepositTxInputs(offererInputAmount, model.offerer.addressEntry);