payment process summary screen offerer, process imporved

This commit is contained in:
Manfred Karrer 2014-05-19 19:16:11 +02:00
parent 1215f338ad
commit d39ae903ff
15 changed files with 428 additions and 198 deletions

View File

@ -8,7 +8,7 @@ import java.math.BigInteger;
public class Fees
{
// min dust value lead to exception at for non standard to address pay scripts, so we use a value >= 7860 instead
public static BigInteger MS_TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
public static BigInteger TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
public static BigInteger ACCOUNT_REGISTRATION_FEE = Utils.toNanoCoins("0.0002");
public static BigInteger OFFER_CREATION_FEE = Utils.toNanoCoins("0.0002");
public static BigInteger OFFER_TAKER_FEE = OFFER_CREATION_FEE;

View File

@ -91,7 +91,7 @@ public class WalletFacade
// Now configure and start the appkit. This will take a second or two - we could show a temporary splash screen
// or progress widget to keep the user engaged whilst we initialise, but we don't.
walletAppKit.setDownloadListener(new BlockChainDownloadListener()).setBlockingStartup(false).setUserAgent(BitSquare.ID, "0.1");
walletAppKit.setDownloadListener(new BlockChainDownloadListener()).setBlockingStartup(false).setUserAgent("BitSquare", "0.1");
walletAppKit.startAsync();
walletAppKit.awaitRunning();
@ -190,7 +190,8 @@ public class WalletFacade
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
// give fee to miners yet. Later it could be spent to other traders via lottery...
sendRequest.fee = Fees.ACCOUNT_REGISTRATION_FEE.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
sendRequest.fee = Fees.ACCOUNT_REGISTRATION_FEE.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Fees.TX_FEE);
log.trace("sendRequest.fee: " + Utils.bitcoinValueToFriendlyString(sendRequest.fee));
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
log.debug("Registration transaction: " + tx.toString());
printInputs("publishRegistrationTxWithExtraData", tx);
@ -215,6 +216,8 @@ public class WalletFacade
// Trade process
///////////////////////////////////////////////////////////////////////////////////////////
//TODO refactor to similar solution like in PaymentChannelServerState
public String payOfferFee(BigInteger fee, FutureCallback<Transaction> callback) throws InsufficientMoneyException
{
log.debug("payOfferFee fee=" + Utils.bitcoinValueToFriendlyString(fee));
@ -222,7 +225,7 @@ public class WalletFacade
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, WalletUtil.getEmptyOP_RETURNScript());
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
sendRequest.fee = fee.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
sendRequest.fee = fee.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Fees.TX_FEE);
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
Futures.addCallback(sendResult.broadcastComplete, callback);
@ -344,11 +347,14 @@ public class WalletFacade
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(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
msOutputAmount = msOutputAmount.add(Fees.TX_FEE);
tx.getOutput(0).setValue(msOutputAmount);
// 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);
Sha256Hash hash = tx.hashForSignature(1, scriptPubKey, Transaction.SigHash.ALL, false);
@ -436,11 +442,11 @@ public class WalletFacade
//TODO handle non change output cases
// add outputs from takers tx, they are already correct
for (int i = 0; i < takersSignedTx.getOutputs().size(); i++)
{
tx.addOutput(takersSignedTx.getOutput(i));
}
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.toString());
@ -448,6 +454,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);
Sha256Hash hash = tx.hashForSignature(0, scriptPubKey, Transaction.SigHash.ALL, false);
@ -503,7 +512,19 @@ public class WalletFacade
log.trace("depositTxID=" + depositTxAsHex);
Transaction depositTx = new Transaction(params, Utils.parseAsHexOrBase58(depositTxAsHex));
log.trace("depositTx=" + depositTx);
wallet.commitTx(depositTx);
// boolean isAlreadyInWallet = wallet.maybeCommitTx(depositTx);
//log.trace("isAlreadyInWallet=" + isAlreadyInWallet);
try
{
// Manually add the multisigContract to the wallet, overriding the isRelevant checks so we can track
// it and check for double-spends later
wallet.receivePending(depositTx, null, true);
} catch (VerificationException e)
{
throw new RuntimeException(e); // Cannot happen, we already called multisigContract.verify()
}
}
// 5. step payout tx: Offerer creates payout tx and signs it

View File

@ -2,10 +2,10 @@ package io.bitsquare.di;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Utils;
import com.google.bitcoin.kits.WalletAppKit;
import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.params.RegTestParams;
import com.google.bitcoin.params.TestNet3Params;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provider;
@ -22,9 +22,12 @@ import io.bitsquare.trade.orderbook.OrderBook;
import io.bitsquare.trade.orderbook.OrderBookFilter;
import io.bitsquare.user.User;
import io.bitsquare.util.Utilities;
import org.spongycastle.util.encoders.Hex;
import java.io.File;
import static com.google.common.base.Preconditions.checkState;
public class BitSquareModule extends AbstractModule
{
@ -88,7 +91,7 @@ class NetworkParametersProvider implements Provider<NetworkParameters>
result = MainNetParams.get();
break;
case WalletFacade.TEST_NET:
result = TestNet3Params.get();
result = TestNet3Params2.get();
break;
case WalletFacade.REG_TEST_NET:
result = RegTestParams.get();
@ -96,4 +99,57 @@ class NetworkParametersProvider implements Provider<NetworkParameters>
}
return result;
}
}
}
/**
* UnknownHostException with testnet-seed.bitcoin.petertodd.org so use testnet-seed.bluematt.me as primary DND seed server
* testnet-seed.bluematt.me delivers 1 dead node, so nothing works yet... ;-(
* http://sourceforge.net/p/bitcoin/mailman/message/32349208/
*/
class TestNet3Params2 extends NetworkParameters
{
public TestNet3Params2()
{
super();
id = ID_TESTNET;
// Genesis hash is 000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943
packetMagic = 0x0b110907;
interval = INTERVAL;
targetTimespan = TARGET_TIMESPAN;
proofOfWorkLimit = Utils.decodeCompactBits(0x1d00ffffL);
port = 18333;
addressHeader = 111;
p2shHeader = 196;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
dumpedPrivateKeyHeader = 239;
genesisBlock.setTime(1296688602L);
genesisBlock.setDifficultyTarget(0x1d00ffffL);
genesisBlock.setNonce(414098458);
spendableCoinbaseDepth = 100;
subsidyDecreaseBlockCount = 210000;
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"));
alertSigningKey = Hex.decode("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a");
dnsSeeds = new String[]{
"testnet-seed.bluematt.me"
};
}
private static TestNet3Params2 instance;
public static synchronized TestNet3Params2 get()
{
if (instance == null)
{
instance = new TestNet3Params2();
}
return instance;
}
public String getPaymentProtocolId()
{
return PAYMENT_PROTOCOL_ID_TESTNET;
}
}

View File

@ -94,7 +94,7 @@ public class CreateOfferController implements Initializable, ChildController
//TODO
amountTextField.setText("0,1");
amountTextField.setText("0,001");
minAmountTextField.setText("0,001");
priceTextField.setText("300");
collateralTextField.setText("50");

View File

@ -171,7 +171,7 @@ public class TakerTradeController implements Initializable, ChildController
totalLabel = FormBuilder.addTextField(gridPane, "Total (" + offer.getCurrency() + "):", Formatter.formatVolume(getVolume()), ++row);
collateralTextField = FormBuilder.addTextField(gridPane, "Collateral (BTC):", "", ++row);
applyCollateral();
FormBuilder.addTextField(gridPane, "Offer fee (BTC):", Utils.bitcoinValueToFriendlyString(Fees.OFFER_TAKER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)), ++row);
FormBuilder.addTextField(gridPane, "Offer fee (BTC):", Utils.bitcoinValueToFriendlyString(Fees.OFFER_TAKER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Fees.TX_FEE)), ++row);
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPay(), ++row);
isOnlineTextField = FormBuilder.addTextField(gridPane, "Online status:", "Checking offerers online status...", ++row);
@ -361,14 +361,19 @@ public class TakerTradeController implements Initializable, ChildController
gridPane.getChildren().clear();
row = -1;
FormBuilder.addHeaderLabel(gridPane, "Trade successfully completed", ++row);
FormBuilder.addTextField(gridPane, "You have payed in total (BTC):", getTotalToPay(), ++row);
String fiatReceived = Formatter.formatVolume(trade.getOffer().getPrice() * trade.getTradeAmount().doubleValue());
FormBuilder.addTextField(gridPane, "You have sold (BTC):", Utils.bitcoinValueToFriendlyString(trade.getTradeAmount()), ++row);
if (takerIsSelling())
{
FormBuilder.addTextField(gridPane, "You got returned collateral (BTC):", BtcFormatter.formatSatoshis(getCollateralInSatoshis(), false), ++row);
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):", Formatter.formatVolume(getVolume()), ++row);
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):\"", fiatReceived, ++row);
FormBuilder.addTextField(gridPane, "Total fees (take offer fee + tx fee):", Utils.bitcoinValueToFriendlyString(Fees.OFFER_TAKER_FEE.add(Fees.TX_FEE)), ++row);
FormBuilder.addTextField(gridPane, "Refunded collateral:", Utils.bitcoinValueToFriendlyString(trade.getCollateralAmount()), ++row);
}
else
{
//TODO
FormBuilder.addTextField(gridPane, "You got returned collateral (BTC):", BtcFormatter.formatSatoshis(getCollateralInSatoshis(), false), ++row);
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):", Formatter.formatVolume(getVolume()), ++row);
FormBuilder.addTextField(gridPane, "You have received (BTC):", BtcFormatter.formatSatoshis(offer.getAmount(), false), ++row);
@ -433,11 +438,11 @@ public class TakerTradeController implements Initializable, ChildController
{
if (takerIsSelling())
{
return BtcFormatter.formatSatoshis(getAmountInSatoshis().add(Fees.OFFER_TAKER_FEE).add(Transaction.MIN_NONDUST_OUTPUT).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).add(getCollateralInSatoshis()), false);
return BtcFormatter.formatSatoshis(getAmountInSatoshis().add(Fees.OFFER_TAKER_FEE).add(Transaction.MIN_NONDUST_OUTPUT).add(Fees.TX_FEE).add(getCollateralInSatoshis()), false);
}
else
{
return BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).add(getCollateralInSatoshis()), false) + "\n" +
return BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Fees.TX_FEE).add(getCollateralInSatoshis()), false) + "\n" +
Formatter.formatVolume(getVolume(), offer.getCurrency());
}
}

View File

@ -1,19 +1,18 @@
package io.bitsquare.gui.orders;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.core.WalletEventListener;
import com.google.bitcoin.core.*;
import com.google.bitcoin.script.Script;
import com.google.inject.Inject;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.btc.Fees;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.util.ConfidenceDisplay;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.gui.util.Icons;
import io.bitsquare.gui.util.Localisation;
import io.bitsquare.trade.Direction;
@ -36,6 +35,7 @@ import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -51,11 +51,14 @@ public class OrdersController implements Initializable, ChildController
private Trading trading;
private WalletFacade walletFacade;
private Trade currentTrade;
private NavigationController navigationController;
private Image buyIcon = Icons.getIconImage(Icons.BUY);
private Image sellIcon = Icons.getIconImage(Icons.SELL);
private ConfidenceDisplay confidenceDisplay;
@FXML
private VBox rootContainer;
@FXML
private TableView openTradesTable;
@FXML
@ -63,7 +66,8 @@ public class OrdersController implements Initializable, ChildController
@FXML
private ProgressIndicator progressIndicator;
@FXML
private Label confirmationLabel, txIDCopyIcon, holderNameCopyIcon, primaryBankAccountIDCopyIcon, secondaryBankAccountIDCopyIcon;
private Label txTitleLabel, txHeaderLabel, confirmationLabel, txIDCopyIcon, holderNameCopyIcon, primaryBankAccountIDCopyIcon, secondaryBankAccountIDCopyIcon, bankAccountDetailsHeaderLabel,
bankAccountTypeTitleLabel, holderNameTitleLabel, primaryBankAccountIDTitleLabel, secondaryBankAccountIDTitleLabel;
@FXML
private TextField txTextField, bankAccountTypeTextField, holderNameTextField, primaryBankAccountIDTextField, secondaryBankAccountIDTextField;
@FXML
@ -82,6 +86,10 @@ public class OrdersController implements Initializable, ChildController
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb)
{
@ -135,19 +143,19 @@ public class OrdersController implements Initializable, ChildController
{
openTradesTable.getSelectionModel().select(0);
}
}
});
}
private void showTradeDetails(TradesTableItem tradesTableItem)
{
fillData(tradesTableItem.getTrade());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: ChildController
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setNavigationController(NavigationController navigationController)
{
this.navigationController = navigationController;
}
@Override
@ -155,74 +163,83 @@ public class OrdersController implements Initializable, ChildController
{
}
///////////////////////////////////////////////////////////////////////////////////////////
// GUI handlers
///////////////////////////////////////////////////////////////////////////////////////////
public void bankTransferInited(ActionEvent actionEvent)
{
trading.onBankTransferInited(currentTrade.getUid());
bankTransferInitedButton.setDisable(true);
}
private void updateTx(Trade trade)
public void close(ActionEvent actionEvent)
{
Transaction transaction = trade.getDepositTransaction();
if (transaction != null)
{
confirmationLabel.setVisible(true);
progressIndicator.setVisible(true);
progressIndicator.setProgress(-1);
txTextField.setText(transaction.getHashAsString());
confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, transaction, progressIndicator);
int depthInBlocks = transaction.getConfidence().getDepthInBlocks();
bankTransferInitedButton.setDisable(depthInBlocks == 0);
walletFacade.getWallet().addEventListener(new WalletEventListener()
{
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
int depthInBlocks = tx.getConfidence().getDepthInBlocks();
bankTransferInitedButton.setDisable(depthInBlocks == 0);
}
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
}
@Override
public void onReorganize(Wallet wallet)
{
}
@Override
public void onWalletChanged(Wallet wallet)
{
}
@Override
public void onKeysAdded(Wallet wallet, List<ECKey> keys)
{
}
@Override
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
{
}
});
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void showTradeDetails(TradesTableItem tradesTableItem)
{
fillData(tradesTableItem.getTrade());
}
private void updateTx(Transaction transaction)
{
txTextField.setText(transaction.getHashAsString());
confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, transaction, progressIndicator);
int depthInBlocks = transaction.getConfidence().getDepthInBlocks();
bankTransferInitedButton.setDisable(depthInBlocks == 0);
walletFacade.getWallet().addEventListener(new WalletEventListener()
{
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
int depthInBlocks = tx.getConfidence().getDepthInBlocks();
bankTransferInitedButton.setDisable(depthInBlocks == 0);
}
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
}
@Override
public void onReorganize(Wallet wallet)
{
}
@Override
public void onWalletChanged(Wallet wallet)
{
}
@Override
public void onKeysAdded(Wallet wallet, List<ECKey> keys)
{
}
@Override
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
{
}
});
}
private void fillData(Trade trade)
{
currentTrade = trade;
@ -234,13 +251,13 @@ public class OrdersController implements Initializable, ChildController
@Override
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean aBoolean, Boolean aBoolean2)
{
updateTx(trade);
updateTx(trade.getDepositTransaction());
}
});
}
else
{
updateTx(trade);
updateTx(trade.getDepositTransaction());
}
// back details
@ -259,19 +276,95 @@ public class OrdersController implements Initializable, ChildController
}
});
}
// state
trade.getStateChangedProperty().addListener(new ChangeListener<String>()
{
@Override
public void changed(ObservableValue<? extends String> observableValue, String aString, String aString2)
{
setState(trade);
}
});
}
private void setState(Trade trade)
{
if (trade.getState() == Trade.State.COMPLETED)
{
Transaction transaction = trade.getPayoutTransaction();
confidenceDisplay.destroy();
confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, transaction, progressIndicator);
txTextField.setText(transaction.getHashAsString());
txHeaderLabel.setText("Payout transaction");
txTitleLabel.setText("Payout transaction ID:");
bankAccountDetailsHeaderLabel.setText("Summary");
bankAccountTypeTitleLabel.setText("You have bought (BTC):");
holderNameTitleLabel.setText("You have payed (" + trade.getOffer().getCurrency() + "):");
primaryBankAccountIDTitleLabel.setText("Total fees (offer fee + tx fee):");
secondaryBankAccountIDTitleLabel.setText("Refunded collateral:");
String fiatPayed = Formatter.formatVolume(trade.getOffer().getPrice() * trade.getTradeAmount().doubleValue());
bankAccountTypeTextField.setText(Utils.bitcoinValueToFriendlyString(trade.getTradeAmount()));
holderNameTextField.setText(fiatPayed);
primaryBankAccountIDTextField.setText(Utils.bitcoinValueToFriendlyString(Fees.OFFER_CREATION_FEE.add(Fees.TX_FEE)));
secondaryBankAccountIDTextField.setText(Utils.bitcoinValueToFriendlyString(trade.getCollateralAmount()));
holderNameCopyIcon.setVisible(false);
primaryBankAccountIDCopyIcon.setVisible(false);
secondaryBankAccountIDCopyIcon.setVisible(false);
bankTransferInitedButton.setVisible(false);
}
}
private void setBankData(Trade trade)
{
BankAccount bankAccount = trade.getContract().getTakerBankAccount();
//TODO why null?
if (bankAccount != null)
{
bankAccountTypeTextField.setText(bankAccount.getBankAccountType().getType().toString());
holderNameTextField.setText(bankAccount.getAccountHolderName());
primaryBankAccountIDTextField.setText(bankAccount.getAccountPrimaryID());
secondaryBankAccountIDTextField.setText(bankAccount.getAccountSecondaryID());
}
bankAccountTypeTextField.setText(bankAccount.getBankAccountType().getType().toString());
holderNameTextField.setText(bankAccount.getAccountHolderName());
primaryBankAccountIDTextField.setText(bankAccount.getAccountPrimaryID());
secondaryBankAccountIDTextField.setText(bankAccount.getAccountSecondaryID());
}
private void initCopyIcons()
{
AwesomeDude.setIcon(txIDCopyIcon, AwesomeIcon.COPY);
txIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(txTextField.getText());
clipboard.setContent(content);
});
AwesomeDude.setIcon(holderNameCopyIcon, AwesomeIcon.COPY);
holderNameCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(holderNameTextField.getText());
clipboard.setContent(content);
});
AwesomeDude.setIcon(primaryBankAccountIDCopyIcon, AwesomeIcon.COPY);
primaryBankAccountIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(primaryBankAccountIDTextField.getText());
clipboard.setContent(content);
});
AwesomeDude.setIcon(secondaryBankAccountIDCopyIcon, AwesomeIcon.COPY);
secondaryBankAccountIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(secondaryBankAccountIDTextField.getText());
clipboard.setContent(content);
});
}
@ -438,41 +531,5 @@ public class OrdersController implements Initializable, ChildController
});
}
private void initCopyIcons()
{
AwesomeDude.setIcon(txIDCopyIcon, AwesomeIcon.COPY);
txIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(txTextField.getText());
clipboard.setContent(content);
});
AwesomeDude.setIcon(holderNameCopyIcon, AwesomeIcon.COPY);
holderNameCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(holderNameTextField.getText());
clipboard.setContent(content);
});
AwesomeDude.setIcon(primaryBankAccountIDCopyIcon, AwesomeIcon.COPY);
primaryBankAccountIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(primaryBankAccountIDTextField.getText());
clipboard.setContent(content);
});
AwesomeDude.setIcon(secondaryBankAccountIDCopyIcon, AwesomeIcon.COPY);
secondaryBankAccountIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(secondaryBankAccountIDTextField.getText());
clipboard.setContent(content);
});
}
}

View File

@ -4,7 +4,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.*?>
<VBox fx:controller="io.bitsquare.gui.orders.OrdersController" spacing="10" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0"
<VBox fx:id="rootContainer" fx:controller="io.bitsquare.gui.orders.OrdersController" spacing="10" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0"
AnchorPane.topAnchor="0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1">
<children>
@ -56,13 +56,14 @@
<GridPane hgap="5.0" vgap="5.0">
<children>
<!-- row 0 -->
<Label id="headline-label" text="Deposit transaction" GridPane.columnSpan="2" GridPane.halignment="LEFT"/>
<Label fx:id="txHeaderLabel" id="headline-label" text="Deposit transaction" GridPane.columnSpan="2" GridPane.halignment="LEFT"/>
<!-- row 1 -->
<Label text="Transaction ID:" GridPane.rowIndex="1"/>
<Label fx:id="txTitleLabel" text="Deposit transaction ID:" GridPane.rowIndex="1"/>
<TextField fx:id="txTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label id="copy-icon" fx:id="txIDCopyIcon" minWidth="10" GridPane.columnIndex="2" GridPane.rowIndex="1">
<Label fx:id="txIDCopyIcon" id="copy-icon" minWidth="10" GridPane.columnIndex="2" GridPane.rowIndex="1">
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="-1.0"/>
</padding>
@ -70,7 +71,7 @@
<Tooltip text="Copy address to clipboard"/>
</tooltip>
</Label>
<ProgressIndicator id="confidence-progress-indicator" fx:id="progressIndicator" visible="false" GridPane.columnIndex="3" GridPane.halignment="LEFT" GridPane.rowIndex="1"
<ProgressIndicator fx:id="progressIndicator" id="confidence-progress-indicator" visible="false" progress="0" GridPane.columnIndex="3" GridPane.halignment="LEFT" GridPane.rowIndex="1"
GridPane.rowSpan="2" GridPane.valignment="TOP">
<GridPane.margin>
<Insets top="2.0"/>
@ -78,18 +79,18 @@
</ProgressIndicator>
<Label fx:id="confirmationLabel" visible="false" GridPane.columnIndex="4" GridPane.rowIndex="1"/>
<!-- row 2 -->
<Label id="headline-label" text="Bank details" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="LEFT" GridPane.rowIndex="2"/>
<Label fx:id="bankAccountDetailsHeaderLabel" id="headline-label" text="Bank details" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="LEFT"
GridPane.rowIndex="2"/>
<!-- row 3 -->
<Label text="Bank account type:" GridPane.columnIndex="0" GridPane.rowIndex="3"/>
<Label fx:id="bankAccountTypeTitleLabel" text="Bank account type:" GridPane.columnIndex="0" GridPane.rowIndex="3"/>
<TextField fx:id="bankAccountTypeTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
<!-- row 4 -->
<Label text="Holder name:" GridPane.columnIndex="0" GridPane.rowIndex="4"/>
<Label fx:id="holderNameTitleLabel" text="Holder name:" GridPane.columnIndex="0" GridPane.rowIndex="4"/>
<TextField fx:id="holderNameTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<Label id="copy-icon" fx:id="holderNameCopyIcon" minWidth="10" GridPane.columnIndex="2" GridPane.rowIndex="4">
<Label fx:id="holderNameCopyIcon" id="copy-icon" minWidth="10" GridPane.columnIndex="2" GridPane.rowIndex="4">
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="-1.0"/>
</padding>
@ -99,9 +100,9 @@
</Label>
<!-- row 5 -->
<Label text="Primary bank account ID:" GridPane.columnIndex="0" GridPane.rowIndex="5"/>
<Label fx:id="primaryBankAccountIDTitleLabel" text="Primary bank account ID:" GridPane.columnIndex="0" GridPane.rowIndex="5"/>
<TextField fx:id="primaryBankAccountIDTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="5"/>
<Label id="copy-icon" fx:id="primaryBankAccountIDCopyIcon" minWidth="10" GridPane.columnIndex="2" GridPane.rowIndex="5">
<Label fx:id="primaryBankAccountIDCopyIcon" id="copy-icon" minWidth="10" GridPane.columnIndex="2" GridPane.rowIndex="5">
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="-1.0"/>
</padding>
@ -111,9 +112,9 @@
</Label>
<!-- row 6 -->
<Label text="Secondary bank account ID:" GridPane.columnIndex="0" GridPane.rowIndex="6"/>
<Label fx:id="secondaryBankAccountIDTitleLabel" text="Secondary bank account ID:" GridPane.columnIndex="0" GridPane.rowIndex="6"/>
<TextField fx:id="secondaryBankAccountIDTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="6"/>
<Label id="copy-icon" fx:id="secondaryBankAccountIDCopyIcon" minWidth="10" GridPane.columnIndex="2" GridPane.rowIndex="6">
<Label fx:id="secondaryBankAccountIDCopyIcon" id="copy-icon" minWidth="10" GridPane.columnIndex="2" GridPane.rowIndex="6">
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="-1.0"/>
</padding>
@ -123,7 +124,9 @@
</Label>
<!-- row 7 -->
<Button fx:id="bankTransferInitedButton" defaultButton="true" onAction="#bankTransferInited" disable="true" text="Bank transfer inited" GridPane.columnIndex="1" GridPane.rowIndex="7"/>
<Button fx:id="bankTransferInitedButton" defaultButton="true" onAction="#bankTransferInited" disable="true" text="Bank transfer inited"
GridPane.columnIndex="1"
GridPane.rowIndex="7"/>
</children>
<columnConstraints>

View File

@ -184,7 +184,7 @@ public class SetupController implements Initializable, ChildController
public void onClose(ActionEvent actionEvent)
{
navigationController.navigateToView(NavigationController.MARKET, "");
navigationController.navigateToView(NavigationController.FUNDS, "");
}

View File

@ -16,10 +16,12 @@ import java.util.Set;
public class ConfidenceDisplay
{
private static final Logger log = LoggerFactory.getLogger(ConfidenceDisplay.class);
private WalletEventListener walletEventListener;
private Wallet wallet;
private Label confirmationLabel;
private TextField balanceTextField;
private Transaction transaction;
private ProgressIndicator progressIndicator;
/**
@ -43,8 +45,7 @@ public class ConfidenceDisplay
progressIndicator.setProgress(0);
updateBalance(wallet.getBalance());
wallet.addEventListener(new WalletEventListener()
walletEventListener = new WalletEventListener()
{
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
@ -63,6 +64,7 @@ public class ConfidenceDisplay
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
updateBalance(newBalance);
}
@Override
@ -84,19 +86,21 @@ public class ConfidenceDisplay
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
{
}
});
};
wallet.addEventListener(walletEventListener);
}
/**
* @param wallet
* @param confirmationLabel
* @param newTransaction We want the confidence for only that tx, not the lasted changed in the wallet
* @param transaction We want the confidence for only that tx, not the lasted changed in the wallet
* @param progressIndicator
*/
public ConfidenceDisplay(Wallet wallet, Label confirmationLabel, final Transaction newTransaction, ProgressIndicator progressIndicator)
public ConfidenceDisplay(Wallet wallet, Label confirmationLabel, final Transaction transaction, ProgressIndicator progressIndicator)
{
this.wallet = wallet;
this.confirmationLabel = confirmationLabel;
this.transaction = transaction;
this.progressIndicator = progressIndicator;
if (balanceTextField != null)
@ -106,26 +110,31 @@ public class ConfidenceDisplay
progressIndicator.setProgress(0);
updateBalance(wallet.getBalance());
updateConfidence(transaction);
wallet.addEventListener(new WalletEventListener()
walletEventListener = new WalletEventListener()
{
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
updateBalance(newBalance);
if (tx.getHashAsString().equals(transaction.getHashAsString()))
updateBalance(newBalance);
// log.debug("onCoinsReceived " + newBalance);
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
updateConfidence(newTransaction);
if (tx.getHashAsString().equals(transaction.getHashAsString()))
updateConfidence(transaction);
// log.debug("onTransactionConfidenceChanged newTransaction " + newTransaction.getHashAsString());
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
if (tx.getHashAsString().equals(transaction.getHashAsString()))
updateBalance(newBalance);
}
@Override
@ -147,7 +156,24 @@ public class ConfidenceDisplay
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
{
}
});
};
wallet.addEventListener(walletEventListener);
}
public void destroy()
{
boolean wasInList = wallet.removeEventListener(walletEventListener);
log.trace("ConfidenceDisplay.destroy wasInList = " + wasInList);
progressIndicator.setProgress(0);
confirmationLabel.setText("");
if (balanceTextField != null)
balanceTextField.setText("");
walletEventListener = null;
wallet = null;
confirmationLabel = null;
progressIndicator = null;
balanceTextField = null;
}
private void updateBalance(BigInteger balance)
@ -175,18 +201,22 @@ public class ConfidenceDisplay
latestTransaction = transaction;
}
}
if (latestTransaction != null)
{
if (latestTransaction != null && (transaction == null || latestTransaction.getHashAsString().equals(transaction.getHashAsString())))
updateConfidence(latestTransaction);
}
}
if (balanceTextField != null)
balanceTextField.setText(Utils.bitcoinValueToFriendlyString(balance));
}
private void updateConfidence(Transaction tx)
{
log.debug("updateConfidence: " + this.toString());
log.debug("tx: " + tx.getHashAsString());
TransactionConfidence confidence = tx.getConfidence();
log.debug("ConfidenceType: " + confidence.getConfidenceType().toString());
log.debug("numBroadcastPeers: " + confidence.numBroadcastPeers());
log.debug("getDepthInBlocks: " + confidence.getDepthInBlocks());
double progressIndicatorSize = 50;
switch (confidence.getConfidenceType())
{

View File

@ -37,7 +37,9 @@ public class TradeMessage implements Serializable
private String accountID;
private String offererPubKey;
private String preparedOffererDepositTxAsHex;
private String payoutTxID;
private String payoutTxAsHex;
public TradeMessage(TradeMessageType type, String offerUID)
{
@ -244,19 +246,19 @@ public class TradeMessage implements Serializable
return takerPaybackAmount;
}
public String getPayoutTxID()
{
return payoutTxID;
}
public void setPayoutTxID(String payoutTxID)
{
this.payoutTxID = payoutTxID;
}
public String getDepositTxAsHex()
{
return depositTxAsHex;
}
public void setPayoutTxAsHex(String payoutTxAsHex)
{
this.payoutTxAsHex = payoutTxAsHex;
}
public String getPayoutTxAsHex()
{
return payoutTxAsHex;
}
}

View File

@ -2,16 +2,26 @@ package io.bitsquare.trade;
import com.google.bitcoin.core.Transaction;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import java.io.Serializable;
import java.math.BigInteger;
public class Trade implements Serializable
{
public static enum State
{
NONE,
ACCEPTED,
COMPLETED
}
private static final long serialVersionUID = -8275323072940974077L;
transient private final SimpleBooleanProperty depositTxChangedProperty = new SimpleBooleanProperty();
transient private final SimpleBooleanProperty payoutTxChangedProperty = new SimpleBooleanProperty();
transient private final SimpleBooleanProperty contractChangedProperty = new SimpleBooleanProperty();
transient private final SimpleStringProperty stateChangedProperty = new SimpleStringProperty();
private Offer offer;
private String takeOfferFeeTxID;
@ -20,6 +30,8 @@ public class Trade implements Serializable
private String contractAsJson;
private String takerSignature;
private Transaction depositTransaction;
private Transaction payoutTransaction;
private State state = State.NONE;
public Trade(Offer offer)
{
@ -63,6 +75,19 @@ public class Trade implements Serializable
depositTxChangedProperty.set(!depositTxChangedProperty.get());
}
public void setState(State state)
{
this.state = state;
stateChangedProperty.set(state.toString());
}
public void setPayoutTransaction(Transaction payoutTransaction)
{
this.payoutTransaction = payoutTransaction;
payoutTxChangedProperty.set(!payoutTxChangedProperty.get());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
@ -108,6 +133,17 @@ public class Trade implements Serializable
return depositTransaction;
}
public Transaction getPayoutTransaction()
{
return payoutTransaction;
}
public State getState()
{
return state;
}
public SimpleBooleanProperty getDepositTxChangedProperty()
{
return depositTxChangedProperty;
@ -118,10 +154,26 @@ public class Trade implements Serializable
return contractChangedProperty;
}
public SimpleBooleanProperty getPayoutTxChangedProperty()
{
return payoutTxChangedProperty;
}
public SimpleStringProperty getStateChangedProperty()
{
return stateChangedProperty;
}
public BigInteger getCollateralAmount()
{
return getTradeAmount().multiply(BigInteger.valueOf(getOffer().getCollateral())).divide(BigInteger.valueOf(100));
}
///////////////////////////////////////////////////////////////////////////////////////////
// toString
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public String toString()
{
@ -132,8 +184,8 @@ public class Trade implements Serializable
", contract=" + contract +
", contractAsJson='" + contractAsJson + '\'' +
", takerSignature='" + takerSignature + '\'' +
", depositTransaction=" + depositTransaction +
", state=" + state +
'}';
}
}

View File

@ -3,6 +3,7 @@ package io.bitsquare.trade;
import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.TransactionConfidence;
import com.google.bitcoin.core.Utils;
import com.google.common.util.concurrent.FutureCallback;
import com.google.inject.Inject;
import io.bitsquare.btc.BlockChainFacade;
@ -184,8 +185,11 @@ public class Trading
}
@Override
public void onPayoutTxPublished(String payoutTxID)
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 onPayoutTxPublished");
}

View File

@ -42,7 +42,7 @@ public class OffererPaymentProtocol
private User user;
private PeerAddress peerAddress;
private boolean isTakeOfferRequested;
private int numberOfSteps = 15;//TODO
private int numberOfSteps = 10;//TODO
private int currentStep = 0;
private String preparedOffererDepositTxAsHex;
private Transaction depositTransaction;
@ -214,7 +214,7 @@ public class OffererPaymentProtocol
log.debug("2.5 createDepositTx");
BigInteger offererInputAmount = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
BigInteger offererInputAmount = trade.getCollateralAmount();
String offererPubKey = walletFacade.getPubKeyAsHex();
String takerPubKey = requestTradeMessage.getTakerMultiSigPubKey();
String arbitratorPubKey = offer.getArbitrator().getPubKey();
@ -546,7 +546,7 @@ public class OffererPaymentProtocol
try
{
BigInteger collateral = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
BigInteger collateral = trade.getCollateralAmount();
BigInteger offererPaybackAmount = trade.getTradeAmount().add(collateral);
BigInteger takerPaybackAmount = collateral;
@ -604,7 +604,7 @@ public class OffererPaymentProtocol
log.debug("3.14 onPayoutTxPublished");
log.debug("3.14 TRADE COMPLETE!!!!!!!!!!!");
offererPaymentProtocolListener.onPayoutTxPublished(tradeMessage.getPayoutTxID());
offererPaymentProtocolListener.onPayoutTxPublished(tradeMessage.getPayoutTxAsHex());
}

View File

@ -44,7 +44,7 @@ public class TakerPaymentProtocol
private CryptoFacade cryptoFacade;
private User user;
private PeerAddress peerAddress;
private int numberOfSteps = 15;//TODO
private int numberOfSteps = 10;//TODO
private int currentStep = 0;
@ -362,7 +362,7 @@ public class TakerPaymentProtocol
{
log.debug("2.10 payDeposit");
BigInteger collateralAmount = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
BigInteger collateralAmount = trade.getCollateralAmount();
BigInteger takerInputAmount = trade.getTradeAmount().add(collateralAmount);
BigInteger msOutputAmount = trade.getTradeAmount().add(collateralAmount).add(collateralAmount);
@ -513,7 +513,7 @@ public class TakerPaymentProtocol
log.debug("3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction.toString());
takerPaymentProtocolListener.onTradeCompleted(transaction.getHashAsString());
sendPayoutTxToOfferer(transaction.getHashAsString());
sendPayoutTxToOfferer(Utils.bytesToHexString(transaction.bitcoinSerialize()));
}
@Override
@ -554,7 +554,7 @@ public class TakerPaymentProtocol
// Step 3.13 Send payout txID to offerer
///////////////////////////////////////////////////////////////////////////////////////////
public void sendPayoutTxToOfferer(String txId)
public void sendPayoutTxToOfferer(String payoutTxAsHex)
{
log.debug("3.13 sendPayoutTxToOfferer ");
TradeMessageListener listener = new TradeMessageListener()
@ -576,8 +576,7 @@ public class TakerPaymentProtocol
};
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.PAYOUT_TX_PUBLISHED, trade.getUid());
tradeMessage.setPayoutTxID(txId);
tradeMessage.setPayoutTxAsHex(payoutTxAsHex);
log.debug("3.13 sendTradeMessage PAYOUT_TX_PUBLISHED");
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
}

View File

@ -15,22 +15,23 @@
<logger name="io.bitsquare" level="TRACE"/>
<logger name="com.google.bitcoin" level="TRACE"/>
<logger name="com.google.bitcoin" level="INFO"/>
<logger name="net.tomp2p" level="WARN"/>
<!--
-->
-->
<logger name="com.google.bitcoin.core.Wallet" level="DEBUG"/>
<logger name="com.google.bitcoin.core.MemoryPool" level="INFO" additivity="false"/>
<logger name="com.google.bitcoin.net.discovery.DnsDiscovery" level="INFO" additivity="false"/>
<logger name="com.google.bitcoin.core.DownloadListener" level="WARN" additivity="false"/>
<logger name="com.google.bitcoin.core.TransactionOutput" level="INFO" additivity="false"/>
<logger name="com.google.bitcoin.core.TransactionOutput" level="WARN" additivity="false"/>
<logger name="com.google.bitcoin.core.BitcoinSerializer" level="WARN" additivity="false"/>
<logger name="com.google.bitcoin.core.Peer" level="ERROR" additivity="false"/>
<logger name="com.google.bitcoin.core.PeerGroup" level="ERROR" additivity="false"/>
<logger name="com.google.bitcoin.core.PeerSocketHandler" level="OFF" additivity="false"/>
<logger name="com.google.bitcoin.net.NioClientManager" level="ERROR" additivity="false"/>
<logger name="com.google.bitcoin.net.ConnectionHandler" level="ERROR" additivity="false"/>
<logger name="com.google.bitcoin.net.discovery.DnsDiscovery" level="OFF" additivity="false"/>
<logger name="com.google.bitcoin.core.MemoryPool" level="OFF" additivity="false"/>
<logger name="com.google.bitcoin.core.Peer" level="WARN" additivity="false"/>
<logger name="com.google.bitcoin.core.PeerGroup" level="WARN" additivity="false"/>
<logger name="com.google.bitcoin.core.PeerSocketHandler" level="WARN" additivity="false"/>
<logger name="com.google.bitcoin.net.NioClientManager" level="WARN" additivity="false"/>
<logger name="com.google.bitcoin.net.ConnectionHandler" level="WARN" additivity="false"/>
</configuration>