/* * * Copyright 2014 http://Bither.net * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * / */ package net.bither.viewsystem.froms; import net.bither.Bither; import net.bither.BitherUI; import net.bither.bitherj.core.Address; import net.bither.bitherj.core.AddressManager; import net.bither.bitherj.core.Tx; import net.bither.bitherj.qrcode.QRCodeTxTransport; import net.bither.bitherj.utils.GenericUtils; import net.bither.bitherj.utils.TransactionsUtil; import net.bither.bitherj.utils.UnitUtil; import net.bither.bitherj.utils.Utils; import net.bither.fonts.AwesomeDecorator; import net.bither.fonts.AwesomeIcon; import net.bither.languages.MessageKey; import net.bither.qrcode.GenerateUnsignedTxPanel; import net.bither.qrcode.IReadQRCode; import net.bither.qrcode.IScanQRCode; import net.bither.qrcode.SelectQRCodePanel; import net.bither.runnable.CommitTransactionThread; import net.bither.runnable.CompleteTransactionRunnable; import net.bither.runnable.RunnableListener; import net.bither.utils.InputParser; import net.bither.utils.LocaliserUtils; import net.bither.viewsystem.TextBoxes; import net.bither.viewsystem.action.PasteAddressAction; import net.bither.viewsystem.base.Buttons; import net.bither.viewsystem.base.Labels; import net.bither.viewsystem.base.Panels; import net.bither.viewsystem.dialogs.MessageDialog; import net.miginfocom.swing.MigLayout; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.event.ActionEvent; public class UnSignTxPanel extends WizardPanel implements IScanQRCode, SelectAddressPanel.SelectAddressListener { private JTextField tfAddress; private JTextField tfAmt; private String bitcoinAddress; private Tx tx; private boolean needConfirm = true; private String changeAddress = ""; private String doateAddress; public UnSignTxPanel() { this(null); } public UnSignTxPanel(String doateAddress) { super(MessageKey.UNSIGNED, AwesomeIcon.FA_BANK); this.doateAddress = doateAddress; setOkAction(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { onOK(); } }); } @Override public void initialiseContent(JPanel panel) { panel.setLayout(new MigLayout( Panels.migXYLayout(), "[]", // Column constraints "[][][][]" // Row constraints )); JLabel label = Labels.newValueLabel(LocaliserUtils.getString("address_balance") + " : " + Utils.bitcoinValueToPlainString(Bither.getActionAddress().getBalance())); panel.add(label, "align center,wrap"); panel.add(newEnterAddressPanel(), "push,wrap"); panel.add(newAmountPanel(), "push,wrap"); if (!Utils.isEmpty(this.doateAddress)) { tfAddress.setText(this.doateAddress); } validateValues(); } public JPanel newAmountPanel() { JPanel panel = Panels.newPanel(new MigLayout( Panels.migXLayout(), "[][][][]", // Columns "[]" // Rows )); //panel.add(Labels.newAmount(), "span 4,grow,push,wrap"); JLabel label = Labels.newBitcoinSymbol(); label.setText(""); AwesomeDecorator.applyIcon(AwesomeIcon.FA_BTC, label, true, BitherUI.NORMAL_ICON_SIZE); tfAmt = TextBoxes.newAmount(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { updateUI(); } @Override public void removeUpdate(DocumentEvent e) { updateUI(); } @Override public void changedUpdate(DocumentEvent e) { updateUI(); } private void updateUI() { validateValues(); } }); panel.add(label, "shrink"); panel.add(tfAmt, "grow,push,wrap"); return panel; } public JPanel newEnterAddressPanel() { JPanel panel = Panels.newPanel( new MigLayout( Panels.migXLayout(), "[][][][]", // Columns "[]" // Rows )); tfAddress = TextBoxes.newEnterAddress(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { updateUI(); } @Override public void removeUpdate(DocumentEvent e) { updateUI(); } @Override public void changedUpdate(DocumentEvent e) { updateUI(); } private void updateUI() { validateValues(); } }); panel.add(Labels.newBitcoinAddress()); panel.add(tfAddress, "growx," + BitherUI.COMBO_BOX_WIDTH_MIG + ",push"); panel.add(Buttons.newPasteButton(new PasteAddressAction(tfAddress)), "shrink"); panel.add(getQRCodeButton(), "shrink"); panel.add(Buttons.newOptionsButton(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { String defaultAddress = changeAddress; if (Utils.isEmpty(defaultAddress)) { defaultAddress = Bither.getActionAddress().getAddress(); } SelectAddressPanel selectAddressPanel = new SelectAddressPanel(UnSignTxPanel.this, AddressManager.getInstance().getAllAddresses(), defaultAddress); selectAddressPanel.updateTitle(LocaliserUtils.getString("select_change_address_option_name")); selectAddressPanel.showPanel(); } }), "shrink"); return panel; } private JButton getQRCodeButton() { JButton button = Buttons.newFromCameraIconButton(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { onQRcode(); } }); return button; } private void onQRcode() { SelectQRCodePanel qrCodePanel = new SelectQRCodePanel(new IScanQRCode() { public void handleResult(String result, final IReadQRCode readQRCode) { new InputParser.StringInputParser(result) { @Override protected void bitcoinRequest(final String address, final String addressLabel, final long amount, final String bluetoothMac) { tfAddress.setText(address); if (amount > 0) { tfAmt.setText(UnitUtil.formatValue(amount, UnitUtil.BitcoinUnit.BTC)); } tfAmt.requestFocus(); validateValues(); } @Override protected void error(final String messageResId, final Object... messageArgs) { readQRCode.reTry(LocaliserUtils.getString("scan_watch_only_address_error")); } }.parse(); } }); qrCodePanel.showPanel(); } private void validateValues() { boolean isValidAmounts = false; String amtString = tfAmt.getText().trim(); long btc = 0; if (!Utils.isEmpty(amtString)) { btc = GenericUtils.toNanoCoins(amtString, 0).longValue(); } if (btc > 0) { isValidAmounts = true; } else { } boolean isValidAddress = Utils.validBicoinAddress(tfAddress.getText().trim()); setOkEnabled(isValidAddress && isValidAmounts); } private void onOK() { bitcoinAddress = tfAddress.getText().trim(); if (Utils.validBicoinAddress(bitcoinAddress)) { if (Utils.compareString(bitcoinAddress, changeAddress)) { new MessageDialog(LocaliserUtils.getString("select_change_address_change_to_same_warn")).showMsg(); return; } String amtString = tfAmt.getText().trim(); long btc = GenericUtils.toNanoCoins(amtString, 0).longValue(); try { CompleteTransactionRunnable completeTransactionRunnable = new CompleteTransactionRunnable( Bither.getActionAddress(), btc, bitcoinAddress, changeAddress, null); completeTransactionRunnable.setRunnableListener(completeTransactionListener); new Thread(completeTransactionRunnable).start(); } catch (Exception e) { e.printStackTrace(); } } } SendBitcoinConfirmPanel.SendConfirmListener sendConfirmListener = new SendBitcoinConfirmPanel.SendConfirmListener() { @Override public void onConfirm(Tx request) { String qrCodeString = QRCodeTxTransport.getPresignTxString(request, changeAddress, LocaliserUtils.getString("address_cannot_be_parsed"), QRCodeTxTransport.NO_HDM_INDEX); GenerateUnsignedTxPanel generateUnsignedTxPanel = new GenerateUnsignedTxPanel(UnSignTxPanel.this, qrCodeString); generateUnsignedTxPanel.showPanel(); } @Override public void onCancel() { } }; RunnableListener completeTransactionListener = new RunnableListener() { @Override public void prepare() { } @Override public void success(Object obj) { if (obj != null && obj instanceof Tx) { tx = (Tx) obj; if (needConfirm) { SendBitcoinConfirmPanel confirmPanel = new SendBitcoinConfirmPanel (sendConfirmListener, bitcoinAddress, changeAddress, tx); confirmPanel.showPanel(); } else { sendConfirmListener.onConfirm(tx); } } else { new MessageDialog(LocaliserUtils.getString("password_wrong")).showMsg(); } } @Override public void error(int errorCode, String errorMsg) { new MessageDialog(errorMsg).showMsg(); } }; @Override public void handleResult(String result, IReadQRCode readQRCode) { boolean success; try { success = TransactionsUtil.signTransaction(tx, result); } catch (Exception e) { success = false; e.printStackTrace(); } if (success) { readQRCode.close(); sendTx(tx); } else { readQRCode.reTry(" qr code error"); } } private void sendTx(Tx tx) { try { CommitTransactionThread commitTransactionThread = new CommitTransactionThread(Bither.getActionAddress(), tx , false, commitTransactionListener); commitTransactionThread.start(); } catch (Exception e) { e.printStackTrace(); } } CommitTransactionThread.CommitTransactionListener commitTransactionListener = new CommitTransactionThread.CommitTransactionListener() { @Override public void onCommitTransactionSuccess(Tx tx) { Panels.hideLightBoxIfPresent(); if (Utils.isEmpty(doateAddress)) { new MessageDialog(LocaliserUtils.getString("send_success")).showMsg(); } else { new MessageDialog(LocaliserUtils.getString("donate_thanks")).showMsg(); } } @Override public void onCommitTransactionFailed() { new MessageDialog(LocaliserUtils.getString("send_failed")).showMsg(); } }; @Override public void selectAddress(Address address) { changeAddress = address.getAddress(); } }