payment process payout done

This commit is contained in:
Manfred Karrer 2014-05-17 01:48:23 +02:00
parent 9af3f6aeba
commit a508f95582
28 changed files with 867 additions and 377 deletions

View File

@ -122,13 +122,13 @@ public class BitSquare extends Application
settings.getAcceptedArbitrators().clear();
settings.addAcceptedArbitrator(new Arbitrator("uid_1", "Charlie Boom", Utils.bytesToHexString(new ECKey().getPubKey()),
getMessagePubKey(), "http://www.arbit.io/Charly_Boom", 1, 10, Utils.toNanoCoins("0.01")));
getMessagePubKey(), "http://www.arbit.io/Charly_Boom", 10, 50, Utils.toNanoCoins("0.01")));
settings.addAcceptedArbitrator(new Arbitrator("uid_2", "Tom Shang", Utils.bytesToHexString(new ECKey().getPubKey()),
getMessagePubKey(), "http://www.arbit.io/Tom_Shang", 0, 1, Utils.toNanoCoins("0.001")));
getMessagePubKey(), "http://www.arbit.io/Tom_Shang", 10, 100, Utils.toNanoCoins("0.001")));
settings.addAcceptedArbitrator(new Arbitrator("uid_3", "Edward Snow", Utils.bytesToHexString(new ECKey().getPubKey()),
getMessagePubKey(), "http://www.arbit.io/Edward_Swow", 2, 5, Utils.toNanoCoins("0.05")));
getMessagePubKey(), "http://www.arbit.io/Edward_Swow", 20, 50, Utils.toNanoCoins("0.05")));
settings.addAcceptedArbitrator(new Arbitrator("uid_4", "Julian Sander", Utils.bytesToHexString(new ECKey().getPubKey()),
getMessagePubKey(), "http://www.arbit.io/Julian_Sander", 0, 20, Utils.toNanoCoins("0.1")));
getMessagePubKey(), "http://www.arbit.io/Julian_Sander", 10, 20, Utils.toNanoCoins("0.1")));
settings.setMinCollateral(1);
settings.setMaxCollateral(10);

View File

@ -23,7 +23,7 @@ public class RelayNode
{
masterPeer = new PeerMaker(ID).setPorts(port).makeAndListen();
// masterPeer = new PeerMaker(ID).setPorts(port).setBagSize(100).makeAndListen(); // setBagSize cause sync problems...
masterPeer.getBroadcastRPC().getConnectionBean().getConnectionReservation().reserve(10).awaitUninterruptibly();
masterPeer.getBroadcastRPC().getConnectionBean().getConnectionReservation().reserve(3).awaitUninterruptibly();
}
return masterPeer;
}

View File

@ -9,8 +9,6 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import io.bitsquare.BitSquare;
import io.bitsquare.util.Utilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
@ -25,23 +23,33 @@ import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
public class AccountRegistrationWallet extends Wallet implements WalletEventListener
{
private static final Logger log = LoggerFactory.getLogger(AccountRegistrationWallet.class);
// private static final Logger log = LoggerFactory.getLogger(AccountRegistrationWallet.class);
private final File walletFile;
private NetworkParameters networkParameters;
private NetworkParameters params;
private BlockChain chain;
private PeerGroup peerGroup;
private List<WalletFacade.WalletListener> walletListeners = new ArrayList<>();
AccountRegistrationWallet(NetworkParameters networkParameters, BlockChain chain, PeerGroup peerGroup)
AccountRegistrationWallet(NetworkParameters params, BlockChain chain, PeerGroup peerGroup)
{
super(networkParameters);
super(params);
this.networkParameters = networkParameters;
this.params = params;
this.chain = chain;
this.peerGroup = peerGroup;
walletFile = new File(Utilities.getRootDir() + "account_reg_" + BitSquare.ID + ".wallet");
/* try
{
final InetAddress localHost = InetAddress.getLocalHost();
PeerAddress peerAddress = new PeerAddress(localHost, params.getPort());
peerGroup.addAddress(peerAddress);
} catch (UnknownHostException e)
{
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} */
walletFile = new File(Utilities.getRootDir() + BitSquare.ID + "_account_reg" + ".wallet");
if (walletFile.exists())
{
FileInputStream walletStream = null;
@ -78,6 +86,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
}
autosaveToFile(walletFile, 1, TimeUnit.SECONDS, null);
peerGroup.setMinBroadcastConnections(1);
allowSpendingUnconfirmedTransactions();
}
@ -95,7 +104,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
Address getAddress()
{
return getKey().toAddress(networkParameters);
return getKey().toAddress(params);
}
ECKey getKey()
@ -125,8 +134,8 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
.op(OP_RETURN)
.data(dataToEmbed)
.build();
Transaction transaction = new Transaction(networkParameters);
TransactionOutput dataOutput = new TransactionOutput(networkParameters,
Transaction transaction = new Transaction(params);
TransactionOutput dataOutput = new TransactionOutput(params,
transaction,
Transaction.MIN_NONDUST_OUTPUT,
script.getProgram());
@ -144,14 +153,14 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
@Override
public void onSuccess(Transaction result)
{
log.info("sendResult onSuccess:" + result.toString());
//log.info("sendResult onSuccess:" + result.toString());
// Platform.runLater(overlayUi::done);
}
@Override
public void onFailure(Throwable t)
{
log.warn("sendResult onFailure:" + t.toString());
//log.warn("sendResult onFailure:" + t.toString());
// We died trying to empty the wallet.
// crashAlert(t);
}
@ -171,7 +180,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
for (WalletFacade.WalletListener walletListener : walletListeners)
walletListener.onCoinsReceived(newBalance);
// log.info("onCoinsReceived");
// //log.info("onCoinsReceived");
}
@Override
@ -180,37 +189,37 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
for (WalletFacade.WalletListener walletListener : walletListeners)
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfDepthInBlocks(this));
// log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
// //log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
log.info("onCoinsSent");
//log.info("onCoinsSent");
}
@Override
public void onReorganize(Wallet wallet)
{
log.info("onReorganize");
//log.info("onReorganize");
}
@Override
public void onWalletChanged(Wallet wallet)
{
// log.info("onWalletChanged");
// //log.info("onWalletChanged");
}
@Override
public void onKeysAdded(Wallet wallet, List<ECKey> keys)
{
log.info("onKeysAdded");
//log.info("onKeysAdded");
}
@Override
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
{
log.info("onScriptsAdded");
//log.info("onScriptsAdded");
}
int getConfNumBroadcastPeers()

View File

@ -1,14 +1,15 @@
package io.bitsquare.btc;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.Utils;
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; // Transaction.REFERENCE_DEFAULT_MIN_TX_FEE = BigInteger.valueOf(10000)
public static BigInteger ACCOUNT_REGISTRATION_FEE = BigInteger.valueOf(7860);// Utils.toNanoCoins("0.001");
public static BigInteger OFFER_CREATION_FEE = BigInteger.valueOf(7860); // Transaction.MIN_NONDUST_OUTPUT; // Utils.toNanoCoins("0.001");
public static BigInteger OFFER_TAKER_FEE = BigInteger.valueOf(7860);
public static BigInteger MS_TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
public static BigInteger ACCOUNT_REGISTRATION_FEE = Utils.toNanoCoins("0.01").subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
public static BigInteger OFFER_CREATION_FEE = Utils.toNanoCoins("0.001").subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
public static BigInteger OFFER_TAKER_FEE = OFFER_CREATION_FEE;
}

View File

@ -15,7 +15,6 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
import io.bitsquare.BitSquare;
import io.bitsquare.crypto.CryptoFacade;
import io.bitsquare.gui.util.Popups;
import javafx.application.Platform;
import javafx.util.Pair;
import org.slf4j.Logger;
@ -27,6 +26,8 @@ import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
/**
* That facade delivers wallet functionality from the bitcoinJ library
* Code from BitcoinJ must not be used outside that facade.
@ -51,13 +52,15 @@ public class WalletFacade implements WalletEventListener
private CryptoFacade cryptoFacade;
// that wallet is used only for the registration process
private AccountRegistrationWallet accountRegistrationWallet = null;
//private AccountRegistrationWallet accountRegistrationWallet = null;
private List<DownloadListener> downloadListeners = new ArrayList<>();
private List<WalletListener> walletListeners = new ArrayList<>();
private Wallet wallet;
private ECKey registrationKey;
private ECKey tradingKey;
///////////////////////////////////////////////////////////////////////////////////////////
@ -98,20 +101,27 @@ public class WalletFacade implements WalletEventListener
walletAppKit.setCheckpoints(getClass().getResourceAsStream("/wallet/checkpoints"));
}
walletAppKit.setAutoSave(true);
// 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", "0.1");
walletAppKit.setDownloadListener(new BlockChainDownloadListener()).setBlockingStartup(false).setUserAgent("BitSquare", "0.1");
walletAppKit.startAsync();
walletAppKit.awaitRunning();
wallet = walletAppKit.wallet();
registrationKey = wallet.getKeys().get(0);
tradingKey = new ECKey();
wallet.addKey(tradingKey);
log.info("getConnectedPeers " + walletAppKit.peerGroup().getConnectedPeers().size());
wallet.allowSpendingUnconfirmedTransactions();
walletAppKit.peerGroup().setMaxConnections(20);
// walletAppKit.peerGroup().setMaxConnections(10);
walletAppKit.peerGroup().setMinBroadcastConnections(1);
wallet.addEventListener(this);
wallet.addWatchedAddress(tradingKey.toAddress(params));
// testTradeProcessDepositTx();
// testTradeProcessPayOutTx();
@ -119,12 +129,17 @@ public class WalletFacade implements WalletEventListener
public void shutDown()
{
if (accountRegistrationWallet != null)
accountRegistrationWallet.shutDown();
/*if (accountRegistrationWallet != null)
accountRegistrationWallet.shutDown(); */
walletAppKit.stopAsync();
walletAppKit.awaitTerminated();
}
public void updateWallet()
{
}
///////////////////////////////////////////////////////////////////////////////////////////
// Listener
///////////////////////////////////////////////////////////////////////////////////////////
@ -139,7 +154,7 @@ public class WalletFacade implements WalletEventListener
downloadListeners.remove(listener);
}
public void addWalletListener(WalletListener listener)
/* public void addWalletListener(WalletListener listener)
{
walletListeners.add(listener);
}
@ -157,7 +172,7 @@ public class WalletFacade implements WalletEventListener
public void removeRegistrationWalletListener(WalletListener listener)
{
getAccountRegistrationWallet().removeWalletListener(listener);
}
} */
///////////////////////////////////////////////////////////////////////////////////////////
@ -171,10 +186,10 @@ public class WalletFacade implements WalletEventListener
public String getAddressAsString()
{
return wallet.getKeys().get(0).toAddress(params).toString();
return tradingKey.toAddress(params).toString();
}
public String payFee(BigInteger fee, FutureCallback<Transaction> callback) throws InsufficientMoneyException
public String payOfferFee(BigInteger fee, FutureCallback<Transaction> callback) throws InsufficientMoneyException
{
Transaction tx = new Transaction(params);
//TransactionOutput output = new TransactionOutput(params, tx, Transaction.MIN_NONDUST_OUTPUT, WalletUtil.getEmptyOP_RETURNScript());
@ -206,36 +221,84 @@ public class WalletFacade implements WalletEventListener
// Account registration
///////////////////////////////////////////////////////////////////////////////////////////
public Address getAccountRegistrationAddress()
{
return getAccountRegistrationWallet().getAddress();
return registrationKey.toAddress(params);
}
public String getAccountRegistrationPubKey()
/* public String getAccountRegistrationPubKey()
{
return Utils.bytesToHexString(getAccountRegistrationKey().getPubKey());
}
} */
public BigInteger getAccountRegistrationBalance()
{
return getAccountRegistrationWallet().getBalance(Wallet.BalanceType.ESTIMATED);
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
// return getAccountRegistrationWallet().getBalance(Wallet.BalanceType.ESTIMATED);
}
public void sendRegistrationTx(String stringifiedBankAccounts) throws InsufficientMoneyException
{
getAccountRegistrationWallet().saveToBlockchain(cryptoFacade.getEmbeddedAccountRegistrationData(getAccountRegistrationWallet().getKey(), stringifiedBankAccounts));
saveToBlockchain(cryptoFacade.getEmbeddedAccountRegistrationData(registrationKey, stringifiedBankAccounts));
}
public ECKey getAccountRegistrationKey()
public ECKey getRegistrationKey()
{
return getAccountRegistrationWallet().getKey();
return registrationKey;
}
void saveToBlockchain(byte[] dataToEmbed) throws InsufficientMoneyException
{
Script script = new ScriptBuilder()
.op(OP_RETURN)
.data(dataToEmbed)
.build();
Transaction transaction = new Transaction(params);
TransactionOutput dataOutput = new TransactionOutput(params,
transaction,
Transaction.MIN_NONDUST_OUTPUT,
script.getProgram());
transaction.addOutput(dataOutput);
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(transaction);
// give fee to miners yet. Later it could be spent to other traders via lottery...
sendRequest.fee = Fees.ACCOUNT_REGISTRATION_FEE;
Wallet.SendResult sendResult = null;
sendResult = wallet.sendCoins(sendRequest);
log.info("Registration transaction: " + transaction.toString());
//TODO
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>()
{
@Override
public void onSuccess(Transaction result)
{
log.info("sendResult onSuccess:" + result.toString());
// Platform.runLater(overlayUi::done);
}
@Override
public void onFailure(Throwable t)
{
log.warn("sendResult onFailure:" + t.toString());
// We died trying to empty the wallet.
// crashAlert(t);
}
});
//TODO
sendResult.tx.getConfidence().addEventListener((tx, reason) -> {
//if (reason == TransactionConfidence.Listener.ChangeReason.SEEN_PEERS)
//updateTitleForBroadcast();
});
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter
///////////////////////////////////////////////////////////////////////////////////////////
public int getRegConfNumBroadcastPeers()
/*public int getRegConfNumBroadcastPeers()
{
return getAccountRegistrationWallet().getConfNumBroadcastPeers();
}
@ -243,7 +306,7 @@ public class WalletFacade implements WalletEventListener
public int getRegConfDepthInBlocks()
{
return WalletUtil.getConfDepthInBlocks(getAccountRegistrationWallet());
}
} */
public Wallet getWallet()
{
@ -306,13 +369,13 @@ public class WalletFacade implements WalletEventListener
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
public AccountRegistrationWallet getAccountRegistrationWallet()
/* public AccountRegistrationWallet getAccountRegistrationWallet()
{
if (accountRegistrationWallet == null)
accountRegistrationWallet = new AccountRegistrationWallet(params, walletAppKit.chain(), walletAppKit.peerGroup());
return accountRegistrationWallet;
}
}*/
private Script getMultiSigScript(String offererPubKey, String takerPubKey, String arbitratorPubKey)
{
@ -416,13 +479,14 @@ public class WalletFacade implements WalletEventListener
offererSignatureS,
offererPaybackAmount,
takerPaybackAmount,
offererAddress);
offererAddress, null);
log.info(takerTx.toString()); // tx has 265 Bytes
/*
6606c366a487bff9e412d0b6c09c14916319932db5954bf5d8719f43f828a3ba: Unknown confidence level.
in [] [30450221008ebd06e53ce1ab7b599098b3117f2073b1d224baae21190ef7839b70a638207602201485ae19965f2d954398f691aa40fecb4d08d625ae96037a4fc5eecb7a4803c301] [30440220521c485045a46fbb61c634ebf456c470f9c2f7307a743e3fce10b50f7a69115d0220249ff5f9796a9fcd12984afcfd3f7d16d2f8c49ddcef245db7c7b02b909af9a601]
in [] [30450221008ebd06e53ce1ab7b599098b3117f2073b1d224baae21190ef7839b70a638207602201485ae19965f2d954398f691aa40fecb4d08d625ae96037a4fc5eecb7a4803c301]
[30440220521c485045a46fbb61c634ebf456c470f9c2f7307a743e3fce10b50f7a69115d0220249ff5f9796a9fcd12984afcfd3f7d16d2f8c49ddcef245db7c7b02b909af9a601]
outpoint:4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9:0 hash160:[exception: Script not in the standard scriptPubKey form]
out DUP HASH160 [9fc3d8e0371b6eab89a8c3c015839f9e493ccf65] EQUALVERIFY CHECKSIG 0.0289 BTC
out DUP HASH160 [e5175c1f71c28218306d4a27c8cec0269dddbbde] EQUALVERIFY CHECKSIG 0.0009 BTC
@ -439,19 +503,21 @@ public class WalletFacade implements WalletEventListener
public String getMultiSigPubKeyAsHex()
{
return Utils.bytesToHexString(wallet.getKeys().get(0).getPubKey());
return Utils.bytesToHexString(tradingKey.getPubKey());
}
// deposit 1. offerer
public Transaction offererCreatesMSTxAndAddPayment(BigInteger offererAmount, String offererPubKey, String takerPubKey, String arbitratorPubKey) throws InsufficientMoneyException
public Transaction offererCreatesMSTxAndAddPayment(BigInteger offererInputAmount, String offererPubKey, String takerPubKey, String arbitratorPubKey) throws InsufficientMoneyException
{
log.debug("offererCreatesMSTxAndAddPayment");
// use that to use the convenient api for getting the best coin selection and fee calculation
// TODO should be constructed manually
Transaction tx = new Transaction(params);
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
tx.addOutput(offererAmount, multiSigOutputScript);
tx.addOutput(offererInputAmount, multiSigOutputScript);
Wallet.SendRequest request = Wallet.SendRequest.forTx(tx);
wallet.completeTx(request);
// TODO remove sig or use SigHash.NONE
//tx.getInput(0).setScriptSig(null);
@ -460,6 +526,8 @@ public class WalletFacade implements WalletEventListener
OUT[0] MS
OUT[1] offerer change
*/
log.debug("offererCreatesMSTxAndAddPayment tx = " + tx.toString());
return tx;
}
@ -472,6 +540,7 @@ public class WalletFacade implements WalletEventListener
String tx1AsHex
) throws InsufficientMoneyException, ExecutionException, InterruptedException, AddressFormatException
{
log.debug("takerAddPaymentAndSign");
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
// use that to use the convenient api for getting the best coin selection and fee calculation
@ -485,6 +554,8 @@ public class WalletFacade implements WalletEventListener
tx.addOutput(dummyTx.getOutput(1));
tx.getOutput(0).setValue(msOutputAmount);
log.debug("tx" + tx.toString());
TransactionInput input = tx.getInput(1);
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
@ -498,6 +569,7 @@ public class WalletFacade implements WalletEventListener
else
throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
log.debug("correctlySpends?");
input.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false);
/*
@ -508,6 +580,7 @@ public class WalletFacade implements WalletEventListener
OUT[2] taker change
*/
// wallet.commitTx(tx);
return tx;
}
@ -555,10 +628,9 @@ public class WalletFacade implements WalletEventListener
log.info("offererSignAndSendTx check correctlySpends input 0");
input.getScriptSig().correctlySpends(tx, 0, scriptPubKey, false);
log.info("offererSignAndSendTx check correctlySpends input 1");
input = tx.getInput(1);
scriptPubKey = input.getConnectedOutput().getScriptPubKey();
log.info("offererSignAndSendTx check correctlySpends input 1");
input.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false);
/*
@ -571,15 +643,14 @@ public class WalletFacade implements WalletEventListener
log.info("offererSignAndSendTx broadcastTransaction verify ");
tx.verify();
log.info("offererSignAndSendTx broadcastTransaction pre ");
log.info("offererSignAndSendTx broadcastTransaction");
ListenableFuture<Transaction> broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(tx);
log.info("offererSignAndSendTx broadcastTransaction post");
FutureCallback<Transaction> localCallback = new FutureCallback<Transaction>()
/*FutureCallback<Transaction> localCallback = new FutureCallback<Transaction>()
{
@Override
public void onSuccess(Transaction transaction)
{
log.info("offererSignAndSendTx onSuccess" + transaction.toString());
log.info("offererSignAndSendTx onSuccess" + transaction.getHashAsString());
}
@Override
@ -589,19 +660,18 @@ public class WalletFacade implements WalletEventListener
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t.toString());
}
};
Futures.addCallback(broadcastComplete, localCallback);
Futures.addCallback(broadcastComplete, localCallback); */
Futures.addCallback(broadcastComplete, callback);
return tx;
}
// payout 1. offerer
private Pair<ECKey.ECDSASignature, Transaction> offererCreateAndSignPayoutTx(String depositTxID,
BigInteger offererPaybackAmount,
BigInteger takerPaybackAmount,
String takerAddress) throws InsufficientMoneyException, AddressFormatException
public Pair<ECKey.ECDSASignature, Transaction> offererCreateAndSignPayoutTx(String depositTxID,
BigInteger offererPaybackAmount,
BigInteger takerPaybackAmount,
String takerAddress) throws InsufficientMoneyException, AddressFormatException
{
ECKey key = wallet.getKeys().get(0);
// offerer has published depositTx so he has it in wallet
Transaction depositTx = wallet.getTransaction(new Sha256Hash(depositTxID));
TransactionOutput multiSigOutput = depositTx.getOutput(0);
@ -610,24 +680,24 @@ public class WalletFacade implements WalletEventListener
Transaction tx = new Transaction(params);
tx.addInput(multiSigOutput);
//TODO fee calculation
tx.addOutput(offererPaybackAmount.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), key.toAddress(params));
tx.addOutput(offererPaybackAmount.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), tradingKey.toAddress(params));
tx.addOutput(takerPaybackAmount.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), new Address(params, takerAddress));
Sha256Hash sigHash = tx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature signature = key.sign(sigHash);
ECKey.ECDSASignature signature = tradingKey.sign(sigHash);
return new Pair<>(signature, depositTx);
}
// payout 2. taker
private Transaction takerSignAndSendTx(String depositTxAsHex,
String offererSignatureR,
String offererSignatureS,
BigInteger offererPaybackAmount,
BigInteger takerPaybackAmount,
String offererAddress) throws InsufficientMoneyException, AddressFormatException
public Transaction takerSignAndSendTx(String depositTxAsHex,
String offererSignatureR,
String offererSignatureS,
BigInteger offererPaybackAmount,
BigInteger takerPaybackAmount,
String offererAddress,
FutureCallback<Transaction> callback) throws InsufficientMoneyException, AddressFormatException
{
ECKey key = wallet.getKeys().get(0);
Transaction depositTx = new Transaction(params, Utils.parseAsHexOrBase58(depositTxAsHex));
TransactionOutput multiSigOutput = depositTx.getOutput(0);
@ -636,12 +706,17 @@ public class WalletFacade implements WalletEventListener
Transaction tx = new Transaction(params);
tx.addInput(multiSigOutput);
//TODO fee calculation
if (offererPaybackAmount.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) <= 0)
log.error("Cannot use such low value");
if (takerPaybackAmount.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) <= 0)
log.error("Cannot use such low value");
tx.addOutput(offererPaybackAmount.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), new Address(params, offererAddress));
tx.addOutput(takerPaybackAmount.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), key.toAddress(params));
tx.addOutput(takerPaybackAmount.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), tradingKey.toAddress(params));
Sha256Hash sigHash = tx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature takerSignature = key.sign(sigHash);
ECKey.ECDSASignature takerSignature = tradingKey.sign(sigHash);
TransactionSignature takerTxSig = new TransactionSignature(takerSignature, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature offererSignature = new ECKey.ECDSASignature(new BigInteger(offererSignatureR), new BigInteger(offererSignatureS));
@ -650,32 +725,143 @@ public class WalletFacade implements WalletEventListener
Script inputScript = ScriptBuilder.createMultiSigInputScript(ImmutableList.of(offererTxSig, takerTxSig));
tx.getInput(0).setScriptSig(inputScript);
log.info("verify tx");
tx.verify();
tx.getInput(0).getScriptSig().correctlySpends(tx, 0, multiSigScript, false);
tx.getInput(0).verify(multiSigOutput);
try
{
log.info("verify correctlySpends");
tx.getInput(0).getScriptSig().correctlySpends(tx, 0, multiSigScript, false);
} catch (Exception e)
{
log.error("verify correctlySpends 0:" + e.getMessage());
}
try
{
log.info("verify multiSigOutput");
tx.getInput(0).verify(multiSigOutput);
} catch (Exception e)
{
log.error("verify multiSigOutput 1:" + e.getMessage());
}
log.info("broadcastTransaction:" + tx.toString());
Object t = wallet.getTransactions(true);
log.info("pre broadcastTransaction broadcastTransaction:" + wallet.getTransactions(true).size());
ListenableFuture<Transaction> broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(tx);
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
/* final TransactionBroadcast broadcast = new TransactionBroadcast(walletAppKit.peerGroup(), tx);
broadcast.setMinConnections(1);
Futures.addCallback(broadcast.future(), new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction transaction) {
// OK, now tell the wallet about the transaction. If the wallet created the transaction then
// it already knows and will ignore this. If it's a transaction we received from
// somebody else via a side channel and are now broadcasting, this will put it into the
// wallet now we know it's valid.
for (Wallet wallet : wallets) {
// Assumption here is there are no dependencies of the created transaction.
//
// We may end up with two threads trying to do this in parallel - the wallet will
// ignore whichever one loses the race.
try {
wallet.receivePending(transaction, null);
} catch (VerificationException e) {
throw new RuntimeException(e); // Cannot fail to verify a tx we created ourselves.
}
}
}
@Override
public void onFailure(Throwable throwable) {
// This can't happen with the current code, but just in case one day that changes ...
// runningBroadcasts.remove(broadcast);
throw new RuntimeException(throwable);
}
}); */
// Keep a reference to the TransactionBroadcast object. This is important because otherwise, the entire tree
// of objects we just created would become garbage if the user doens't hold on to the returned future, and
// eventually be collected. This in turn could result in the transaction not being committed to the wallet
// at all.
// runningBroadcasts.add(broadcast);
// broadcast.broadcast();
FutureCallback<Transaction> localCallback = new FutureCallback<Transaction>()
{
@Override
public void onSuccess(Transaction transaction)
{
Object t = wallet.getTransactions(true);
log.info("onSuccess broadcastTransaction:" + wallet.getTransactions(true).size());
log.info("sendResult onSuccess:" + transaction.toString());
log.info("is in wallet?" + wallet.getTransaction(transaction.getHash()).getHashAsString());
/*if (wallet.getTransaction(transaction.getHash()) == null)
wallet.commitTx(transaction); */
log.info("now must be in wallet?" + wallet.getTransaction(transaction.getHash()).getHashAsString());
log.info("##################### now must be in wallet?" + wallet.getTransaction(transaction.getHash()).getHashAsString());
}
@Override
public void onFailure(Throwable t)
{
log.warn("sendResult onFailure:" + t.toString());
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t.toString());
}
};
Futures.addCallback(broadcastComplete, localCallback);
Futures.addCallback(broadcastComplete, callback);
return tx;
}
/*
public ListenableFuture<Transaction> broadcastTransaction(final Transaction tx, final int minConnections) {
final TransactionBroadcast broadcast = new TransactionBroadcast(walletAppKit.peerGroup(), tx);
broadcast.setMinConnections(1);
// Send the TX to the wallet once we have a successful broadcast.
Futures.addCallback(broadcast.future(), new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction transaction) {
// OK, now tell the wallet about the transaction. If the wallet created the transaction then
// it already knows and will ignore this. If it's a transaction we received from
// somebody else via a side channel and are now broadcasting, this will put it into the
// wallet now we know it's valid.
for (Wallet wallet : wallets) {
// Assumption here is there are no dependencies of the created transaction.
//
// We may end up with two threads trying to do this in parallel - the wallet will
// ignore whichever one loses the race.
try {
wallet.receivePending(transaction, null);
} catch (VerificationException e) {
throw new RuntimeException(e); // Cannot fail to verify a tx we created ourselves.
}
}
}
@Override
public void onFailure(Throwable throwable) {
// This can't happen with the current code, but just in case one day that changes ...
runningBroadcasts.remove(broadcast);
throw new RuntimeException(throwable);
}
});
// Keep a reference to the TransactionBroadcast object. This is important because otherwise, the entire tree
// of objects we just created would become garbage if the user doens't hold on to the returned future, and
// eventually be collected. This in turn could result in the transaction not being committed to the wallet
// at all.
runningBroadcasts.add(broadcast);
broadcast.broadcast();
return broadcast.future();
} */
///////////////////////////////////////////////////////////////////////////////////////////
// Inner classes
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -44,9 +44,9 @@ public class BitSquareModule extends AbstractModule
bind(Trading.class).asEagerSingleton();
//bind(String.class).annotatedWith(Names.named("networkType")).toInstance(WalletFacade.MAIN_NET);
// bind(String.class).annotatedWith(Names.named("networkType")).toInstance(WalletFacade.REG_TEST_NET);
bind(String.class).annotatedWith(Names.named("networkType")).toInstance(WalletFacade.TEST_NET);
// bind(String.class).annotatedWith(Names.named("networkType")).toInstance(WalletFacade.MAIN_NET);
bind(String.class).annotatedWith(Names.named("networkType")).toInstance(WalletFacade.REG_TEST_NET);
// bind(String.class).annotatedWith(Names.named("networkType")).toInstance(WalletFacade.TEST_NET);
bind(NetworkParameters.class).toProvider(NetworkParametersProvider.class).asEagerSingleton();
bind(WalletAppKit.class).toProvider(WalletAppKitProvider.class).asEagerSingleton();
}

View File

@ -305,7 +305,6 @@ public class MainController implements Initializable, NavigationController, Wall
{
balanceTextField = new TextField();
balanceTextField.setEditable(false);
balanceTextField.setMouseTransparent(true);
balanceTextField.setPrefWidth(90);
balanceTextField.setId("nav-balance-label");

View File

@ -1,67 +0,0 @@
package io.bitsquare.gui.components;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.util.FormBuilder;
import io.bitsquare.gui.util.Icons;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
public class ConfirmationComponent implements WalletFacade.WalletListener
{
private static final Logger log = LoggerFactory.getLogger(ConfirmationComponent.class);
private ImageView confirmIconImageView;
private TextField confirmationsLabel;
private ProgressIndicator confirmSpinner;
public ConfirmationComponent(WalletFacade walletFacade, GridPane gridPane, int row)
{
confirmationsLabel = FormBuilder.addConfirmationsLabel(gridPane, walletFacade, row);
confirmIconImageView = FormBuilder.addConfirmationsIcon(gridPane, walletFacade, row);
confirmSpinner = FormBuilder.addConfirmationsSpinner(gridPane, walletFacade, row);
}
@Override
public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks)
{
confirmIconImageView.setImage(getConfirmIconImage(numBroadcastPeers, depthInBlocks));
confirmationsLabel.setText(getConfirmationsText(numBroadcastPeers, depthInBlocks));
if (depthInBlocks == 0 && numBroadcastPeers > 0)
confirmSpinner.setProgress(-1);
else
confirmSpinner.setOpacity(0);
log.info("onConfidenceChanged " + numBroadcastPeers + " / " + depthInBlocks);
}
@Override
public void onCoinsReceived(BigInteger newBalance)
{
log.info("onCoinsReceived " + newBalance);
}
private String getConfirmationsText(int numBroadcastPeers, int depthInBlocks)
{
depthInBlocks = 0;
return depthInBlocks + " confirmation(s) / " + "Seen by " + numBroadcastPeers + " peer(s)";
}
private Image getConfirmIconImage(int numBroadcastPeers, int depthInBlocks)
{
depthInBlocks = 0;
if (depthInBlocks > 0)
return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks));
else
return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers));
}
}

View File

@ -32,6 +32,7 @@ public class NetworkSyncPane extends HBox
public void doneDownload()
{
networkSyncInfoLabel.setText("Sync with network: Done");
networkSyncProgressBar.setProgress(1);
FadeTransition fade = new FadeTransition(Duration.millis(700), this);
fade.setToValue(0.0);

View File

@ -94,9 +94,10 @@ public class CreateOfferController implements Initializable, ChildController
//TODO
amountTextField.setText("0,01");
minAmountTextField.setText("0,001");
amountTextField.setText("1");
minAmountTextField.setText("0,1");
priceTextField.setText("500");
collateralTextField.setText("10");
updateVolume();
amountTextField.textProperty().addListener(new ChangeListener<String>()
@ -131,7 +132,7 @@ public class CreateOfferController implements Initializable, ChildController
bankAccountCountyTextField.setText(user.getCurrentBankAccount().getCountryLocale().getDisplayCountry());
acceptedCountriesTextField.setText(Formatter.countryLocalesToString(settings.getAcceptedCountryLocales()));
acceptedLanguagesTextField.setText(Formatter.languageLocalesToString(settings.getAcceptedLanguageLocales()));
feeLabel.setText(Utils.bitcoinValueToFriendlyString(Fees.OFFER_CREATION_FEE));
feeLabel.setText(Utils.bitcoinValueToFriendlyString(Fees.OFFER_CREATION_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)));
}
@ -279,9 +280,9 @@ public class CreateOfferController implements Initializable, ChildController
return priceAsDouble > 0 &&
amountAsDouble > 0 &&
minAmountAsDouble > 0 &&
minAmountAsDouble <= amountAsDouble &&
minAmountAsDouble <= amountAsDouble/* &&
collateralAsDouble >= settings.getMinCollateral() &&
collateralAsDouble <= settings.getMaxCollateral();
collateralAsDouble <= settings.getMaxCollateral()*/;
}
}

View File

@ -1,5 +1,7 @@
package io.bitsquare.gui.market.trade;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.Utils;
import com.google.inject.Inject;
import io.bitsquare.btc.BlockChainFacade;
import io.bitsquare.btc.BtcFormatter;
@ -14,6 +16,7 @@ import io.bitsquare.gui.util.FormBuilder;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.gui.util.Popups;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.TradeMessage;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.Trade;
@ -37,7 +40,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
public class TakerTradeController implements Initializable, ChildController, WalletFacade.WalletListener
public class TakerTradeController implements Initializable, ChildController
{
private static final Logger log = LoggerFactory.getLogger(TakerTradeController.class);
@ -114,7 +117,6 @@ public class TakerTradeController implements Initializable, ChildController, Wal
@Override
public void initialize(URL url, ResourceBundle rb)
{
walletFacade.addRegistrationWalletListener(this);
}
@ -136,27 +138,9 @@ public class TakerTradeController implements Initializable, ChildController, Wal
checkOnlineStatusTimer.stop();
checkOnlineStatusTimer = null;
}
walletFacade.removeRegistrationWalletListener(this);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: WalletFacade.WalletListener
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks)
{
//log.info("onConfidenceChanged " + numBroadcastPeers + " / " + depthInBlocks);
}
@Override
public void onCoinsReceived(BigInteger newBalance)
{
//log.info("onCoinsReceived " + newBalance);
}
//TODO
public void onPingPeerResult(boolean success)
{
@ -187,7 +171,7 @@ public class TakerTradeController implements Initializable, ChildController, Wal
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):", BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE, false), ++row);
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);
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPay(), ++row);
isOnlineTextField = FormBuilder.addTextField(gridPane, "Online status:", "Checking offerers online status...", ++row);
@ -198,9 +182,10 @@ public class TakerTradeController implements Initializable, ChildController, Wal
isOnlineCheckerHolder.getChildren().addAll(isOnlineChecker);
gridPane.add(isOnlineCheckerHolder, 2, row);
//TODO
messageFacade.pingPeer(offer.getMessagePubKeyAsHex());
checkOnlineStatusTimer = Utilities.setTimeout(5000, (AnimationTimer animationTimer) -> {
setIsOnlineStatus(false);
checkOnlineStatusTimer = Utilities.setTimeout(1000, (AnimationTimer animationTimer) -> {
setIsOnlineStatus(true);
return null;
});
@ -321,15 +306,26 @@ public class TakerTradeController implements Initializable, ChildController, Wal
}
@Override
public void onBankTransferInited()
public void onBankTransferInited(TradeMessage tradeMessage)
{
buildBankTransferInitedScreen();
buildBankTransferInitedScreen(tradeMessage);
}
@Override
public void onTradeCompleted(String hashAsString)
{
showSummary(hashAsString);
}
});
takerPaymentProtocol.takeOffer();
}
private void updateTx(Trade trade)
{
}
private void buildDepositPublishedScreen(String depositTxID)
{
gridPane.getChildren().clear();
@ -338,24 +334,26 @@ public class TakerTradeController implements Initializable, ChildController, Wal
headerLabel = FormBuilder.addHeaderLabel(gridPane, "Deposit transaction published", ++row, 0);
infoLabel = FormBuilder.addLabel(gridPane, "Status:", "Deposit transaction published by offerer.\nAs soon as the offerer starts the \nBank transfer, you will get informed.", ++row);
FormBuilder.addTextField(gridPane, "Transaction ID:", depositTxID, ++row, false, true);
// todo need to load that tx from blockchain, or listen to blockchain
// confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, transaction, progressIndicator);
}
private void buildBankTransferInitedScreen()
private void buildBankTransferInitedScreen(TradeMessage tradeMessage)
{
processStepBar.next();
headerLabel.setText("Bank transfer inited");
infoLabel.setText("Check your bank account and continue \nwhen you have received the money.");
log.info("#### grid " + gridPane.getChildren().size());
gridPane.add(nextButton, 1, ++row);
nextButton.setText("I have received the money at my bank");
nextButton.setOnAction(e -> releaseBTC());
nextButton.setOnAction(e -> releaseBTC(tradeMessage));
}
private void releaseBTC()
private void releaseBTC(TradeMessage tradeMessage)
{
processStepBar.next();
trading.releaseBTC(trade);
trading.releaseBTC(trade.getUid(), tradeMessage);
nextButton.setText("Close");
nextButton.setOnAction(e -> close());
@ -379,10 +377,14 @@ public class TakerTradeController implements Initializable, ChildController, Wal
gridPane.add(nextButton, 1, ++row);
}
private void showSummary(String hashAsString)
{
gridPane.getChildren().clear();
}
private void close()
{
walletFacade.removeRegistrationWalletListener(this);
TabPane tabPane = ((TabPane) (rootContainer.getParent().getParent()));
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
@ -431,11 +433,11 @@ public class TakerTradeController implements Initializable, ChildController, Wal
{
if (takerIsSelling())
{
return BtcFormatter.formatSatoshis(getAmountInSatoshis().add(Fees.OFFER_TAKER_FEE).add(getCollateralInSatoshis()), false);
return BtcFormatter.formatSatoshis(getAmountInSatoshis().add(Fees.OFFER_TAKER_FEE).add(Transaction.MIN_NONDUST_OUTPUT).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).add(getCollateralInSatoshis()), false);
}
else
{
return BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE.add(getCollateralInSatoshis()), false) + "\n" +
return BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).add(getCollateralInSatoshis()), false) + "\n" +
Formatter.formatVolume(getVolume(), offer.getCurrency());
}
}

View File

@ -1,14 +1,19 @@
package io.bitsquare.gui.orders;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.TransactionConfidence;
import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.core.WalletEventListener;
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.WalletFacade;
import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.util.ConfidenceDisplay;
import io.bitsquare.gui.util.Icons;
import io.bitsquare.gui.util.Localisation;
import io.bitsquare.trade.Direction;
@ -19,6 +24,7 @@ import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
@ -34,6 +40,7 @@ import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.net.URL;
import java.util.*;
@ -42,10 +49,12 @@ public class OrdersController implements Initializable, ChildController
private static final Logger log = LoggerFactory.getLogger(OrdersController.class);
private Trading trading;
private WalletFacade walletFacade;
private Trade currentTrade;
private Image buyIcon = Icons.getIconImage(Icons.BUY);
private Image sellIcon = Icons.getIconImage(Icons.SELL);
private ConfidenceDisplay confidenceDisplay;
@FXML
private TableView openTradesTable;
@ -54,9 +63,9 @@ public class OrdersController implements Initializable, ChildController
@FXML
private ProgressIndicator progressIndicator;
@FXML
private Label confidenceLabel, txIDCopyIcon, holderNameCopyIcon, primaryBankAccountIDCopyIcon, secondaryBankAccountIDCopyIcon;
private Label confirmationLabel, txIDCopyIcon, holderNameCopyIcon, primaryBankAccountIDCopyIcon, secondaryBankAccountIDCopyIcon;
@FXML
private TextField txIDTextField, bankAccountTypeTextField, holderNameTextField, primaryBankAccountIDTextField, secondaryBankAccountIDTextField;
private TextField txTextField, bankAccountTypeTextField, holderNameTextField, primaryBankAccountIDTextField, secondaryBankAccountIDTextField;
@FXML
private Button bankTransferInitedButton;
@ -66,9 +75,10 @@ public class OrdersController implements Initializable, ChildController
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public OrdersController(Trading trading)
public OrdersController(Trading trading, WalletFacade walletFacade)
{
this.trading = trading;
this.walletFacade = walletFacade;
}
@ -95,12 +105,44 @@ public class OrdersController implements Initializable, ChildController
openTradesTable.getSelectionModel().selectedItemProperty().addListener((observableValue, oldValue, newValue) -> {
if (newValue instanceof TradesTableItem)
{
TradesTableItem tradesTableItem = (TradesTableItem) newValue;
fillData(tradesTableItem.getTrade());
showTradeDetails((TradesTableItem) newValue);
}
});
trading.getNewTradeProperty().addListener(new ChangeListener<String>()
{
@Override
public void changed(ObservableValue<? extends String> observableValue, String oldTradeUid, String newTradeUid)
{
Trade newTrade = trading.getTrades().get(newTradeUid);
tradeItems.add(new TradesTableItem(newTrade));
}
});
initCopyIcons();
if (tradeItems.size() > 0)
{
openTradesTable.getSelectionModel().select(0);
}
tradeItems.addListener(new ListChangeListener<TradesTableItem>()
{
@Override
public void onChanged(Change<? extends TradesTableItem> change)
{
if (openTradesTable.getSelectionModel().getSelectedItem() == null && tradeItems.size() > 0)
{
openTradesTable.getSelectionModel().select(0);
}
}
});
}
private void showTradeDetails(TradesTableItem tradesTableItem)
{
fillData(tradesTableItem.getTrade());
}
@Override
@ -111,62 +153,75 @@ public class OrdersController implements Initializable, ChildController
@Override
public void cleanup()
{
}
public void bankTransferInited(ActionEvent actionEvent)
{
trading.onBankTransferInited(currentTrade.getUid());
bankTransferInitedButton.setDisable(true);
}
private void updateTx(Trade trade)
{
Transaction transaction = trade.getDepositTransaction();
String txID = "";
if (transaction != null)
{
txID = transaction.getHashAsString();
confirmationLabel.setVisible(true);
progressIndicator.setVisible(true);
progressIndicator.setProgress(-1);
transaction.getConfidence().addEventListener(new TransactionConfidence.Listener()
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 onConfidenceChanged(Transaction tx, ChangeReason reason)
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)
{
updateConfidence(tx);
}
});
}
else
{
updateConfidence(transaction);
}
txIDTextField.setText(txID);
}
private void updateConfidence(Transaction tx)
{
TransactionConfidence confidence = tx.getConfidence();
switch (confidence.getConfidenceType())
{
case UNKNOWN:
confidenceLabel.setText("");
progressIndicator.setProgress(0);
break;
case PENDING:
confidenceLabel.setText("Seen by " + confidence.numBroadcastPeers() + " peer(s)");
progressIndicator.setProgress(-1);
break;
case BUILDING:
bankTransferInitedButton.setOpacity(1);
confidenceLabel.setText("Confirmed in " + confidence.getDepthInBlocks() + " block(s)");
progressIndicator.setProgress(Math.min(1, (double) confidence.getDepthInBlocks() / 6.0));
break;
case DEAD:
confidenceLabel.setText("Transaction is invalid.");
break;
}
}
private void fillData(Trade trade)
{
@ -189,12 +244,37 @@ public class OrdersController implements Initializable, ChildController
}
// back details
BankAccount bankAccount = trade.getContract().getTakerBankAccount();
bankAccountTypeTextField.setText(bankAccount.getBankAccountType().getType().toString());
holderNameTextField.setText(bankAccount.getAccountHolderName());
primaryBankAccountIDTextField.setText(bankAccount.getAccountPrimaryID());
secondaryBankAccountIDTextField.setText(bankAccount.getAccountSecondaryID());
if (trade.getContract() != null)
{
setBankData(trade);
}
else
{
trade.getContractChangedProperty().addListener(new ChangeListener<Boolean>()
{
@Override
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean aBoolean, Boolean aBoolean2)
{
setBankData(trade);
}
});
}
}
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());
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Table columns
///////////////////////////////////////////////////////////////////////////////////////////
@ -218,14 +298,14 @@ public class OrdersController implements Initializable, ChildController
}
@Override
public void updateItem(final TradesTableItem orderBookListItem, boolean empty)
public void updateItem(final TradesTableItem tradesTableItem, boolean empty)
{
super.updateItem(orderBookListItem, empty);
super.updateItem(tradesTableItem, empty);
hBox.getChildren().clear();
if (orderBookListItem != null)
if (tradesTableItem != null)
{
Locale countryLocale = orderBookListItem.getTrade().getOffer().getBankAccountCountryLocale();
Locale countryLocale = tradesTableItem.getTrade().getOffer().getBankAccountCountryLocale();
try
{
hBox.getChildren().add(Icons.getIconImageView("/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png"));
@ -253,13 +333,13 @@ public class OrdersController implements Initializable, ChildController
return new TableCell<String, TradesTableItem>()
{
@Override
public void updateItem(final TradesTableItem orderBookListItem, boolean empty)
public void updateItem(final TradesTableItem tradesTableItem, boolean empty)
{
super.updateItem(orderBookListItem, empty);
super.updateItem(tradesTableItem, empty);
if (orderBookListItem != null)
if (tradesTableItem != null)
{
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum = orderBookListItem.getTrade().getOffer().getBankAccountTypeEnum();
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum = tradesTableItem.getTrade().getOffer().getBankAccountTypeEnum();
setText(Localisation.get(bankAccountTypeEnum.toString()));
}
else
@ -291,15 +371,15 @@ public class OrdersController implements Initializable, ChildController
}
@Override
public void updateItem(final TradesTableItem orderBookListItem, boolean empty)
public void updateItem(final TradesTableItem tradesTableItem, boolean empty)
{
super.updateItem(orderBookListItem, empty);
super.updateItem(tradesTableItem, empty);
if (orderBookListItem != null)
if (tradesTableItem != null)
{
String title;
Image icon;
Offer offer = orderBookListItem.getTrade().getOffer();
Offer offer = tradesTableItem.getTrade().getOffer();
if (offer.getDirection() == Direction.SELL)
{
@ -339,12 +419,13 @@ public class OrdersController implements Initializable, ChildController
final Button button = new Button("Select");
@Override
public void updateItem(final TradesTableItem orderBookListItem, boolean empty)
public void updateItem(final TradesTableItem tradesTableItem, boolean empty)
{
super.updateItem(orderBookListItem, empty);
super.updateItem(tradesTableItem, empty);
if (orderBookListItem != null)
if (tradesTableItem != null)
{
button.setOnAction(event -> showTradeDetails(tradesTableItem));
setGraphic(button);
}
else
@ -364,7 +445,7 @@ public class OrdersController implements Initializable, ChildController
txIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(txIDTextField.getText());
content.putString(txTextField.getText());
clipboard.setContent(content);
});
@ -372,7 +453,7 @@ public class OrdersController implements Initializable, ChildController
holderNameCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(holderNameCopyIcon.getText());
content.putString(holderNameTextField.getText());
clipboard.setContent(content);
});
@ -380,7 +461,7 @@ public class OrdersController implements Initializable, ChildController
primaryBankAccountIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(primaryBankAccountIDCopyIcon.getText());
content.putString(primaryBankAccountIDTextField.getText());
clipboard.setContent(content);
});
@ -388,7 +469,7 @@ public class OrdersController implements Initializable, ChildController
secondaryBankAccountIDCopyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(secondaryBankAccountIDCopyIcon.getText());
content.putString(secondaryBankAccountIDTextField.getText());
clipboard.setContent(content);
});
}

View File

@ -4,8 +4,9 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.*?>
<VBox prefHeight="540" prefWidth="800" 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" fx:controller="io.bitsquare.gui.orders.OrdersController">
<VBox 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>
<Label id="headline-label" text="Open trades">
<VBox.margin>
@ -13,7 +14,7 @@
</VBox.margin>
</Label>
<TableView fx:id="openTradesTable" id="orderbook-table" prefHeight="150.0">
<TableView id="orderbook-table" fx:id="openTradesTable" prefHeight="150.0">
<columns>
<TableColumn fx:id="amountColumn" minWidth="120" text="Amount (Min.)">
<cellValueFactory>
@ -56,12 +57,11 @@
<GridPane hgap="5.0" vgap="5.0">
<children>
<!-- row 0 -->
<Label id="headline-label" text="Deposit transaction" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="LEFT"
GridPane.rowIndex="0"/>
<Label id="headline-label" text="Deposit transaction" GridPane.columnSpan="2" GridPane.halignment="LEFT"/>
<!-- row 1 -->
<Label text="Transaction ID:" GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField fx:id="txIDTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label text="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">
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="-1.0"/>
@ -70,12 +70,17 @@
<Tooltip text="Copy address to clipboard"/>
</tooltip>
</Label>
<ProgressIndicator fx:id="progressIndicator" prefHeight="20" prefWidth="20" GridPane.columnIndex="3" GridPane.rowIndex="1"/>
<Label fx:id="confidenceLabel" text="Checking confirmations..." GridPane.columnIndex="4" GridPane.rowIndex="1"/>
<ProgressIndicator id="confidence-progress-indicator" fx:id="progressIndicator" visible="false" GridPane.columnIndex="3" GridPane.halignment="LEFT" GridPane.rowIndex="1"
GridPane.rowSpan="2" GridPane.valignment="TOP">
<GridPane.margin>
<Insets top="2.0"/>
</GridPane.margin>
</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 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"/>
@ -118,16 +123,15 @@
</Label>
<!-- row 7 -->
<Button fx:id="bankTransferInitedButton" defaultButton="true" opacity="0.5" onAction="#bankTransferInited" 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>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES"/>
<ColumnConstraints hgrow="ALWAYS" minWidth="400"/>
<ColumnConstraints fillWidth="false" halignment="LEFT" hgrow="NEVER"/>
<ColumnConstraints fillWidth="false" halignment="LEFT" hgrow="SOMETIMES"/>
<ColumnConstraints fillWidth="false" halignment="LEFT" hgrow="SOMETIMES"/>
<ColumnConstraints hgrow="ALWAYS"/>
<ColumnConstraints fillWidth="false" hgrow="SOMETIMES" minWidth="20"/>
<ColumnConstraints fillWidth="false" hgrow="SOMETIMES" minWidth="20" prefWidth="20"/>
<ColumnConstraints fillWidth="false" hgrow="SOMETIMES"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>

View File

@ -214,10 +214,10 @@ public class SetupController implements Initializable, ChildController
clipboard.setContent(content);
});
confidenceDisplay = new ConfidenceDisplay(walletFacade.getAccountRegistrationWallet(), confirmationLabel, balanceTextField, progressIndicator);
confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, balanceTextField, progressIndicator);
paymentDoneButton.setDisable(walletFacade.getAccountRegistrationBalance().compareTo(BigInteger.ZERO) == 0);
walletFacade.getAccountRegistrationWallet().addEventListener(new WalletEventListener()
log.debug("getAccountRegistrationBalance " + walletFacade.getAccountRegistrationBalance().toString());
walletFacade.getWallet().addEventListener(new WalletEventListener()
{
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
@ -336,13 +336,13 @@ public class SetupController implements Initializable, ChildController
accountSecondaryID.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState());
//todo
bankAccountTypesComboBox.getSelectionModel().select(0);
/* bankAccountTypesComboBox.getSelectionModel().select(0);
currencyComboBox.getSelectionModel().select(0);
countryComboBox.getSelectionModel().select(0);
accountHolderName.setText("dummy accountHolderName");
accountTitle.setText("dummy accountTitle");
accountPrimaryID.setText("dummy accountPrimaryID");
accountSecondaryID.setText("dummy accountSecondaryID");
accountTitle.setText("Sepa EUR Account");
accountHolderName.setText("Alice");
accountPrimaryID.setText("123456");
accountSecondaryID.setText("7896541"); */
}
private void setupSettingsScreen()

View File

@ -50,12 +50,14 @@ public class ConfidenceDisplay
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
updateBalance(newBalance);
// log.debug("onCoinsReceived " + newBalance);
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
updateConfidence(tx);
// log.debug("onTransactionConfidenceChanged tx " + tx.getHashAsString());
}
@Override
@ -111,12 +113,14 @@ public class ConfidenceDisplay
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
updateBalance(newBalance);
// log.debug("onCoinsReceived " + newBalance);
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
updateConfidence(newTransaction);
// log.debug("onTransactionConfidenceChanged newTransaction " + newTransaction.getHashAsString());
}
@Override

View File

@ -1,12 +1,12 @@
package io.bitsquare.gui.util;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.components.VSpacer;
import javafx.collections.FXCollections;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import java.util.Currency;
@ -103,12 +103,12 @@ public class FormBuilder
} */
public static TextField addConfirmationsLabel(GridPane gridPane, WalletFacade walletFacade, int row)
/* public static TextField addConfirmationsLabel(GridPane gridPane, WalletFacade walletFacade, int row)
{
return FormBuilder.addTextField(gridPane, "Confirmations:", getConfirmationText(walletFacade), row);
}
} */
public static ProgressIndicator addConfirmationsSpinner(GridPane gridPane, WalletFacade walletFacade, int row)
/* public static ProgressIndicator addConfirmationsSpinner(GridPane gridPane, WalletFacade walletFacade, int row)
{
ProgressIndicator progressIndicator = new ProgressIndicator();
gridPane.add(progressIndicator, 3, row);
@ -143,7 +143,7 @@ public class FormBuilder
int numBroadcastPeers = walletFacade.getRegConfNumBroadcastPeers();
int depthInBlocks = walletFacade.getRegConfDepthInBlocks();
return depthInBlocks + " confirmation(s) / " + "Seen by " + numBroadcastPeers + " peer(s)";
}
} */
}

View File

@ -182,6 +182,7 @@ public class MessageFacade
{
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
Number160 contentKey = Number160.createHash(offer.getUid());
log.debug("removeOffer");
FutureDHT removeFuture = myPeer.remove(locationKey).setReturnResults().setContentKey(contentKey).start();
removeFuture.addListener(new BaseFutureAdapter<BaseFuture>()
{
@ -196,6 +197,7 @@ public class MessageFacade
private void onOfferRemoved(Data data, boolean success, Number160 locationKey)
{
log.debug("onOfferRemoved");
setDirty(locationKey);
for (OrderBookListener orderBookListener : orderBookListeners)
@ -456,7 +458,11 @@ public class MessageFacade
break;
case BANK_TX_INITED:
for (TakerPaymentProtocol takeOfferTradeListener : takerPaymentProtocols)
takeOfferTradeListener.onBankTransferInited();
takeOfferTradeListener.onBankTransferInited(tradeMessage);
break;
case PAYOUT_TX_PUBLISHED:
for (OffererPaymentProtocol offererPaymentProtocol : offererPaymentProtocols)
offererPaymentProtocol.onPayoutTxPublished(tradeMessage);
break;
default:
@ -638,7 +644,7 @@ public class MessageFacade
private void setupStorage() throws IOException
{
//TODO BitSquare.ID just temp...
String dirPath = Utilities.getRootDir() + "tomP2P_" + BitSquare.ID;
String dirPath = Utilities.getRootDir() + BitSquare.ID + "_tomP2P";
File dirFile = new File(dirPath);
boolean success = true;
if (!dirFile.exists())

View File

@ -18,8 +18,14 @@ public class TradeMessage implements Serializable
private String txConnOutAsHex;
private String contractAsJson;
private String takerContractSignature;
private String takerPayoutAddress;
private TradeMessageType type;
private String depositTxID;
private String offererSignatureR;
private String offererSignatureS;
private BigInteger offererPaybackAmount;
private BigInteger takerPaybackAmount;
private String offererPayoutAddress;
private BigInteger tradeAmount;
private String takeOfferFeeTxID;
private String takerMultiSigPubKey;
@ -28,6 +34,7 @@ public class TradeMessage implements Serializable
private String accountID;
private String offererPubKey;
private String preparedOffererDepositTxAsHex;
private String payoutTxID;
public TradeMessage(TradeMessageType type, String offerUID)
{
@ -37,6 +44,7 @@ public class TradeMessage implements Serializable
uid = UUID.randomUUID().toString();
}
public TradeMessage(TradeMessageType type, String offerUID, BigInteger tradeAmount, String takeOfferFeeTxID, String takerMultiSigPubKey)
{
this.offerUID = offerUID;
@ -68,7 +76,8 @@ public class TradeMessage implements Serializable
String txScriptSigAsHex,
String txConnOutAsHex,
String contractAsJson,
String takerContractSignature)
String takerContractSignature,
String takerPayoutAddress)
{
this.offerUID = offerUID;
this.type = type;
@ -80,6 +89,7 @@ public class TradeMessage implements Serializable
this.txConnOutAsHex = txConnOutAsHex;
this.contractAsJson = contractAsJson;
this.takerContractSignature = takerContractSignature;
this.takerPayoutAddress = takerPayoutAddress;
uid = UUID.randomUUID().toString();
}
@ -93,6 +103,28 @@ public class TradeMessage implements Serializable
uid = UUID.randomUUID().toString();
}
// 3.10
public TradeMessage(TradeMessageType type, String offerUID,
String depositTxID,
String offererSignatureR,
String offererSignatureS,
BigInteger offererPaybackAmount,
BigInteger takerPaybackAmount,
String offererPayoutAddress)
{
this.offerUID = offerUID;
this.type = type;
this.depositTxID = depositTxID;
this.offererSignatureR = offererSignatureR;
this.offererSignatureS = offererSignatureS;
this.offererPaybackAmount = offererPaybackAmount;
this.takerPaybackAmount = takerPaybackAmount;
this.offererPayoutAddress = offererPayoutAddress;
uid = UUID.randomUUID().toString();
}
public String getUid()
{
@ -178,4 +210,46 @@ public class TradeMessage implements Serializable
{
return offererPubKey;
}
public String getTakerPayoutAddress()
{
return takerPayoutAddress;
}
public String getOffererPayoutAddress()
{
return offererPayoutAddress;
}
public String getOffererSignatureR()
{
return offererSignatureR;
}
public String getOffererSignatureS()
{
return offererSignatureS;
}
public BigInteger getOffererPaybackAmount()
{
return offererPaybackAmount;
}
public BigInteger getTakerPaybackAmount()
{
return takerPaybackAmount;
}
public String getPayoutTxID()
{
return payoutTxID;
}
public void setPayoutTxID(String payoutTxID)
{
this.payoutTxID = payoutTxID;
}
}

View File

@ -9,5 +9,7 @@ public enum TradeMessageType
REQUEST_TAKER_DEPOSIT_PAYMENT,
REQUEST_OFFERER_DEPOSIT_PUBLICATION,
DEPOSIT_TX_PUBLISHED,
BANK_TX_INITED
BANK_TX_INITED,
PAYOUT_TX_PUBLISHED
}

View File

@ -17,7 +17,7 @@ public class Storage
private static final Logger log = LoggerFactory.getLogger(Storage.class);
//TODO save in users preferences location
private final String preferencesFileName = "pref_" + BitSquare.ID + ".ser";
private final String preferencesFileName = BitSquare.ID + "_pref" + ".ser";
private final String storageFile;
private Map<String, Object> dict;

View File

@ -11,6 +11,7 @@ public class Trade implements Serializable
private static final long serialVersionUID = -8275323072940974077L;
transient private final SimpleBooleanProperty depositTxChangedProperty = new SimpleBooleanProperty();
transient private final SimpleBooleanProperty contractChangedProperty = new SimpleBooleanProperty();
private Offer offer;
private String takeOfferFeeTxID;
@ -43,6 +44,7 @@ public class Trade implements Serializable
public void setContract(Contract contract)
{
this.contract = contract;
contractChangedProperty.set(!contractChangedProperty.get());
}
public void setContractAsJson(String contractAsJson)
@ -110,6 +112,12 @@ public class Trade implements Serializable
{
return depositTxChangedProperty;
}
public SimpleBooleanProperty getContractChangedProperty()
{
return contractChangedProperty;
}
///////////////////////////////////////////////////////////////////////////////////////////
// toString
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -18,6 +18,8 @@ import io.bitsquare.trade.offerer.OffererPaymentProtocolListener;
import io.bitsquare.trade.taker.TakerPaymentProtocol;
import io.bitsquare.trade.taker.TakerPaymentProtocolListener;
import io.bitsquare.user.User;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import net.tomp2p.peers.PeerAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -36,8 +38,6 @@ public class Trading
private Map<String, Offer> myOffers = new HashMap<>();
private Map<String, Trade> trades = new HashMap<>();
private final Map<String, TakerPaymentProtocol> takerPaymentProtocols = new HashMap<>();
private final Map<String, OffererPaymentProtocol> offererPaymentProtocols = new HashMap<>();
private final String storageKey;
private User user;
@ -47,6 +47,7 @@ public class Trading
private WalletFacade walletFacade;
private CryptoFacade cryptoFacade;
private Settings settings;
private final StringProperty newTradeProperty = new SimpleStringProperty();
///////////////////////////////////////////////////////////////////////////////////////////
@ -101,8 +102,9 @@ public class Trading
throw new IllegalStateException("offers contains already a offer with the ID " + offer.getUid());
myOffers.put(offer.getUid(), offer);
storage.write(storageKey + ".offers", myOffers);
walletFacade.payFee(Fees.OFFER_CREATION_FEE, callback);
//TODO for testing
//storage.write(storageKey + ".offers", myOffers);
walletFacade.payOfferFee(Fees.OFFER_CREATION_FEE, callback);
}
public void removeOffer(Offer offer) throws IOException
@ -113,12 +115,16 @@ public class Trading
public Trade createTrade(Offer offer)
{
/* if (trades.containsKey(offer.getUid()))
throw new IllegalStateException("trades contains already a trade with the ID " + offer.getUid()); */
if (trades.containsKey(offer.getUid()))
throw new IllegalStateException("trades contains already a trade with the ID " + offer.getUid());
Trade trade = new Trade(offer);
trades.put(offer.getUid(), trade);
storage.write(storageKey + ".trades", trades);
//TODO for testing
//storage.write(storageKey + ".trades", trades);
this.newTradeProperty.set(trade.getUid());
return trade;
}
@ -128,6 +134,11 @@ public class Trading
storage.write(storageKey + ".trades", trades);
}
public final StringProperty getNewTradeProperty()
{
return this.newTradeProperty;
}
public TakerPaymentProtocol addTakerPaymentProtocol(Trade trade, TakerPaymentProtocolListener listener)
{
TakerPaymentProtocol takerPaymentProtocol = new TakerPaymentProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
@ -172,6 +183,12 @@ public class Trading
log.debug("trading onDepositTxConfirmedUpdate");
}
@Override
public void onPayoutTxPublished(String payoutTxID)
{
log.debug("trading onPayoutTxPublished");
}
@Override
public void onDepositTxConfirmedInBlockchain()
{
@ -198,14 +215,9 @@ public class Trading
// 6
public void releaseBTC(Trade trade)
public void releaseBTC(String tradeUID, TradeMessage tradeMessage)
{
log.info("Sign payment tx");
log.info("Broadcast payment tx");
log.info("Send message to peer that payment Tx has been broadcasted.");
// messageFacade.send(new Message(Message.REQUEST_OFFER_FEE_PAYMENT_CONFIRM, trade), trade.getOffer().getOfferer().getMessageID());
takerPaymentProtocols.get(tradeUID).releaseBTC(tradeMessage);
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -1,9 +1,6 @@
package io.bitsquare.trade.offerer;
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.bitcoin.core.*;
import com.google.common.util.concurrent.FutureCallback;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.btc.BlockChainFacade;
@ -18,6 +15,7 @@ import io.bitsquare.trade.Offer;
import io.bitsquare.trade.Trade;
import io.bitsquare.user.User;
import io.bitsquare.util.Utilities;
import javafx.util.Pair;
import net.tomp2p.peers.PeerAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -44,9 +42,11 @@ public class OffererPaymentProtocol
private User user;
private PeerAddress peerAddress;
private boolean isTakeOfferRequested;
private int numberOfSteps = 20;//TODO
private int numberOfSteps = 15;//TODO
private int currentStep = 0;
private String preparedOffererDepositTxAsHex;
private Transaction depositTransaction;
private String takerPayoutAddress;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
@ -118,9 +118,11 @@ public class OffererPaymentProtocol
isTakeOfferRequested = true;
try
{
log.debug("1.3 messageFacade.removeOffer");
messageFacade.removeOffer(offer);
} catch (IOException e)
{
log.error("1.3 messageFacade.removeOffer failed " + e.getMessage());
offererPaymentProtocolListener.onFailure("removeOffer failed " + e.getMessage());
}
@ -212,7 +214,7 @@ public class OffererPaymentProtocol
log.debug("2.5 createDepositTx");
BigInteger collateralAmount = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
BigInteger offererInputAmount = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
String offererPubKey = walletFacade.getMultiSigPubKeyAsHex();
String takerPubKey = requestTradeMessage.getTakerMultiSigPubKey();
String arbitratorPubKey = offer.getArbitrator().getPubKey();
@ -223,13 +225,13 @@ public class OffererPaymentProtocol
checkNotNull(arbitratorPubKey);
log.debug("2.5 offererCreatesMSTxAndAddPayment");
log.debug("collateralAmount " + collateralAmount);
log.debug("offererInputAmount " + Utils.bitcoinValueToFriendlyString(offererInputAmount));
log.debug("offerer pubkey " + offererPubKey);
log.debug("taker pubkey " + takerPubKey);
log.debug("arbitrator pubkey " + arbitratorPubKey);
try
{
Transaction tx = walletFacade.offererCreatesMSTxAndAddPayment(collateralAmount, offererPubKey, takerPubKey, arbitratorPubKey);
Transaction tx = walletFacade.offererCreatesMSTxAndAddPayment(offererInputAmount, offererPubKey, takerPubKey, arbitratorPubKey);
preparedOffererDepositTxAsHex = Utils.bytesToHexString(tx.bitcoinSerialize());
log.debug("2.5 deposit tx created: " + tx);
log.debug("2.5 deposit txAsHex: " + preparedOffererDepositTxAsHex);
@ -237,6 +239,8 @@ public class OffererPaymentProtocol
} catch (InsufficientMoneyException e)
{
log.warn("2.5 InsufficientMoneyException " + e.getMessage());
//110010000
// 20240000
}
}
@ -298,6 +302,7 @@ public class OffererPaymentProtocol
public void onDepositTxReadyForPublication(TradeMessage requestTradeMessage)
{
log.debug("3.1 onDepositTxReadyForPublication");
takerPayoutAddress = requestTradeMessage.getTakerPayoutAddress();
verifyTaker(requestTradeMessage);
}
@ -350,24 +355,29 @@ public class OffererPaymentProtocol
log.debug("3.3 contractAsJson: " + contractAsJson);
log.debug("3.3 requestTradingMessage.getContractAsJson(): " + requestTradeMessage.getContractAsJson());
// TODO generic json creates too complex object, at least the PublicKeys need to be removed
boolean isEqual = contractAsJson.equals(requestTradeMessage.getContractAsJson());
log.debug("3.3 does json match?: " + isEqual);
if (contractAsJson.equals(requestTradeMessage.getContractAsJson()))
{
log.debug("3.3 The 2 contracts as json does match");
String signature = cryptoFacade.signContract(walletFacade.getRegistrationKey(), contractAsJson);
trade.setContract(contract);
trade.setContractAsJson(contractAsJson);
trade.setContractTakerSignature(signature);
log.debug("3.3 signature: " + signature);
/* if (contractAsJson.equals(requestTradingMessage.getContractAsJson()))
{ */
String signature = cryptoFacade.signContract(walletFacade.getAccountRegistrationKey(), contractAsJson);
trade.setContract(contract);
trade.setContractAsJson(contractAsJson);
trade.setContractTakerSignature(signature);
log.debug("3.3 signature: " + signature);
signAndPublishDepositTx(requestTradeMessage);
/* }
signAndPublishDepositTx(requestTradeMessage);
}
else
{
log.error("3.3 verifyContract failed");
} */
//TODO ignore that for now... fee inconsistency...
String signature = cryptoFacade.signContract(walletFacade.getRegistrationKey(), contractAsJson);
trade.setContract(contract);
trade.setContractAsJson(contractAsJson);
trade.setContractTakerSignature(signature);
log.debug("3.3 signature: " + signature);
signAndPublishDepositTx(requestTradeMessage);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -388,6 +398,12 @@ public class OffererPaymentProtocol
public void onSuccess(Transaction transaction)
{
log.info("3.4 signAndPublishDepositTx offererSignAndSendTx onSuccess:" + transaction.toString());
String txID = transaction.getHashAsString();
trade.setDepositTransaction(transaction);
log.debug("3.4 deposit tx published: " + transaction);
log.debug("3.4 deposit txID: " + txID);
sendDepositTxIdToTaker(transaction);
}
@Override
@ -399,13 +415,7 @@ public class OffererPaymentProtocol
try
{
log.debug("3.4 offererSignAndSendTx");
Transaction transaction = walletFacade.offererSignAndSendTx(preparedOffererDepositTxAsHex, signedTakerDepositTxAsHex, txConnOutAsHex, txScriptSigAsHex, callback);
String txID = transaction.getHashAsString();
trade.setDepositTransaction(transaction);
log.debug("3.4 deposit tx published: " + transaction);
log.debug("3.4 deposit txID: " + txID);
sendDepositTxIdToTaker(transaction);
depositTransaction = walletFacade.offererSignAndSendTx(preparedOffererDepositTxAsHex, signedTakerDepositTxAsHex, txConnOutAsHex, txScriptSigAsHex, callback);
} catch (Exception e)
{
log.error("3.4 error at walletFacade.offererSignAndSendTx: " + e.getMessage());
@ -469,20 +479,16 @@ public class OffererPaymentProtocol
@Override
public void onConfidenceChanged(Transaction tx, ChangeReason reason)
{
log.info("onConfidenceChanged reason = " + reason);
log.info("onConfidenceChanged confidence = " + tx.getConfidence().toString());
if (reason == ChangeReason.SEEN_PEERS)
{
updateConfirmation(tx.getConfidence());
log.debug("### confidence.numBroadcastPeers() " + tx.getConfidence().numBroadcastPeers());
//todo just for testing now, dont like to wait so long...
if (tx.getConfidence().numBroadcastPeers() > 3)
/* if (tx.getConfidence().numBroadcastPeers() > 3)
{
onDepositTxConfirmedInBlockchain();
transaction.getConfidence().removeEventListener(this);
}
} */
}
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
@ -534,8 +540,6 @@ public class OffererPaymentProtocol
public void onResult()
{
log.debug("3.10 bankTransferInited BANK_TX_INITED onResult");
log.debug("########## LAST STEP OFFERER FOR FIRST PART");
offererPaymentProtocolListener.onProgress(getProgress());
}
@ -546,9 +550,52 @@ public class OffererPaymentProtocol
offererPaymentProtocolListener.onFailure("bankTransferInited BANK_TX_INITED");
}
};
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.BANK_TX_INITED, trade.getUid());
log.debug("3.10 sendTradingMessage BANK_TX_INITED");
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
try
{
BigInteger collateral = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
BigInteger offererPaybackAmount = trade.getTradeAmount().add(collateral);
BigInteger takerPaybackAmount = collateral;
log.debug("offererPaybackAmount " + offererPaybackAmount.toString());
log.debug("takerPaybackAmount " + takerPaybackAmount.toString());
log.debug("depositTransaction.getHashAsString() " + depositTransaction.getHashAsString());
log.debug("takerPayoutAddress " + takerPayoutAddress);
log.debug("walletFacade.offererCreateAndSignPayoutTx");
Pair<ECKey.ECDSASignature, Transaction> result = walletFacade.offererCreateAndSignPayoutTx(depositTransaction.getHashAsString(), offererPaybackAmount, takerPaybackAmount, takerPayoutAddress);
ECKey.ECDSASignature offererSignature = result.getKey();
String offererSignatureR = offererSignature.r.toString();
String offererSignatureS = offererSignature.s.toString();
Transaction depositTx = result.getValue();
String depositTxID = Utils.bytesToHexString(depositTx.bitcoinSerialize());
String offererPayoutAddress = walletFacade.getAddressAsString();
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.BANK_TX_INITED, trade.getUid(),
depositTxID,
offererSignatureR,
offererSignatureS,
offererPaybackAmount,
takerPaybackAmount,
offererPayoutAddress);
log.debug("depositTxID " + depositTxID);
log.debug("offererSignatureR " + offererSignatureR);
log.debug("offererSignatureS " + offererSignatureS);
log.debug("offererPaybackAmount " + offererPaybackAmount.toString());
log.debug("takerPaybackAmount " + takerPaybackAmount.toString());
log.debug("offererPayoutAddress " + offererPayoutAddress);
log.debug("3.10 sendTradingMessage BANK_TX_INITED");
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
} catch (InsufficientMoneyException e)
{
log.error("3.10 offererCreateAndSignPayoutTx onFailed InsufficientMoneyException " + e.getMessage());
} catch (AddressFormatException e)
{
log.error("3.10 offererCreateAndSignPayoutTx onFailed AddressFormatException " + e.getMessage());
}
}
@ -557,9 +604,29 @@ public class OffererPaymentProtocol
//************************************************************************************************
///////////////////////////////////////////////////////////////////////////////////////////
// Step 3.14 We received the payout tx. Trade is completed
///////////////////////////////////////////////////////////////////////////////////////////
public void onPayoutTxPublished(TradeMessage tradeMessage)
{
log.debug("3.14 onPayoutTxPublished");
log.debug("3.14 TRADE COMPLETE!!!!!!!!!!!");
walletFacade.updateWallet();
offererPaymentProtocolListener.onPayoutTxPublished(tradeMessage.getPayoutTxID());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Util
///////////////////////////////////////////////////////////////////////////////////////////
private double getProgress()
{
currentStep++;
return (double) currentStep / (double) numberOfSteps;
}
}

View File

@ -13,4 +13,6 @@ public interface OffererPaymentProtocolListener
void onDepositTxConfirmedInBlockchain();
void onDepositTxConfirmedUpdate(TransactionConfidence confidence);
void onPayoutTxPublished(String payoutTxID);
}

View File

@ -3,6 +3,7 @@ package io.bitsquare.trade.taker;
import com.google.bitcoin.core.AddressFormatException;
import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.Utils;
import com.google.common.util.concurrent.FutureCallback;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.btc.BlockChainFacade;
@ -43,8 +44,7 @@ public class TakerPaymentProtocol
private CryptoFacade cryptoFacade;
private User user;
private PeerAddress peerAddress;
private boolean isTakeOfferRequested;
private int numberOfSteps = 6;//TODO
private int numberOfSteps = 15;//TODO
private int currentStep = 0;
@ -217,7 +217,7 @@ public class TakerPaymentProtocol
{
// Pay the offer fee
takerPaymentProtocolListener.onProgress(getProgress());
walletFacade.payFee(Fees.OFFER_TAKER_FEE, callback);
walletFacade.payOfferFee(Fees.OFFER_TAKER_FEE, callback);
} catch (InsufficientMoneyException e)
{
takerPaymentProtocolListener.onProgress(getProgress());
@ -341,7 +341,7 @@ public class TakerPaymentProtocol
log.debug("2.9 contract created: " + contract.toString());
String contractAsJson = Utilities.objectToJson(contract);
String signature = cryptoFacade.signContract(walletFacade.getAccountRegistrationKey(), contractAsJson);
String signature = cryptoFacade.signContract(walletFacade.getRegistrationKey(), contractAsJson);
//log.debug("2.9 contractAsJson: " + contractAsJson);
log.debug("2.9 contract signature: " + signature);
@ -363,14 +363,17 @@ public class TakerPaymentProtocol
log.debug("2.10 payDeposit");
BigInteger collateralAmount = trade.getTradeAmount().multiply(BigInteger.valueOf(offer.getCollateral())).divide(BigInteger.valueOf(100));
BigInteger takerAmount = trade.getTradeAmount().add(collateralAmount);
BigInteger msOutputAmount = trade.getTradeAmount().add(collateralAmount).add(collateralAmount);
BigInteger takerInputAmount = trade.getTradeAmount().add(collateralAmount);
// trade + 2 x coll + 1 x btc network fee
BigInteger msOutputAmount = trade.getTradeAmount().add(collateralAmount).add(collateralAmount).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
String offererPubKey = requestTradeMessage.getOffererPubKey();
String takerPubKey = walletFacade.getMultiSigPubKeyAsHex();
String arbitratorPubKey = offer.getArbitrator().getPubKey();
String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex();
checkNotNull(takerAmount);
checkNotNull(takerInputAmount);
checkNotNull(msOutputAmount);
checkNotNull(offererPubKey);
checkNotNull(takerPubKey);
@ -378,15 +381,15 @@ public class TakerPaymentProtocol
checkNotNull(preparedOffererDepositTxAsHex);
log.debug("2.10 offererCreatesMSTxAndAddPayment");
log.debug("takerAmount " + takerAmount);
log.debug("msOutputAmount " + msOutputAmount);
log.debug("takerAmount " + Utils.bitcoinValueToFriendlyString(takerInputAmount));
log.debug("msOutputAmount " + Utils.bitcoinValueToFriendlyString(msOutputAmount));
log.debug("offerer pubkey " + offererPubKey);
log.debug("taker pubkey " + takerPubKey);
log.debug("arbitrator pubkey " + arbitratorPubKey);
log.debug("preparedOffererDepositTxAsHex " + preparedOffererDepositTxAsHex);
try
{
Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSign(takerAmount, msOutputAmount, offererPubKey, takerPubKey, arbitratorPubKey, preparedOffererDepositTxAsHex);
Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSign(takerInputAmount, msOutputAmount, offererPubKey, takerPubKey, arbitratorPubKey, preparedOffererDepositTxAsHex);
log.debug("2.10 deposit tx created: " + signedTakerDepositTx);
sendSignedTakerDepositTxAsHex(signedTakerDepositTx);
} catch (InterruptedException | AddressFormatException | ExecutionException | InsufficientMoneyException e)
@ -433,9 +436,12 @@ public class TakerPaymentProtocol
String signedTakerDepositTxAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.bitcoinSerialize());
String txScriptSigAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes());
String txConnOutAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize());
//TODO just 1 address supported yet
String payoutAddress = walletFacade.getAddressAsString();
log.debug("2.10 deposit txAsHex: " + signedTakerDepositTxAsHex);
log.debug("2.10 txScriptSigAsHex: " + txScriptSigAsHex);
log.debug("2.10 txConnOutAsHex: " + txConnOutAsHex);
log.debug("2.10 payoutAddress: " + payoutAddress);
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_OFFERER_DEPOSIT_PUBLICATION,
trade.getUid(),
@ -446,7 +452,8 @@ public class TakerPaymentProtocol
txScriptSigAsHex,
txConnOutAsHex,
contractAsJson,
signature);
signature,
payoutAddress);
log.debug("2.11 sendTradingMessage");
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
@ -466,6 +473,9 @@ public class TakerPaymentProtocol
{
log.debug("3.6 DepositTxID received: " + tradeMessage.getDepositTxID());
//Transaction tx = walletFacade.getWallet().getTransaction(new Sha256Hash(tradeMessage.getDepositTxID()));
//walletFacade.getWallet().commitTx(tx);
takerPaymentProtocolListener.onProgress(getProgress());
takerPaymentProtocolListener.onDepositTxPublished(tradeMessage.getDepositTxID());
}
@ -480,12 +490,10 @@ public class TakerPaymentProtocol
// Step 3.11 Incoming msg from offerer
///////////////////////////////////////////////////////////////////////////////////////////
public void onBankTransferInited()
public void onBankTransferInited(TradeMessage tradeMessage)
{
log.debug("3.11 Bank transfer inited msg received");
log.debug("########## LAST STEP TAKER FOR FIRST PART");
takerPaymentProtocolListener.onBankTransferInited();
takerPaymentProtocolListener.onBankTransferInited(tradeMessage);
}
//************************************************************************************************
@ -493,6 +501,91 @@ public class TakerPaymentProtocol
//************************************************************************************************
///////////////////////////////////////////////////////////////////////////////////////////
// Step 3.12 User clicked the "bank transfer received" button, so we release the funds for pay out
///////////////////////////////////////////////////////////////////////////////////////////
public void releaseBTC(TradeMessage tradeMessage)
{
log.debug("3.12 releaseBTC");
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
{
@Override
public void onSuccess(Transaction transaction)
{
System.out.println("######### 3.12 onSuccess walletFacade.takerSignAndSendTx " + transaction.toString());
log.error("3.12 onSuccess walletFacade.takerSignAndSendTx " + transaction.toString());
takerPaymentProtocolListener.onTradeCompleted(transaction.getHashAsString());
sendPayoutTxToOfferer(transaction.getHashAsString());
}
@Override
public void onFailure(Throwable t)
{
log.error("######### 3.12 onFailure walletFacade.takerSignAndSendTx");
System.err.println("3.12 onFailure walletFacade.takerSignAndSendTx");
takerPaymentProtocolListener.onFailure("takerSignAndSendTx failed " + t.getMessage());
}
};
try
{
String depositTxID = tradeMessage.getDepositTxID();
String offererSignatureR = tradeMessage.getOffererSignatureR();
String offererSignatureS = tradeMessage.getOffererSignatureS();
BigInteger offererPaybackAmount = tradeMessage.getOffererPaybackAmount();
BigInteger takerPaybackAmount = tradeMessage.getTakerPaybackAmount();
String offererPayoutAddress = tradeMessage.getOffererPayoutAddress();
log.debug("3.12 walletFacade.takerSignAndSendTx");
walletFacade.takerSignAndSendTx(depositTxID,
offererSignatureR,
offererSignatureS,
offererPaybackAmount,
takerPaybackAmount,
offererPayoutAddress,
callback);
} catch (InsufficientMoneyException e)
{
log.error("3.12 offererCreateAndSignPayoutTx onFailed InsufficientMoneyException " + e.getMessage());
} catch (AddressFormatException e)
{
log.error("3.12 offererCreateAndSignPayoutTx onFailed AddressFormatException " + e.getMessage());
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Step 3.13 Send payout txID to offerer
///////////////////////////////////////////////////////////////////////////////////////////
public void sendPayoutTxToOfferer(String txId)
{
log.debug("3.13 sendPayoutTxToOfferer ");
TradeMessageListener listener = new TradeMessageListener()
{
@Override
public void onResult()
{
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onResult");
log.debug("3.13 TRADE COMPLETE!!!!!!!!!!!");
takerPaymentProtocolListener.onProgress(getProgress());
}
@Override
public void onFailed()
{
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed");
takerPaymentProtocolListener.onFailure("sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed");
}
};
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.PAYOUT_TX_PUBLISHED, trade.getUid());
tradeMessage.setPayoutTxID(txId);
log.debug("3.13 sendTradeMessage PAYOUT_TX_PUBLISHED");
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
}
private double getProgress()
{
currentStep++;

View File

@ -1,5 +1,7 @@
package io.bitsquare.trade.taker;
import io.bitsquare.msg.TradeMessage;
public interface TakerPaymentProtocolListener
{
void onProgress(double progress);
@ -8,5 +10,7 @@ public interface TakerPaymentProtocolListener
void onDepositTxPublished(String depositTxID);
void onBankTransferInited();
void onBankTransferInited(TradeMessage tradeMessage);
void onTradeCompleted(String hashAsString);
}

View File

@ -25,7 +25,7 @@ public class DSAKeyUtil
public static KeyPair getKeyPair(String keyName)
{
return getKeyPair("public_" + keyName + ".key", "private_" + keyName + ".key");
return getKeyPair(keyName + "_public" + ".key", keyName + "_private" + ".key");
}

View File

@ -15,17 +15,18 @@
<logger name="io.bitsquare" level="DEBUG"/>
<logger name="com.google.bitcoin" level="ERROR"/>
<logger name="net.tomp2p" level="ERROR"/>
<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.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" level="INFO"/>
<logger name="net.tomp2p" level="WARN"/>
<!--
-->
<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"/>
</configuration>