add listeners to setupController

This commit is contained in:
Manfred Karrer 2014-04-28 02:36:43 +02:00
parent 38199b9b5f
commit 6509441e8c
7 changed files with 240 additions and 98 deletions

View File

@ -15,6 +15,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -26,8 +27,9 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
private static final Logger log = LoggerFactory.getLogger(AccountRegistrationWallet.class);
private NetworkParameters networkParameters;
private List<WalletFacade.WalletListener> walletListeners = new ArrayList<>();
public AccountRegistrationWallet(NetworkParameters networkParameters, BlockChain chain, PeerGroup peerGroup)
AccountRegistrationWallet(NetworkParameters networkParameters, BlockChain chain, PeerGroup peerGroup)
{
super(networkParameters);
@ -61,17 +63,33 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
autosaveToFile(walletFile, 1, TimeUnit.SECONDS, null);
}
public Address getAddress()
Address getAddress()
{
return getKey().toAddress(networkParameters);
}
public ECKey getKey()
ECKey getKey()
{
return getKeys().get(0);
}
public void saveToBlockchain(byte[] dataToEmbed) throws InsufficientMoneyException
void addWalletListener(WalletFacade.WalletListener listener)
{
if (walletListeners.size() == 0)
addEventListener(this);
walletListeners.add(listener);
}
void removeWalletListener(WalletFacade.WalletListener listener)
{
walletListeners.remove(listener);
if (walletListeners.size() == 0)
removeEventListener(this);
}
void saveToBlockchain(byte[] dataToEmbed) throws InsufficientMoneyException
{
Script script = new ScriptBuilder()
.op(OP_RETURN)
@ -116,47 +134,25 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
});
}
public int getConfirmations()
{
// TODO just a quick impl. need to be checked if it works for all cases...
Set<Transaction> transactions = getTransactions(true);
if (transactions != null && transactions.size() == 1)
{
Transaction transaction = transactions.iterator().next();
final int lastBlockSeenHeight = getLastBlockSeenHeight();
int appearedAtChainHeight = 0;
if (transaction.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
appearedAtChainHeight = transaction.getConfidence().getAppearedAtChainHeight();
final int numberOfBlocksEmbedded = lastBlockSeenHeight - appearedAtChainHeight + 1;
if (numberOfBlocksEmbedded > 0)
return numberOfBlocksEmbedded;
else
return 0;
}
return 0;
}
public int getNumberOfPeersSeenTx()
{
// TODO just a quick impl. need to be checked if it works for all cases...
Set<Transaction> transactions = getTransactions(true);
if (transactions != null && transactions.size() == 1)
{
Transaction transaction = transactions.iterator().next();
return (transaction == null || transaction.getConfidence() == null) ? 0 : transaction.getConfidence().numBroadcastPeers();
}
return 0;
}
//TODO those handlers are not called yet...
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
for (WalletFacade.WalletListener walletListener : walletListeners)
walletListener.onCoinsReceived(newBalance);
log.info("onCoinsReceived");
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
for (WalletFacade.WalletListener walletListener : walletListeners)
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), tx.getConfidence().getDepthInBlocks());
log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
@ -169,12 +165,6 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
log.info("onReorganize");
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
log.info("onTransactionConfidenceChanged");
}
@Override
public void onWalletChanged(Wallet wallet)
{
@ -193,5 +183,26 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
log.info("onScriptsAdded");
}
int getConfirmationNumBroadcastPeers()
{
Transaction transaction = getTransaction();
return (transaction == null || transaction.getConfidence() == null) ? 0 : transaction.getConfidence().numBroadcastPeers();
}
int getConfirmationDepthInBlocks()
{
Transaction transaction = getTransaction();
return (transaction == null || transaction.getConfidence() == null) ? 0 : transaction.getConfidence().getDepthInBlocks();
}
//TODO only 1 tx supported yet...
private Transaction getTransaction()
{
Set<Transaction> transactions = getTransactions(true);
if (transactions != null && transactions.size() == 1)
{
return transactions.iterator().next();
}
return null;
}
}

View File

@ -1,10 +0,0 @@
package io.bitsquare.btc;
import java.util.Date;
public interface DownloadListener
{
void progress(double percent, int blocksSoFar, Date date);
void doneDownload();
}

View File

@ -4,6 +4,7 @@ import com.google.bitcoin.core.*;
import com.google.bitcoin.kits.WalletAppKit;
import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.params.RegTestParams;
import com.google.bitcoin.script.Script;
import com.google.bitcoin.utils.Threading;
import com.google.inject.Inject;
import io.bitsquare.crypto.CryptoFacade;
@ -22,7 +23,7 @@ import java.util.UUID;
* Code from BitcoinJ must not be used outside that facade.
* That way a change of the library will only affect that class.
*/
public class WalletFacade
public class WalletFacade implements WalletEventListener
{
public static final String MAIN_NET = "MAIN_NET";
public static final String TEST_NET = "TEST_NET";
@ -38,6 +39,7 @@ public class WalletFacade
private AccountRegistrationWallet accountRegistrationWallet = null;
private List<DownloadListener> downloadListeners = new ArrayList<>();
private List<WalletListener> walletListeners = new ArrayList<>();
@Inject
public WalletFacade(NetworkParameters networkParameters, WalletAppKit walletAppKit, CryptoFacade cryptoFacade, BlockChainFacade blockChainFacade)
@ -80,6 +82,8 @@ public class WalletFacade
walletAppKit.wallet().allowSpendingUnconfirmedTransactions();
walletAppKit.peerGroup().setMaxConnections(11);
walletAppKit.wallet().addEventListener(this);
log.info(walletAppKit.wallet().toString());
}
@ -89,16 +93,37 @@ public class WalletFacade
walletAppKit.awaitTerminated();
}
public void addDownloadListener(DownloadListener downloadListener)
public void addDownloadListener(DownloadListener listener)
{
downloadListeners.add(downloadListener);
downloadListeners.add(listener);
}
public void removeDownloadListener(DownloadListener downloadListener)
public void removeDownloadListener(DownloadListener listener)
{
downloadListeners.remove(downloadListener);
downloadListeners.remove(listener);
}
public void addWalletListener(WalletListener listener)
{
walletListeners.add(listener);
}
public void removeWalletListener(WalletListener listener)
{
walletListeners.remove(listener);
}
public void addRegistrationWalletListener(WalletListener listener)
{
getAccountRegistrationWallet().addWalletListener(listener);
}
public void removeRegistrationWalletListener(WalletListener listener)
{
getAccountRegistrationWallet().removeWalletListener(listener);
}
//MOCK
public KeyPair createNewAddress()
{
@ -132,16 +157,6 @@ public class WalletFacade
return getAccountRegistrationWallet().getBalance(Wallet.BalanceType.ESTIMATED);
}
public int getAccountRegistrationConfirmations()
{
return getAccountRegistrationWallet().getConfirmations();
}
public int getAccountRegistrationNumberOfPeersSeenTx()
{
return getAccountRegistrationWallet().getNumberOfPeersSeenTx();
}
public void sendRegistrationTx(String stringifiedBankAccounts) throws InsufficientMoneyException
{
getAccountRegistrationWallet().saveToBlockchain(cryptoFacade.getEmbeddedAccountRegistrationData(getAccountRegistrationWallet().getKey(), stringifiedBankAccounts));
@ -154,6 +169,66 @@ public class WalletFacade
&& blockChainFacade.verifyAddressInBlockChain(hashAsHexStringToVerify, address);
}
public int getRegistrationConfirmationNumBroadcastPeers()
{
return getAccountRegistrationWallet().getConfirmationNumBroadcastPeers();
}
public int getRegistrationConfirmationDepthInBlocks()
{
return getAccountRegistrationWallet().getConfirmationDepthInBlocks();
}
// WalletEventListener
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
for (WalletListener walletListener : walletListeners)
walletListener.onCoinsReceived(newBalance);
log.info("onCoinsReceived");
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
for (WalletListener walletListener : walletListeners)
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), tx.getConfidence().getDepthInBlocks());
log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
log.info("onCoinsSent");
}
@Override
public void onReorganize(Wallet wallet)
{
log.info("onReorganize");
}
@Override
public void onWalletChanged(Wallet wallet)
{
log.info("onWalletChanged");
}
@Override
public void onKeysAdded(Wallet wallet, List<ECKey> keys)
{
log.info("onKeysAdded");
}
@Override
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
{
log.info("onScriptsAdded");
}
private AccountRegistrationWallet getAccountRegistrationWallet()
{
if (accountRegistrationWallet == null)
@ -182,4 +257,18 @@ public class WalletFacade
downloadListener.doneDownload();
}
}
public static interface DownloadListener
{
void progress(double percent, int blocksSoFar, Date date);
void doneDownload();
}
public static interface WalletListener
{
void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks);
void onCoinsReceived(BigInteger newBalance);
}
}

View File

@ -1,7 +1,6 @@
package io.bitsquare.gui;
import com.google.inject.Inject;
import io.bitsquare.btc.DownloadListener;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.components.NetworkSyncPane;
@ -35,7 +34,7 @@ import java.util.Currency;
import java.util.Date;
import java.util.ResourceBundle;
public class MainController implements Initializable, NavigationController, DownloadListener
public class MainController implements Initializable, NavigationController, WalletFacade.DownloadListener
{
private static final Logger log = LoggerFactory.getLogger(MainController.class);

View File

@ -23,6 +23,7 @@ import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
@ -31,10 +32,11 @@ import javafx.scene.layout.GridPane;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.net.URL;
import java.util.*;
public class SetupController implements Initializable, ChildController
public class SetupController implements Initializable, ChildController, WalletFacade.WalletListener
{
private static final Logger log = LoggerFactory.getLogger(SetupController.class);
@ -45,8 +47,11 @@ public class SetupController implements Initializable, ChildController
private Storage storage;
private List<ProcessStepItem> processStepItems = new ArrayList();
private int depthInBlocks = 0;
private NavigationController navigationController;
private ImageView confirmIconImageView;
private TextField balanceLabel, confirmationsLabel;
@FXML
private AnchorPane rootContainer;
@ -59,6 +64,7 @@ public class SetupController implements Initializable, ChildController
@FXML
private Button nextButton, skipButton;
@Inject
public SetupController(User user, WalletFacade walletFacade, CryptoFacade cryptoFacade, Settings settings, Storage storage)
{
@ -76,6 +82,8 @@ public class SetupController implements Initializable, ChildController
processStepItems.add(new ProcessStepItem("Complete", Colors.BLUE));
processStepBar.setProcessStepItems(processStepItems);
walletFacade.addRegistrationWalletListener(this);
buildStep0();
}
@ -91,8 +99,29 @@ public class SetupController implements Initializable, ChildController
this.navigationController = navigationController;
}
@Override
public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks)
{
this.depthInBlocks = depthInBlocks;
updateCreateAccountButton();
confirmIconImageView.setImage(getConfirmIconImage(numBroadcastPeers, depthInBlocks));
confirmationsLabel.setText(getConfirmationsText(numBroadcastPeers, depthInBlocks));
log.info("onConfidenceChanged " + numBroadcastPeers + " / " + depthInBlocks);
}
@Override
public void onCoinsReceived(BigInteger newBalance)
{
updateCreateAccountButton();
balanceLabel.setText(Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true));
log.info("onCoinsReceived " + newBalance);
}
private void close()
{
walletFacade.removeRegistrationWalletListener(this);
navigationController.navigateToView(NavigationController.HOME, "");
}
@ -108,13 +137,12 @@ public class SetupController implements Initializable, ChildController
return result;
}
private ImageView getConfirmIcon()
private Image getConfirmIconImage(int numBroadcastPeers, int depthInBlocks)
{
int confirmations = walletFacade.getAccountRegistrationConfirmations();
if (confirmations > 0)
return Icons.getIconImageView(Icons.getIconIDForConfirmations(confirmations));
if (depthInBlocks > 0)
return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks));
else
return Icons.getIconImageView(Icons.getIconIDForPeersSeenTx(walletFacade.getAccountRegistrationNumberOfPeersSeenTx()));
return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers));
}
@ -122,27 +150,43 @@ public class SetupController implements Initializable, ChildController
// GUI BUILDER
///////////////////////////////////////////////////////////////////////////////////
private String getConfirmationsText(int registrationConfirmationNumBroadcastPeers, int registrationConfirmationDepthInBlocks)
{
return registrationConfirmationDepthInBlocks + " confirmation(s) / " + "Seen by " + registrationConfirmationNumBroadcastPeers + " peer(s)";
}
private void buildStep0()
{
infoLabel.setText("You need to pay 0.01 BTC to the registration address.\n" +
infoLabel.setText("You need to pay 0.01 BTC to the registration address.\n\n" +
"That payment will be used to create a unique account connected with your bank account number.\n" +
"The privacy of your bank account number will be protected and only revealed to your trading partners.\n" +
"The payment will be spent to miners and is needed to store data into the blockchain.\n" +
"Your trading account will be the source for your reputation in the trading platform.");
"Your trading account will be the source for your reputation in the trading platform.\n\n" +
"You need at least 1 confirmation for doing the registration payment.");
int row = -1;
TextField addressLabel = FormBuilder.addInputField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++row);
int gridRow = -1;
TextField addressLabel = FormBuilder.addInputField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow);
addressLabel.setEditable(false);
Label copyIcon = new Label("");
formGridPane.add(copyIcon, 2, row);
formGridPane.add(copyIcon, 2, gridRow);
copyIcon.setId("copy-icon");
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
Tooltip.install(copyIcon, new Tooltip("Copy address to clipboard"));
formGridPane.add(getConfirmIcon(), 3, row);
TextField balanceLabel = FormBuilder.addInputField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++row);
balanceLabel = FormBuilder.addInputField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow);
balanceLabel.setEditable(false);
confirmationsLabel = FormBuilder.addInputField(formGridPane, "Confirmations:", getConfirmationsText(walletFacade.getRegistrationConfirmationNumBroadcastPeers(), walletFacade.getRegistrationConfirmationDepthInBlocks()), ++gridRow);
confirmationsLabel.setEditable(false);
confirmIconImageView = new ImageView(getConfirmIconImage(walletFacade.getRegistrationConfirmationNumBroadcastPeers(), walletFacade.getRegistrationConfirmationDepthInBlocks()));
formGridPane.add(confirmIconImageView, 2, gridRow);
nextButton.setText("Payment done");
updateCreateAccountButton();
skipButton.setText("Register later");
// handlers
@ -170,18 +214,19 @@ public class SetupController implements Initializable, ChildController
"Only your trading partners will be able to read those data, so your privacy will be protected.");
formGridPane.getChildren().clear();
int row = -1;
ComboBox bankTransferTypes = FormBuilder.addComboBox(formGridPane, "Bank account type:", settings.getAllBankAccountTypes(), ++row);
int gridRow = -1;
ComboBox bankTransferTypes = FormBuilder.addComboBox(formGridPane, "Bank account type:", settings.getAllBankAccountTypes(), ++gridRow);
bankTransferTypes.setPromptText("Select");
//TODO dev
bankTransferTypes.getSelectionModel().select(1);
TextField accountHolderName = FormBuilder.addInputField(formGridPane, "Bank account holder name:", "Bob Brown", ++row);
TextField accountPrimaryID = FormBuilder.addInputField(formGridPane, "Bank account primary ID", "dummy IBAN", ++row);
TextField accountSecondaryID = FormBuilder.addInputField(formGridPane, "Bank account secondary ID:", "dummy BIC", ++row);
TextField accountHolderName = FormBuilder.addInputField(formGridPane, "Bank account holder name:", "Bob Brown", ++gridRow);
TextField accountPrimaryID = FormBuilder.addInputField(formGridPane, "Bank account primary ID", "dummy IBAN", ++gridRow);
TextField accountSecondaryID = FormBuilder.addInputField(formGridPane, "Bank account secondary ID:", "dummy BIC", ++gridRow);
Button addButton = new Button("Add other Bank account");
formGridPane.add(addButton, 1, ++row);
formGridPane.add(addButton, 1, ++gridRow);
nextButton.setText("Create account");
nextButton.setDisable(true);
skipButton.setText("Register later");
// handlers
@ -197,6 +242,8 @@ public class SetupController implements Initializable, ChildController
accountPrimaryID.setPromptText(bankAccountType.getPrimaryIDName());
accountSecondaryID.setText("");
accountSecondaryID.setPromptText(bankAccountType.getSecondaryIDName());
nextButton.setDisable(false);
}
}
});
@ -254,22 +301,22 @@ public class SetupController implements Initializable, ChildController
"You have saved following bank accounts with your trading account to the blockchain:");
formGridPane.getChildren().clear();
int row = -1;
int gridRow = -1;
Map<String, BankAccount> bankAccounts = user.getBankAccounts();
Iterator iterator = bankAccounts.entrySet().iterator();
int index = 0;
while (iterator.hasNext())
{
FormBuilder.addHeaderLabel(formGridPane, "Bank account " + (index + 1), ++row);
FormBuilder.addHeaderLabel(formGridPane, "Bank account " + (index + 1), ++gridRow);
Map.Entry<String, BankAccount> entry = (Map.Entry) iterator.next();
// need to get updated row from subroutine
row = buildBankAccountDetails(entry.getValue(), ++row);
FormBuilder.addVSpacer(formGridPane, ++row);
// need to get updated gridRow from subroutine
gridRow = buildBankAccountDetails(entry.getValue(), ++gridRow);
FormBuilder.addVSpacer(formGridPane, ++gridRow);
index++;
}
FormBuilder.addVSpacer(formGridPane, ++row);
FormBuilder.addInputField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++row).setMouseTransparent(true);
FormBuilder.addInputField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++row).setMouseTransparent(true);
FormBuilder.addVSpacer(formGridPane, ++gridRow);
FormBuilder.addInputField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow).setMouseTransparent(true);
FormBuilder.addInputField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow).setMouseTransparent(true);
nextButton.setText("Done");
skipButton.setOpacity(0);
@ -289,5 +336,11 @@ public class SetupController implements Initializable, ChildController
FormBuilder.addInputField(formGridPane, "Bank account secondary ID:", bankAccount.getAccountSecondaryID(), ++row).setMouseTransparent(true);
return row;
}
private void updateCreateAccountButton()
{
boolean funded = walletFacade.getAccountRegistrationBalance().compareTo(BigInteger.ZERO) > 0;
nextButton.setDisable(!funded || depthInBlocks == 0);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 B

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B