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,
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,
public Transaction takerSignAndSendTx(String depositTxAsHex,
String offererSignatureR,
String offererSignatureS,
BigInteger offererPaybackAmount,
BigInteger takerPaybackAmount,
String offererAddress) throws InsufficientMoneyException, AddressFormatException
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

@ -45,8 +45,8 @@ 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.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
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(requestTradingMessage.getContractAsJson()))
{ */
String signature = cryptoFacade.signContract(walletFacade.getAccountRegistrationKey(), contractAsJson);
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);
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());
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>