/**
* Copyright 2012 multibit.org
*
* Licensed under the MIT license (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://opensource.org/licenses/mit-license.php
*
* 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 org.multibit.viewsystem.swing.action;
import com.google.bitcoin.core.*;
import com.google.bitcoin.core.Wallet.SendRequest;
import com.google.bitcoin.crypto.KeyCrypterException;
import org.multibit.controller.bitcoin.BitcoinController;
import org.multibit.message.Message;
import org.multibit.message.MessageManager;
import org.multibit.model.core.CoreModel;
import org.multibit.utils.ImageLoader;
import org.multibit.viewsystem.dataproviders.BitcoinFormDataProvider;
import org.multibit.viewsystem.swing.MultiBitFrame;
import org.multibit.viewsystem.swing.view.components.FeeSlider;
import org.multibit.viewsystem.swing.view.dialogs.SendBitcoinConfirmDialog;
import org.multibit.viewsystem.swing.view.dialogs.ValidationErrorDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.math.BigInteger;
/**
* This {@link Action} shows the send bitcoin confirm dialog or validation dialog on an attempted spend.
*/
public class SendBitcoinConfirmAction extends MultiBitSubmitAction {
private static final long serialVersionUID = 1913592460523457765L;
private static final Logger log = LoggerFactory.getLogger(SendBitcoinConfirmAction.class);
private MultiBitFrame mainFrame;
private BitcoinFormDataProvider dataProvider;
private BitcoinController bitcoinController;
/**
* Creates a new {@link SendBitcoinConfirmAction}.
*/
public SendBitcoinConfirmAction(BitcoinController bitcoinController, MultiBitFrame mainFrame, BitcoinFormDataProvider dataProvider) {
super(bitcoinController, "sendBitcoinConfirmAction.text", "sendBitcoinConfirmAction.tooltip", "sendBitcoinConfirmAction.mnemonicKey", ImageLoader.createImageIcon(ImageLoader.SEND_BITCOIN_ICON_FILE));
this.mainFrame = mainFrame;
this.dataProvider = dataProvider;
this.bitcoinController = bitcoinController;
}
/**
* Complete the transaction to work out the fee) and then show the send bitcoin confirm dialog.
*/
@Override
public void actionPerformed(ActionEvent e) {
if (abort()) {
return;
}
SendBitcoinConfirmDialog sendBitcoinConfirmDialog = null;
ValidationErrorDialog validationErrorDialog = null;
try {
String sendAddress = dataProvider.getAddress();
String sendAmount = dataProvider.getAmount();
Validator validator = new Validator(super.bitcoinController);
if (validator.validate(sendAddress, sendAmount)) {
// The address and amount are valid.
// Create a SendRequest.
Address sendAddressObject;
sendAddressObject = new Address(bitcoinController.getModel().getNetworkParameters(), sendAddress);
SendRequest sendRequest = SendRequest.to(sendAddressObject, Utils.toNanoCoins(sendAmount));
sendRequest.ensureMinRequiredFee = true;
sendRequest.fee = BigInteger.ZERO;
// Work out fee per KB
String unparsedFeePerKB = controller.getModel().getUserPreference(CoreModel.FEE_PER_KB);
// Ensure the initialFeeValue is in range of the slider
sendRequest.feePerKb = BigInteger.valueOf(FeeSlider.parseAndNormaliseFeePerKB(unparsedFeePerKB));
// Note - Request is populated with the AES key in the SendBitcoinNowAction after the user has entered it on the SendBitcoinConfirm form.
// Complete it (which works out the fee) but do not sign it yet.
log.debug("Just about to complete the tx (and calculate the fee)...");
boolean completedOk;
try {
bitcoinController.getModel().getActiveWallet().completeTx(sendRequest, false);
completedOk = true;
log.debug("The fee after completing the transaction was " + sendRequest.fee);
} catch (InsufficientMoneyException ime) {
completedOk = false;
}
if (completedOk) {
// There is enough money.
sendBitcoinConfirmDialog = new SendBitcoinConfirmDialog(super.bitcoinController, mainFrame, sendRequest);
sendBitcoinConfirmDialog.setVisible(true);
} else {
// There is not enough money.
// TODO setup validation parameters accordingly so that it displays ok.
validationErrorDialog = new ValidationErrorDialog(super.bitcoinController, mainFrame, sendRequest, true);
validationErrorDialog.setVisible(true);
}
} else {
validationErrorDialog = new ValidationErrorDialog(super.bitcoinController, mainFrame, null, false);
validationErrorDialog.setVisible(true);
}
} catch (WrongNetworkException e1) {
logMessage(e1);
} catch (AddressFormatException e1) {
logMessage(e1);
} catch (KeyCrypterException e1) {
logMessage(e1);
} catch (Exception e1) {
logMessage(e1);
}
}
private void logMessage(Exception e) {
e.printStackTrace();
String errorMessage = controller.getLocaliser().getString("sendBitcoinNowAction.bitcoinSendFailed");
String detailMessage = controller.getLocaliser().getString("deleteWalletConfirmDialog.walletDeleteError2", new String[]{e.getClass().getCanonicalName() + " " + e.getMessage()});
MessageManager.INSTANCE.addMessage(new Message(errorMessage + " " + detailMessage));
}
}