mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
separate wallet addresses
This commit is contained in:
parent
24fdb06a90
commit
205259bee9
9
pom.xml
9
pom.xml
@ -176,7 +176,14 @@
|
||||
<artifactId>core</artifactId>
|
||||
<version>1.50.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>net.sf.proguard</groupId>
|
||||
<artifactId>proguard</artifactId>
|
||||
<version>4.4</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
-->
|
||||
</dependencies>
|
||||
|
||||
<reporting>
|
||||
|
146
src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java
Normal file
146
src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java
Normal file
@ -0,0 +1,146 @@
|
||||
package io.bitsquare.btc;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.bitcoin.params.RegTestParams;
|
||||
import com.google.bitcoin.wallet.CoinSelection;
|
||||
import com.google.bitcoin.wallet.DefaultCoinSelector;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class implements a {@link com.google.bitcoin.wallet.CoinSelector} which attempts to get the highest priority
|
||||
* possible. This means that the transaction is the most likely to get confirmed. Note that this means we may end up
|
||||
* "spending" more priority than would be required to get the transaction we are creating confirmed.
|
||||
*/
|
||||
public class AddressBasedCoinSelector extends DefaultCoinSelector
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(AddressBasedCoinSelector.class);
|
||||
private String tradeUID;
|
||||
private NetworkParameters params;
|
||||
private AddressInfo addressInfo;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public AddressBasedCoinSelector()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AddressBasedCoinSelector(NetworkParameters params, AddressInfo addressInfo)
|
||||
{
|
||||
this.params = params;
|
||||
this.addressInfo = addressInfo;
|
||||
}
|
||||
|
||||
public AddressBasedCoinSelector(String tradeUID)
|
||||
{
|
||||
|
||||
this.tradeUID = tradeUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-classes can override this to just customize whether transactions are usable, but keep age sorting.
|
||||
*/
|
||||
protected boolean shouldSelect(Transaction tx)
|
||||
{
|
||||
return isSelectable(tx);
|
||||
}
|
||||
|
||||
protected boolean matchesRequiredAddress(TransactionOutput transactionOutput)
|
||||
{
|
||||
if (!ScriptUtil.isOpReturnScript(transactionOutput))
|
||||
{
|
||||
Address addressOutput = transactionOutput.getScriptPubKey().getToAddress(params);
|
||||
if (addressInfo != null && addressOutput.equals(addressInfo.getAddress()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public CoinSelection select(BigInteger biTarget, LinkedList<TransactionOutput> candidates)
|
||||
{
|
||||
long target = biTarget.longValue();
|
||||
HashSet<TransactionOutput> selected = new HashSet<TransactionOutput>();
|
||||
// Sort the inputs by age*value so we get the highest "coindays" spent.
|
||||
// TODO: Consider changing the wallets internal format to track just outputs and keep them ordered.
|
||||
ArrayList<TransactionOutput> sortedOutputs = new ArrayList<TransactionOutput>(candidates);
|
||||
// When calculating the wallet balance, we may be asked to select all possible coins, if so, avoid sorting
|
||||
// them in order to improve performance.
|
||||
if (!biTarget.equals(NetworkParameters.MAX_MONEY))
|
||||
{
|
||||
sortOutputs(sortedOutputs);
|
||||
}
|
||||
// Now iterate over the sorted outputs until we have got as close to the target as possible or a little
|
||||
// bit over (excessive value will be change).
|
||||
long total = 0;
|
||||
for (TransactionOutput output : sortedOutputs)
|
||||
{
|
||||
if (total >= target) break;
|
||||
// Only pick chain-included transactions, or transactions that are ours and pending.
|
||||
// Only select outputs from our defined address(es)
|
||||
if (!shouldSelect(output.getParentTransaction()) || !matchesRequiredAddress(output))
|
||||
continue;
|
||||
|
||||
selected.add(output);
|
||||
total += output.getValue().longValue();
|
||||
}
|
||||
// Total may be lower than target here, if the given candidates were insufficient to create to requested
|
||||
// transaction.
|
||||
return new CoinSelection(BigInteger.valueOf(total), selected);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void sortOutputs(ArrayList<TransactionOutput> outputs)
|
||||
{
|
||||
Collections.sort(outputs, new Comparator<TransactionOutput>()
|
||||
{
|
||||
public int compare(TransactionOutput a, TransactionOutput b)
|
||||
{
|
||||
int depth1 = 0;
|
||||
int depth2 = 0;
|
||||
TransactionConfidence conf1 = a.getParentTransaction().getConfidence();
|
||||
TransactionConfidence conf2 = b.getParentTransaction().getConfidence();
|
||||
if (conf1.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||
depth1 = conf1.getDepthInBlocks();
|
||||
if (conf2.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||
depth2 = conf2.getDepthInBlocks();
|
||||
BigInteger aValue = a.getValue();
|
||||
BigInteger bValue = b.getValue();
|
||||
BigInteger aCoinDepth = aValue.multiply(BigInteger.valueOf(depth1));
|
||||
BigInteger bCoinDepth = bValue.multiply(BigInteger.valueOf(depth2));
|
||||
int c1 = bCoinDepth.compareTo(aCoinDepth);
|
||||
if (c1 != 0) return c1;
|
||||
// The "coin*days" destroyed are equal, sort by value alone to get the lowest transaction size.
|
||||
int c2 = bValue.compareTo(aValue);
|
||||
if (c2 != 0) return c2;
|
||||
// They are entirely equivalent (possibly pending) so sort by hash to ensure a total ordering.
|
||||
BigInteger aHash = a.getParentTransaction().getHash().toBigInteger();
|
||||
BigInteger bHash = b.getParentTransaction().getHash().toBigInteger();
|
||||
return aHash.compareTo(bHash);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static boolean isSelectable(Transaction tx)
|
||||
{
|
||||
// Only pick chain-included transactions, or transactions that are ours and pending.
|
||||
TransactionConfidence confidence = tx.getConfidence();
|
||||
TransactionConfidence.ConfidenceType type = confidence.getConfidenceType();
|
||||
return type.equals(TransactionConfidence.ConfidenceType.BUILDING) ||
|
||||
|
||||
type.equals(TransactionConfidence.ConfidenceType.PENDING) &&
|
||||
confidence.getSource().equals(TransactionConfidence.Source.SELF) &&
|
||||
// In regtest mode we expect to have only one peer, so we won't see transactions propagate.
|
||||
// TODO: The value 1 below dates from a time when transactions we broadcast *to* were counted, set to 0
|
||||
(confidence.numBroadcastPeers() > 1 || tx.getParams() == RegTestParams.get());
|
||||
}
|
||||
}
|
@ -5,21 +5,33 @@ import com.google.bitcoin.core.ECKey;
|
||||
import com.google.bitcoin.core.NetworkParameters;
|
||||
import com.google.bitcoin.core.Utils;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class AddressInfo implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 5501603992599920416L;
|
||||
|
||||
public static enum AddressContext
|
||||
{
|
||||
REGISTRATION_FEE,
|
||||
CREATE_OFFER_FEE,
|
||||
TAKE_OFFER_FEE,
|
||||
TRADE,
|
||||
ARBITRATOR_DEPOSIT
|
||||
}
|
||||
|
||||
private ECKey key;
|
||||
private NetworkParameters params;
|
||||
private String label;
|
||||
private String tradeId = null;
|
||||
|
||||
public AddressInfo(ECKey key, NetworkParameters params, String label)
|
||||
private AddressContext addressContext;
|
||||
|
||||
public AddressInfo(ECKey key, NetworkParameters params, AddressContext addressContext, String label)
|
||||
{
|
||||
this.key = key;
|
||||
this.params = params;
|
||||
this.addressContext = addressContext;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@ -28,11 +40,27 @@ public class AddressInfo implements Serializable
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public void setTradeId(String tradeId)
|
||||
{
|
||||
this.tradeId = tradeId;
|
||||
}
|
||||
|
||||
public String getTradeId()
|
||||
{
|
||||
return tradeId;
|
||||
}
|
||||
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
public AddressContext getAddressContext()
|
||||
{
|
||||
return addressContext;
|
||||
}
|
||||
|
||||
public String getAddressString()
|
||||
{
|
||||
return getAddress().toString();
|
||||
@ -43,13 +71,11 @@ public class AddressInfo implements Serializable
|
||||
return Utils.bytesToHexString(key.getPubKey());
|
||||
}
|
||||
|
||||
@Transient
|
||||
public ECKey getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public Address getAddress()
|
||||
{
|
||||
return key.toAddress(params);
|
||||
|
@ -3,12 +3,18 @@ package io.bitsquare.btc;
|
||||
import com.google.bitcoin.core.NetworkParameters;
|
||||
import com.google.bitcoin.core.Wallet;
|
||||
import com.google.bitcoin.crypto.KeyCrypter;
|
||||
import com.google.bitcoin.wallet.CoinSelector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BitSquareWallet extends Wallet
|
||||
import java.io.Serializable;
|
||||
|
||||
public class BitSquareWallet extends Wallet implements Serializable
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(BitSquareWallet.class);
|
||||
private static final long serialVersionUID = -6231929674475881549L;
|
||||
|
||||
private transient CoinSelector coinSelector = new AddressBasedCoinSelector();
|
||||
|
||||
public BitSquareWallet(NetworkParameters params)
|
||||
{
|
||||
@ -20,4 +26,5 @@ public class BitSquareWallet extends Wallet
|
||||
super(params, keyCrypter);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,12 @@ public class BtcFormatter
|
||||
public static BigInteger BTC = new BigInteger("100000000");
|
||||
public static BigInteger mBTC = new BigInteger("100000");
|
||||
|
||||
|
||||
public static String btcToString(BigInteger value)
|
||||
{
|
||||
return Utils.bitcoinValueToFriendlyString(value);
|
||||
}
|
||||
|
||||
//TODO
|
||||
public static double satoshiToBTC(BigInteger satoshis)
|
||||
{
|
||||
|
55
src/main/java/io/bitsquare/btc/FeePolicy.java
Normal file
55
src/main/java/io/bitsquare/btc/FeePolicy.java
Normal file
@ -0,0 +1,55 @@
|
||||
package io.bitsquare.btc;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class FeePolicy
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(FeePolicy.class);
|
||||
|
||||
public static BigInteger TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||
public static BigInteger ACCOUNT_REGISTRATION_FEE = Utils.toNanoCoins("0.01");
|
||||
public static BigInteger CREATE_OFFER_FEE = Utils.toNanoCoins("0.001");
|
||||
public static BigInteger TAKE_OFFER_FEE = CREATE_OFFER_FEE;
|
||||
|
||||
private static final String registrationFee = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR";
|
||||
private static final String offerFee = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg";
|
||||
|
||||
private final NetworkParameters params;
|
||||
|
||||
@Inject
|
||||
public FeePolicy(NetworkParameters params)
|
||||
{
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
//TODO
|
||||
public Address getAddressForRegistrationFee()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Address(params, registrationFee);
|
||||
} catch (AddressFormatException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
public Address getAddressForOfferFee()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Address(params, offerFee);
|
||||
} catch (AddressFormatException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
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 TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||
public static BigInteger ACCOUNT_REGISTRATION_FEE = Utils.toNanoCoins("0.01");
|
||||
public static BigInteger OFFER_CREATION_FEE = Utils.toNanoCoins("0.001");
|
||||
public static BigInteger OFFER_TAKER_FEE = OFFER_CREATION_FEE;
|
||||
}
|
@ -9,11 +9,14 @@ import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
|
||||
|
||||
public class ScriptUtil
|
||||
{
|
||||
public static Script getEmptyOP_RETURNScript()
|
||||
public static Script getOpReturnScript()
|
||||
{
|
||||
return new ScriptBuilder()
|
||||
.op(OP_RETURN)
|
||||
.build();
|
||||
return new ScriptBuilder().op(OP_RETURN).build();
|
||||
}
|
||||
|
||||
public static Script getOpReturnScriptWithData(byte[] data)
|
||||
{
|
||||
return new ScriptBuilder().op(OP_RETURN).data(data).build();
|
||||
}
|
||||
|
||||
public static boolean isOpReturnScript(TransactionOutput transactionOutput)
|
||||
|
@ -7,7 +7,10 @@ import com.google.bitcoin.params.RegTestParams;
|
||||
import com.google.bitcoin.script.Script;
|
||||
import com.google.bitcoin.script.ScriptBuilder;
|
||||
import com.google.bitcoin.utils.Threading;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
@ -22,12 +25,11 @@ import javafx.util.Pair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
|
||||
|
||||
public class WalletFacade
|
||||
{
|
||||
public static final String MAIN_NET = "MAIN_NET";
|
||||
@ -40,6 +42,7 @@ public class WalletFacade
|
||||
|
||||
private NetworkParameters params;
|
||||
private BitSquareWalletAppKit walletAppKit;
|
||||
private FeePolicy feePolicy;
|
||||
private CryptoFacade cryptoFacade;
|
||||
private Storage storage;
|
||||
private BitSquareWallet wallet;
|
||||
@ -55,10 +58,11 @@ public class WalletFacade
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public WalletFacade(NetworkParameters params, BitSquareWalletAppKit walletAppKit, CryptoFacade cryptoFacade, Storage storage)
|
||||
public WalletFacade(NetworkParameters params, BitSquareWalletAppKit walletAppKit, FeePolicy feePolicy, CryptoFacade cryptoFacade, Storage storage)
|
||||
{
|
||||
this.params = params;
|
||||
this.walletAppKit = walletAppKit;
|
||||
this.feePolicy = feePolicy;
|
||||
this.cryptoFacade = cryptoFacade;
|
||||
this.storage = storage;
|
||||
}
|
||||
@ -123,6 +127,7 @@ public class WalletFacade
|
||||
@Override
|
||||
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
|
||||
{
|
||||
log.debug("onTransactionConfidenceChanged " + tx.getConfidence());
|
||||
notifyConfidenceListeners(tx);
|
||||
}
|
||||
|
||||
@ -162,8 +167,14 @@ public class WalletFacade
|
||||
}
|
||||
else
|
||||
{
|
||||
addressInfoList.add(getRegistrationAddressInfo());
|
||||
storage.write("addressInfoList", addressInfoList);
|
||||
ECKey registrationKey = wallet.getKeys().get(0);
|
||||
AddressInfo registrationAddressInfo = new AddressInfo(registrationKey, params, AddressInfo.AddressContext.REGISTRATION_FEE, "Registration");
|
||||
addressInfoList.add(registrationAddressInfo);
|
||||
saveAddressInfoList();
|
||||
|
||||
getNewOfferFeeAddressInfo();
|
||||
getNewTakerFeeAddressInfo();
|
||||
getNewTradeAddressInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,6 +191,12 @@ public class WalletFacade
|
||||
return wallet;
|
||||
}
|
||||
|
||||
private void saveAddressInfoList()
|
||||
{
|
||||
// use wallet extension?
|
||||
storage.write("addressInfoList", addressInfoList);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Listener
|
||||
@ -250,7 +267,7 @@ public class WalletFacade
|
||||
Address address = transactionOutput.getScriptPubKey().getToAddress(params);
|
||||
if (address.equals(balanceListener.getAddress()))
|
||||
{
|
||||
balanceListener.onBalanceChanged(getBalance(address));
|
||||
balanceListener.onBalanceChanged(getBalanceForAddress(address));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -259,7 +276,7 @@ public class WalletFacade
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Address management
|
||||
// Get AddressInfo objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public List<AddressInfo> getAddressInfoList()
|
||||
@ -269,26 +286,123 @@ public class WalletFacade
|
||||
|
||||
public AddressInfo getRegistrationAddressInfo()
|
||||
{
|
||||
ECKey registrationKey = wallet.getKeys().get(0);
|
||||
return new AddressInfo(registrationKey, params, "Registration");
|
||||
return getAddressInfoByAddressContext(AddressInfo.AddressContext.REGISTRATION_FEE);
|
||||
}
|
||||
|
||||
public AddressInfo getNewAddressInfo(String label)
|
||||
public AddressInfo getCreateOfferFeeAddressInfo()
|
||||
{
|
||||
ECKey key = new ECKey();
|
||||
wallet.addKey(key);
|
||||
AddressInfo addressInfo = new AddressInfo(key, params, label);
|
||||
addressInfoList.add(addressInfo);
|
||||
storage.write("addressInfoList", addressInfoList);
|
||||
return getAddressInfoByAddressContext(AddressInfo.AddressContext.CREATE_OFFER_FEE);
|
||||
}
|
||||
|
||||
public AddressInfo getTakerFeeAddressInfo()
|
||||
{
|
||||
return getAddressInfoByAddressContext(AddressInfo.AddressContext.TAKE_OFFER_FEE);
|
||||
}
|
||||
|
||||
public AddressInfo getArbitratorDepositAddressInfo()
|
||||
{
|
||||
AddressInfo arbitratorDepositAddressInfo = getAddressInfoByAddressContext(AddressInfo.AddressContext.ARBITRATOR_DEPOSIT);
|
||||
if (arbitratorDepositAddressInfo == null)
|
||||
arbitratorDepositAddressInfo = getNewArbitratorDepositAddressInfo();
|
||||
|
||||
return arbitratorDepositAddressInfo;
|
||||
}
|
||||
|
||||
private AddressInfo getUnusedTradeAddressInfo()
|
||||
{
|
||||
if (addressInfoList != null)
|
||||
{
|
||||
List<AddressInfo> filteredList = Lists.newArrayList(Collections2.filter(addressInfoList, new Predicate<AddressInfo>()
|
||||
{
|
||||
@Override
|
||||
public boolean apply(@Nullable AddressInfo addressInfo)
|
||||
{
|
||||
return (addressInfo != null && addressInfo.getAddressContext().equals(AddressInfo.AddressContext.TRADE) && addressInfo.getTradeId() == null);
|
||||
}
|
||||
}));
|
||||
|
||||
if (filteredList != null && filteredList.size() > 0)
|
||||
return filteredList.get(0);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private AddressInfo getAddressInfoByAddressContext(AddressInfo.AddressContext addressContext)
|
||||
{
|
||||
if (addressInfoList != null)
|
||||
{
|
||||
List<AddressInfo> filteredList = Lists.newArrayList(Collections2.filter(addressInfoList, new Predicate<AddressInfo>()
|
||||
{
|
||||
@Override
|
||||
public boolean apply(@Nullable AddressInfo addressInfo)
|
||||
{
|
||||
return (addressInfo != null && addressContext != null && addressInfo.getAddressContext() != null && addressInfo.getAddressContext().equals(addressContext));
|
||||
}
|
||||
}));
|
||||
|
||||
if (filteredList != null && filteredList.size() > 0)
|
||||
return filteredList.get(0);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AddressInfo getAddressInfoByTradeID(String tradeId)
|
||||
{
|
||||
for (AddressInfo addressInfo : addressInfoList)
|
||||
{
|
||||
if (addressInfo.getTradeId() != null && addressInfo.getTradeId().equals(tradeId))
|
||||
return addressInfo;
|
||||
}
|
||||
|
||||
AddressInfo addressInfo = getUnusedTradeAddressInfo();
|
||||
addressInfo.setTradeId(tradeId);
|
||||
return addressInfo;
|
||||
}
|
||||
|
||||
public AddressInfo getNewArbitratorAddressInfo()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Create new AddressInfo objects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public AddressInfo getNewTradeAddressInfo()
|
||||
{
|
||||
return getNewAddressInfo("Arbitrator deposit");
|
||||
return getNewAddressInfo(AddressInfo.AddressContext.TRADE, "New trade");
|
||||
}
|
||||
|
||||
public TransactionConfidence getConfidence(Address address)
|
||||
private AddressInfo getNewAddressInfo(AddressInfo.AddressContext addressContext, String label)
|
||||
{
|
||||
ECKey key = new ECKey();
|
||||
wallet.addKey(key);
|
||||
AddressInfo addressInfo = new AddressInfo(key, params, addressContext, label);
|
||||
addressInfoList.add(addressInfo);
|
||||
saveAddressInfoList();
|
||||
return addressInfo;
|
||||
}
|
||||
|
||||
private AddressInfo getNewOfferFeeAddressInfo()
|
||||
{
|
||||
return getNewAddressInfo(AddressInfo.AddressContext.CREATE_OFFER_FEE, "Create offer fee");
|
||||
}
|
||||
|
||||
private AddressInfo getNewTakerFeeAddressInfo()
|
||||
{
|
||||
return getNewAddressInfo(AddressInfo.AddressContext.TAKE_OFFER_FEE, "Take offer fee");
|
||||
}
|
||||
|
||||
private AddressInfo getNewArbitratorDepositAddressInfo()
|
||||
{
|
||||
return getNewAddressInfo(AddressInfo.AddressContext.ARBITRATOR_DEPOSIT, "Arbitrator deposit");
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TransactionConfidence
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public TransactionConfidence getConfidenceForAddress(Address address)
|
||||
{
|
||||
Set<Transaction> transactions = wallet.getTransactions(true);
|
||||
if (transactions != null)
|
||||
@ -317,7 +431,12 @@ public class WalletFacade
|
||||
return null;
|
||||
}
|
||||
|
||||
public BigInteger getBalance(Address address)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Balance
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public BigInteger getBalanceForAddress(Address address)
|
||||
{
|
||||
LinkedList<TransactionOutput> all = wallet.calculateAllSpendCandidates(false);
|
||||
BigInteger value = BigInteger.ZERO;
|
||||
@ -342,103 +461,21 @@ public class WalletFacade
|
||||
|
||||
public BigInteger getRegistrationBalance()
|
||||
{
|
||||
return getBalance(getRegistrationAddressInfo().getAddress());
|
||||
return getBalanceForAddress(getRegistrationAddressInfo().getAddress());
|
||||
}
|
||||
|
||||
public ECKey getRegistrationKey()
|
||||
public BigInteger getArbitratorDepositBalance()
|
||||
{
|
||||
return getRegistrationAddressInfo().getKey();
|
||||
return getBalanceForAddress(getArbitratorDepositAddressInfo().getAddress());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TODO
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//TODO
|
||||
public String getTradingAddress()
|
||||
{
|
||||
return getTradingKey().toAddress(params).toString();
|
||||
}
|
||||
|
||||
//TODO
|
||||
public String getPubKeyAsHex()
|
||||
{
|
||||
return Utils.bytesToHexString(getTradingKey().getPubKey());
|
||||
}
|
||||
|
||||
//TODO
|
||||
public ECKey getTradingKey()
|
||||
{
|
||||
return wallet.getKeys().get(1);
|
||||
}
|
||||
|
||||
|
||||
//TODO separate wallets
|
||||
public BigInteger getCollateralBalance()
|
||||
{
|
||||
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Account registration
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void publishRegistrationTxWithExtraData(String stringifiedBankAccounts) throws InsufficientMoneyException
|
||||
{
|
||||
log.debug("publishRegistrationTxWithExtraData");
|
||||
log.trace("inputs: ");
|
||||
log.trace("stringifiedBankAccounts " + stringifiedBankAccounts);
|
||||
byte[] dataToEmbed = cryptoFacade.getEmbeddedAccountRegistrationData(getRegistrationKey(), stringifiedBankAccounts);
|
||||
Script script = new ScriptBuilder().op(OP_RETURN).data(dataToEmbed).build();
|
||||
Transaction tx = new Transaction(params);
|
||||
TransactionOutput dataOutput = new TransactionOutput(params, tx, Transaction.MIN_NONDUST_OUTPUT, script.getProgram());
|
||||
tx.addOutput(dataOutput);
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
|
||||
// give fee to miners yet. Later it could be spent to other traders via lottery...
|
||||
sendRequest.fee = Fees.ACCOUNT_REGISTRATION_FEE.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Fees.TX_FEE);
|
||||
log.trace("sendRequest.fee: " + Utils.bitcoinValueToFriendlyString(sendRequest.fee));
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
log.debug("Registration transaction: " + tx.toString());
|
||||
printInputs("publishRegistrationTxWithExtraData", tx);
|
||||
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction result)
|
||||
{
|
||||
log.debug("sendResult onSuccess");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.error("sendResult onFailure:" + t.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trade process
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//TODO refactor to similar solution like in PaymentChannelServerState
|
||||
|
||||
public String payOfferFee(BigInteger fee, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
{
|
||||
log.debug("payOfferFee fee=" + Utils.bitcoinValueToFriendlyString(fee));
|
||||
Transaction tx = new Transaction(params);
|
||||
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, ScriptUtil.getEmptyOP_RETURNScript());
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
|
||||
sendRequest.fee = fee.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(Fees.TX_FEE);
|
||||
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
|
||||
log.debug("Check if wallet is consistent: result=" + wallet.isConsistent());
|
||||
printInputs("payOfferFee", tx);
|
||||
log.debug("tx=" + tx.toString());
|
||||
return tx.getHashAsString();
|
||||
}
|
||||
|
||||
public int getNumOfPeersSeenTx(String txID)
|
||||
{
|
||||
// TODO check from blockchain
|
||||
@ -447,13 +484,84 @@ public class WalletFacade
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Transactions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void payRegistrationFee(String stringifiedBankAccounts, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
{
|
||||
log.debug("payRegistrationFee");
|
||||
log.trace("stringifiedBankAccounts " + stringifiedBankAccounts);
|
||||
|
||||
Transaction tx = new Transaction(params);
|
||||
|
||||
byte[] dataToEmbed = cryptoFacade.getEmbeddedAccountRegistrationData(getRegistrationAddressInfo().getKey(), stringifiedBankAccounts);
|
||||
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, ScriptUtil.getOpReturnScriptWithData(dataToEmbed));
|
||||
|
||||
BigInteger fee = FeePolicy.ACCOUNT_REGISTRATION_FEE.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(FeePolicy.TX_FEE);
|
||||
log.trace("fee: " + BtcFormatter.btcToString(fee));
|
||||
tx.addOutput(fee, feePolicy.getAddressForRegistrationFee());
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
sendRequest.coinSelector = new AddressBasedCoinSelector(params, getRegistrationAddressInfo());
|
||||
sendRequest.changeAddress = getRegistrationAddressInfo().getAddress();
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
|
||||
log.debug("Registration transaction: " + tx.toString());
|
||||
printInputs("payRegistrationFee", tx);
|
||||
}
|
||||
|
||||
public String payCreateOfferFee(FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
{
|
||||
Transaction tx = new Transaction(params);
|
||||
BigInteger fee = FeePolicy.CREATE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
|
||||
log.trace("fee: " + BtcFormatter.btcToString(fee));
|
||||
tx.addOutput(fee, feePolicy.getAddressForOfferFee());
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
sendRequest.coinSelector = new AddressBasedCoinSelector(params, getCreateOfferFeeAddressInfo());
|
||||
sendRequest.changeAddress = getCreateOfferFeeAddressInfo().getAddress();
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
|
||||
printInputs("payTakeOfferFee", tx);
|
||||
log.debug("tx=" + tx.toString());
|
||||
|
||||
return tx.getHashAsString();
|
||||
}
|
||||
|
||||
public String payTakeOfferFee(FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
{
|
||||
Transaction tx = new Transaction(params);
|
||||
BigInteger fee = FeePolicy.TAKE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
|
||||
log.trace("fee: " + BtcFormatter.btcToString(fee));
|
||||
tx.addOutput(fee, feePolicy.getAddressForOfferFee());
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
sendRequest.coinSelector = new AddressBasedCoinSelector(params, getTakerFeeAddressInfo());
|
||||
sendRequest.changeAddress = getTakerFeeAddressInfo().getAddress();
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
|
||||
printInputs("payTakeOfferFee", tx);
|
||||
log.debug("tx=" + tx.toString());
|
||||
|
||||
return tx.getHashAsString();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trade process
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 1. step: deposit tx
|
||||
// Offerer creates the 2of3 multiSig deposit tx with his unsigned input and change output
|
||||
public Transaction offererCreatesMSTxAndAddPayment(BigInteger offererInputAmount, String offererPubKey, String takerPubKey, String arbitratorPubKey) throws InsufficientMoneyException
|
||||
public Transaction offererCreatesMSTxAndAddPayment(BigInteger offererInputAmount, String offererPubKey, String takerPubKey, String arbitratorPubKey, String tradeId) throws InsufficientMoneyException
|
||||
{
|
||||
log.debug("offererCreatesMSTxAndAddPayment");
|
||||
log.trace("inputs: ");
|
||||
log.trace("offererInputAmount=" + Utils.bitcoinValueToFriendlyString(offererInputAmount));
|
||||
log.trace("offererInputAmount=" + BtcFormatter.btcToString(offererInputAmount));
|
||||
log.trace("offererPubKey=" + offererPubKey);
|
||||
log.trace("takerPubKey=" + takerPubKey);
|
||||
log.trace("arbitratorPubKey=" + arbitratorPubKey);
|
||||
@ -467,7 +575,13 @@ public class WalletFacade
|
||||
Transaction tx = new Transaction(params);
|
||||
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
|
||||
tx.addOutput(offererInputAmount, multiSigOutputScript);
|
||||
wallet.completeTx(Wallet.SendRequest.forTx(tx));
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
AddressInfo addressInfo = getAddressInfoByTradeID(tradeId);
|
||||
addressInfo.setTradeId(tradeId);
|
||||
sendRequest.coinSelector = new AddressBasedCoinSelector(params, addressInfo);
|
||||
sendRequest.changeAddress = addressInfo.getAddress();
|
||||
wallet.completeTx(sendRequest);
|
||||
|
||||
// The completeTx() call signs the input, but we don't want to pass over a signed tx so we remove the
|
||||
// signature to make sure the tx is invalid for publishing
|
||||
@ -497,13 +611,14 @@ public class WalletFacade
|
||||
String offererPubKey,
|
||||
String takerPubKey,
|
||||
String arbitratorPubKey,
|
||||
String offerersPartialDepositTxAsHex
|
||||
String offerersPartialDepositTxAsHex,
|
||||
String tradeId
|
||||
) throws InsufficientMoneyException, ExecutionException, InterruptedException, AddressFormatException
|
||||
{
|
||||
log.debug("takerAddPaymentAndSignTx");
|
||||
log.trace("inputs: ");
|
||||
log.trace("takerInputAmount=" + Utils.bitcoinValueToFriendlyString(takerInputAmount));
|
||||
log.trace("msOutputAmount=" + Utils.bitcoinValueToFriendlyString(msOutputAmount));
|
||||
log.trace("takerInputAmount=" + BtcFormatter.btcToString(takerInputAmount));
|
||||
log.trace("msOutputAmount=" + BtcFormatter.btcToString(msOutputAmount));
|
||||
log.trace("offererPubKey=" + offererPubKey);
|
||||
log.trace("takerPubKey=" + takerPubKey);
|
||||
log.trace("arbitratorPubKey=" + arbitratorPubKey);
|
||||
@ -518,7 +633,14 @@ public class WalletFacade
|
||||
Transaction tempTx = new Transaction(params);
|
||||
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
|
||||
tempTx.addOutput(takerInputAmount, multiSigOutputScript);
|
||||
wallet.completeTx(Wallet.SendRequest.forTx(tempTx));
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tempTx);
|
||||
AddressInfo addressInfo = getAddressInfoByTradeID(tradeId);
|
||||
addressInfo.setTradeId(tradeId);
|
||||
sendRequest.coinSelector = new AddressBasedCoinSelector(params, addressInfo);
|
||||
sendRequest.changeAddress = addressInfo.getAddress();
|
||||
wallet.completeTx(sendRequest);
|
||||
|
||||
printInputs("tempTx", tempTx);
|
||||
log.trace("tempTx=" + tempTx);
|
||||
// That tx has signed input, but we don't need to remove it as we don't send that tx out, it is just used temporary.
|
||||
@ -550,7 +672,7 @@ public class WalletFacade
|
||||
tx.addOutput(tempTx.getOutput(1));
|
||||
|
||||
// We add the btc tx fee to the msOutputAmount and apply the change to the multiSig output
|
||||
msOutputAmount = msOutputAmount.add(Fees.TX_FEE);
|
||||
msOutputAmount = msOutputAmount.add(FeePolicy.TX_FEE);
|
||||
tx.getOutput(0).setValue(msOutputAmount);
|
||||
|
||||
// Now we sign our input
|
||||
@ -602,6 +724,8 @@ public class WalletFacade
|
||||
String takersSignedTxAsHex,
|
||||
String takersSignedConnOutAsHex,
|
||||
String takersSignedScriptSigAsHex,
|
||||
long offererTxOutIndex,
|
||||
long takerTxOutIndex,
|
||||
FutureCallback<Transaction> callback) throws Exception
|
||||
{
|
||||
log.debug("offererSignAndPublishTx");
|
||||
@ -624,9 +748,9 @@ public class WalletFacade
|
||||
|
||||
// add input
|
||||
Transaction offerersFirstTxConnOut = wallet.getTransaction(offerersFirstTx.getInput(0).getOutpoint().getHash()); // pass that around!
|
||||
TransactionOutPoint offerersFirstTxOutPoint = new TransactionOutPoint(params, 1, offerersFirstTxConnOut);
|
||||
TransactionOutPoint offerersFirstTxOutPoint = new TransactionOutPoint(params, offererTxOutIndex, offerersFirstTxConnOut);
|
||||
//TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, offerersFirstTx.getInput(0).getScriptBytes(), offerersFirstTxOutPoint); // pass that around! getScriptBytes = empty bytes aray
|
||||
TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, new byte[]{}, offerersFirstTxOutPoint); // pass that around! getScriptBytes = empty bytes aray
|
||||
TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, new byte[]{}, offerersFirstTxOutPoint); // pass that around! getScriptBytes = empty bytes array
|
||||
offerersFirstTxInput.setParent(tx);
|
||||
tx.addInput(offerersFirstTxInput);
|
||||
|
||||
@ -638,7 +762,7 @@ public class WalletFacade
|
||||
|
||||
// add input
|
||||
Transaction takersSignedTxConnOut = new Transaction(params, Utils.parseAsHexOrBase58(takersSignedConnOutAsHex));
|
||||
TransactionOutPoint takersSignedTxOutPoint = new TransactionOutPoint(params, 1, takersSignedTxConnOut);
|
||||
TransactionOutPoint takersSignedTxOutPoint = new TransactionOutPoint(params, takerTxOutIndex, takersSignedTxConnOut);
|
||||
TransactionInput takersSignedTxInput = new TransactionInput(params, tx, Utils.parseAsHexOrBase58(takersSignedScriptSigAsHex), takersSignedTxOutPoint);
|
||||
takersSignedTxInput.setParent(tx);
|
||||
tx.addInput(takersSignedTxInput);
|
||||
@ -672,13 +796,13 @@ public class WalletFacade
|
||||
else
|
||||
throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
|
||||
|
||||
log.trace("check if it can be correctly spent for input 0");
|
||||
input.getScriptSig().correctlySpends(tx, 0, scriptPubKey, false);
|
||||
log.trace("check if it can be correctly spent for input 0 OK");
|
||||
|
||||
log.trace("check if it can be correctly spent for input 1");
|
||||
TransactionInput input1 = tx.getInput(1);
|
||||
scriptPubKey = input1.getConnectedOutput().getScriptPubKey();
|
||||
input1.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false);
|
||||
log.trace("check if it can be correctly spent for input 1 OK");
|
||||
|
||||
/*
|
||||
IN[0] offerer signed 0.1001
|
||||
@ -736,13 +860,14 @@ public class WalletFacade
|
||||
public Pair<ECKey.ECDSASignature, String> offererCreatesAndSignsPayoutTx(String depositTxID,
|
||||
BigInteger offererPaybackAmount,
|
||||
BigInteger takerPaybackAmount,
|
||||
String takerAddress) throws InsufficientMoneyException, AddressFormatException
|
||||
String takerAddress,
|
||||
String tradeID) throws InsufficientMoneyException, AddressFormatException
|
||||
{
|
||||
log.debug("offererCreatesAndSignsPayoutTx");
|
||||
log.trace("inputs: ");
|
||||
log.trace("depositTxID=" + depositTxID);
|
||||
log.trace("offererPaybackAmount=" + Utils.bitcoinValueToFriendlyString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + Utils.bitcoinValueToFriendlyString(takerPaybackAmount));
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.btcToString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.btcToString(takerPaybackAmount));
|
||||
log.trace("takerAddress=" + takerAddress);
|
||||
|
||||
// Offerer has published depositTx earlier, so he has it in his wallet
|
||||
@ -750,13 +875,13 @@ public class WalletFacade
|
||||
String depositTxAsHex = Utils.bytesToHexString(depositTx.bitcoinSerialize());
|
||||
|
||||
// We create the payout tx
|
||||
Transaction tx = createPayoutTx(depositTxAsHex, offererPaybackAmount, takerPaybackAmount, getTradingAddress(), takerAddress);
|
||||
Transaction tx = createPayoutTx(depositTxAsHex, offererPaybackAmount, takerPaybackAmount, getAddressInfoByTradeID(tradeID).getAddressString(), takerAddress);
|
||||
|
||||
// We create the signature for that tx
|
||||
TransactionOutput multiSigOutput = tx.getInput(0).getConnectedOutput();
|
||||
Script multiSigScript = multiSigOutput.getScriptPubKey();
|
||||
Sha256Hash sigHash = tx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
|
||||
ECKey.ECDSASignature offererSignature = getTradingKey().sign(sigHash);
|
||||
ECKey.ECDSASignature offererSignature = getAddressInfoByTradeID(tradeID).getKey().sign(sigHash);
|
||||
|
||||
TransactionSignature offererTxSig = new TransactionSignature(offererSignature, Transaction.SigHash.ALL, false);
|
||||
Script inputScript = ScriptBuilder.createMultiSigInputScript(ImmutableList.of(offererTxSig));
|
||||
@ -773,6 +898,7 @@ public class WalletFacade
|
||||
BigInteger offererPaybackAmount,
|
||||
BigInteger takerPaybackAmount,
|
||||
String offererAddress,
|
||||
String tradeID,
|
||||
FutureCallback<Transaction> callback) throws InsufficientMoneyException, AddressFormatException
|
||||
{
|
||||
log.debug("takerSignsAndSendsTx");
|
||||
@ -780,13 +906,13 @@ public class WalletFacade
|
||||
log.trace("depositTxAsHex=" + depositTxAsHex);
|
||||
log.trace("offererSignatureR=" + offererSignatureR);
|
||||
log.trace("offererSignatureS=" + offererSignatureS);
|
||||
log.trace("offererPaybackAmount=" + Utils.bitcoinValueToFriendlyString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + Utils.bitcoinValueToFriendlyString(takerPaybackAmount));
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.btcToString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.btcToString(takerPaybackAmount));
|
||||
log.trace("offererAddress=" + offererAddress);
|
||||
log.trace("callback=" + callback.toString());
|
||||
|
||||
// We create the payout tx
|
||||
Transaction tx = createPayoutTx(depositTxAsHex, offererPaybackAmount, takerPaybackAmount, offererAddress, getTradingAddress());
|
||||
Transaction tx = createPayoutTx(depositTxAsHex, offererPaybackAmount, takerPaybackAmount, offererAddress, getAddressInfoByTradeID(tradeID).getAddressString());
|
||||
|
||||
// We sign that tx with our key and apply the signature form the offerer
|
||||
TransactionOutput multiSigOutput = tx.getInput(0).getConnectedOutput();
|
||||
@ -794,7 +920,7 @@ public class WalletFacade
|
||||
Sha256Hash sigHash = tx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
|
||||
log.trace("sigHash=" + sigHash.toString());
|
||||
|
||||
ECKey.ECDSASignature takerSignature = getTradingKey().sign(sigHash);
|
||||
ECKey.ECDSASignature takerSignature = getAddressInfoByTradeID(tradeID).getKey().sign(sigHash);
|
||||
TransactionSignature takerTxSig = new TransactionSignature(takerSignature, Transaction.SigHash.ALL, false);
|
||||
|
||||
ECKey.ECDSASignature offererSignature = new ECKey.ECDSASignature(new BigInteger(offererSignatureR), new BigInteger(offererSignatureS));
|
||||
@ -846,8 +972,8 @@ public class WalletFacade
|
||||
log.trace("createPayoutTx");
|
||||
log.trace("inputs: ");
|
||||
log.trace("depositTxAsHex=" + depositTxAsHex);
|
||||
log.trace("offererPaybackAmount=" + Utils.bitcoinValueToFriendlyString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + Utils.bitcoinValueToFriendlyString(takerPaybackAmount));
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.btcToString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.btcToString(takerPaybackAmount));
|
||||
log.trace("offererAddress=" + offererAddress);
|
||||
log.trace("takerAddress=" + takerAddress);
|
||||
|
||||
@ -865,7 +991,7 @@ public class WalletFacade
|
||||
{
|
||||
for (TransactionInput input : tx.getInputs())
|
||||
if (input.getConnectedOutput() != null)
|
||||
log.trace(tracePrefix + ": " + Utils.bitcoinValueToFriendlyString(input.getConnectedOutput().getValue()));
|
||||
log.trace(tracePrefix + ": " + BtcFormatter.btcToString(input.getConnectedOutput().getValue()));
|
||||
else
|
||||
log.trace(tracePrefix + ": " + "Transaction already has inputs but we don't have the connected outputs, so we don't know the value.");
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import com.google.inject.name.Named;
|
||||
import com.google.inject.name.Names;
|
||||
import io.bitsquare.btc.BitSquareWalletAppKit;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
@ -39,6 +40,8 @@ public class BitSquareModule extends AbstractModule
|
||||
|
||||
bind(CryptoFacade.class).asEagerSingleton();
|
||||
bind(WalletFacade.class).asEagerSingleton();
|
||||
bind(FeePolicy.class).asEagerSingleton();
|
||||
|
||||
bind(BlockChainFacade.class).asEagerSingleton();
|
||||
bind(MessageFacade.class).asEagerSingleton();
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
package io.bitsquare.gui;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.bitcoin.core.ECKey;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.bitcoin.core.Wallet;
|
||||
import com.google.bitcoin.core.WalletEventListener;
|
||||
import com.google.bitcoin.script.Script;
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
@ -123,8 +126,8 @@ public class MainController implements Initializable, NavigationController
|
||||
|
||||
//homeButton.fire();
|
||||
//settingsButton.fire();
|
||||
fundsButton.fire();
|
||||
// sellButton.fire();
|
||||
//fundsButton.fire();
|
||||
sellButton.fire();
|
||||
// ordersButton.fire();
|
||||
// homeButton.fire();
|
||||
// msgButton.fire();
|
||||
@ -334,31 +337,31 @@ public class MainController implements Initializable, NavigationController
|
||||
vBox.getChildren().setAll(hBox, titleLabel);
|
||||
parent.getChildren().add(vBox);
|
||||
|
||||
balanceTextField.setText(Utils.bitcoinValueToFriendlyString(walletFacade.getWalletBalance()));
|
||||
balanceTextField.setText(BtcFormatter.btcToString(walletFacade.getWalletBalance()));
|
||||
walletFacade.getWallet().addEventListener(new WalletEventListener()
|
||||
{
|
||||
@Override
|
||||
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
||||
{
|
||||
balanceTextField.setText(Utils.bitcoinValueToFriendlyString(newBalance));
|
||||
balanceTextField.setText(BtcFormatter.btcToString(newBalance));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
|
||||
{
|
||||
balanceTextField.setText(Utils.bitcoinValueToFriendlyString(walletFacade.getWallet().getBalance()));
|
||||
balanceTextField.setText(BtcFormatter.btcToString(walletFacade.getWallet().getBalance()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
||||
{
|
||||
balanceTextField.setText(Utils.bitcoinValueToFriendlyString(newBalance));
|
||||
balanceTextField.setText(BtcFormatter.btcToString(newBalance));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReorganize(Wallet wallet)
|
||||
{
|
||||
balanceTextField.setText(Utils.bitcoinValueToFriendlyString(walletFacade.getWallet().getBalance()));
|
||||
balanceTextField.setText(BtcFormatter.btcToString(walletFacade.getWallet().getBalance()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -371,8 +371,8 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
});
|
||||
|
||||
confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, balanceTextField, progressIndicator);
|
||||
paymentDoneButton.setDisable(walletFacade.getCollateralBalance().compareTo(BigInteger.ZERO) == 0);
|
||||
log.debug("getCollateralBalance " + walletFacade.getCollateralBalance().toString());
|
||||
paymentDoneButton.setDisable(walletFacade.getArbitratorDepositBalance().compareTo(BigInteger.ZERO) == 0);
|
||||
log.debug("getArbitratorDepositBalance " + walletFacade.getArbitratorDepositBalance().toString());
|
||||
walletFacade.getWallet().addEventListener(new WalletEventListener()
|
||||
{
|
||||
@Override
|
||||
@ -464,7 +464,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
BitSquareValidator.resetTextFields(hasDoubleValueTextFields);
|
||||
BitSquareValidator.textFieldsHasDoubleValue(hasDoubleValueTextFields);
|
||||
|
||||
String pubKeyAsHex = walletFacade.getNewArbitratorAddressInfo().getPubKeyAsHexString();
|
||||
String pubKeyAsHex = walletFacade.getArbitratorDepositAddressInfo().getPubKeyAsHexString();
|
||||
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey());
|
||||
String name = nameTextField.getText();
|
||||
|
||||
|
@ -5,6 +5,9 @@ import javafx.scene.layout.Pane;
|
||||
|
||||
public class HSpacer extends Pane
|
||||
{
|
||||
public HSpacer()
|
||||
{
|
||||
}
|
||||
|
||||
public HSpacer(double width)
|
||||
{
|
||||
|
@ -4,6 +4,10 @@ import javafx.scene.control.ScrollPane;
|
||||
|
||||
public class NoFocusScrollPane extends ScrollPane
|
||||
{
|
||||
public NoFocusScrollPane()
|
||||
{
|
||||
}
|
||||
|
||||
public void requestFocus()
|
||||
{
|
||||
// prevent focus
|
||||
|
@ -5,6 +5,9 @@ import javafx.scene.layout.Pane;
|
||||
|
||||
public class VSpacer extends Pane
|
||||
{
|
||||
public VSpacer()
|
||||
{
|
||||
}
|
||||
|
||||
public VSpacer(double height)
|
||||
{
|
||||
|
@ -1,11 +1,11 @@
|
||||
package io.bitsquare.gui.funds;
|
||||
|
||||
import com.google.bitcoin.core.TransactionConfidence;
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import com.google.inject.Inject;
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
import io.bitsquare.btc.AddressInfo;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.btc.listeners.ConfidenceListener;
|
||||
@ -31,7 +31,6 @@ import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
||||
public class FundsController implements Initializable, ChildController
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(FundsController.class);
|
||||
@ -105,9 +104,9 @@ public class FundsController implements Initializable, ChildController
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@FXML
|
||||
public void onAddNewAddress(ActionEvent actionEvent)
|
||||
public void onAddNewTradeAddress(ActionEvent actionEvent)
|
||||
{
|
||||
AddressInfo addressInfo = walletFacade.getNewAddressInfo("New address");
|
||||
AddressInfo addressInfo = walletFacade.getNewTradeAddressInfo();
|
||||
addressList.add(new AddressListItem(addressInfo.getLabel(), addressInfo.getAddress(), false));
|
||||
}
|
||||
|
||||
@ -147,7 +146,7 @@ public class FundsController implements Initializable, ChildController
|
||||
}
|
||||
});
|
||||
|
||||
updateBalance(walletFacade.getBalance(item.getAddress()), balanceLabel);
|
||||
updateBalance(walletFacade.getBalanceForAddress(item.getAddress()), balanceLabel);
|
||||
setGraphic(balanceLabel);
|
||||
}
|
||||
else
|
||||
@ -243,7 +242,7 @@ public class FundsController implements Initializable, ChildController
|
||||
}
|
||||
});
|
||||
|
||||
updateConfidence(walletFacade.getConfidence(item.getAddress()), progressIndicator, tooltip);
|
||||
updateConfidence(walletFacade.getConfidenceForAddress(item.getAddress()), progressIndicator, tooltip);
|
||||
setGraphic(progressIndicator);
|
||||
}
|
||||
else
|
||||
@ -262,7 +261,7 @@ public class FundsController implements Initializable, ChildController
|
||||
private void updateBalance(BigInteger balance, Label balanceLabel)
|
||||
{
|
||||
if (balance != null)
|
||||
balanceLabel.setText(Utils.bitcoinValueToFriendlyString(balance));
|
||||
balanceLabel.setText(BtcFormatter.btcToString(balance));
|
||||
}
|
||||
|
||||
private void updateConfidence(TransactionConfidence confidence, ConfidenceProgressIndicator progressIndicator, Tooltip tooltip)
|
||||
|
@ -4,7 +4,7 @@
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.control.cell.PropertyValueFactory?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<AnchorPane prefHeight="600.0" prefWidth="800.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
||||
<AnchorPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
||||
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.bitsquare.gui.funds.FundsController">
|
||||
|
||||
<TabPane fx:id="tabPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
@ -14,7 +14,7 @@
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
||||
</padding>
|
||||
<TableView fx:id="addressesTable" id="orderbook-table">
|
||||
<TableView fx:id="addressesTable" id="orderbook-table" VBox.vgrow="ALWAYS">
|
||||
<columns>
|
||||
<TableColumn text="Label" fx:id="labelColumn" minWidth="100" sortable="false">
|
||||
<cellValueFactory>
|
||||
@ -29,11 +29,10 @@
|
||||
<TableColumn text="Balance" fx:id="balanceColumn" minWidth="50" sortable="false"/>
|
||||
<TableColumn text="Copy" fx:id="copyColumn" minWidth="30" sortable="false"/>
|
||||
<TableColumn text="Status" fx:id="confidenceColumn" minWidth="30" sortable="false"/>
|
||||
|
||||
</columns>
|
||||
</TableView>
|
||||
|
||||
<Button fx:id="addNewAddressButton" text="Add new address" onAction="#onAddNewAddress"/>
|
||||
<Button fx:id="addNewAddressButton" text="Add new address" onAction="#onAddNewTradeAddress"/>
|
||||
</VBox>
|
||||
</Tab>
|
||||
|
||||
|
@ -2,11 +2,10 @@ package io.bitsquare.gui.market.createOffer;
|
||||
|
||||
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 com.google.inject.Inject;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.btc.Fees;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.gui.ChildController;
|
||||
import io.bitsquare.gui.NavigationController;
|
||||
@ -103,7 +102,8 @@ public class CreateOfferController implements Initializable, ChildController
|
||||
|
||||
|
||||
//TODO
|
||||
amountTextField.setText("" + (int) (new Random().nextDouble() * 100 / 10 + 1));
|
||||
//amountTextField.setText("" + (int) (new Random().nextDouble() * 100 / 10 + 1));
|
||||
amountTextField.setText("1");
|
||||
priceTextField.setText("" + (int) (499 - new Random().nextDouble() * 1000 / 100));
|
||||
minAmountTextField.setText("0,1");
|
||||
collateralTextField.setText("10");
|
||||
@ -117,7 +117,6 @@ public class CreateOfferController implements Initializable, ChildController
|
||||
updateVolume();
|
||||
}
|
||||
});
|
||||
|
||||
priceTextField.textProperty().addListener(new ChangeListener<String>()
|
||||
{
|
||||
@Override
|
||||
@ -141,7 +140,7 @@ public class CreateOfferController implements Initializable, ChildController
|
||||
bankAccountCountyTextField.setText(user.getCurrentBankAccount().getCountry().getName());
|
||||
acceptedCountriesTextField.setText(BitSquareFormatter.countryLocalesToString(settings.getAcceptedCountries()));
|
||||
acceptedLanguagesTextField.setText(BitSquareFormatter.languageLocalesToString(settings.getAcceptedLanguageLocales()));
|
||||
feeLabel.setText(Utils.bitcoinValueToFriendlyString(Fees.OFFER_CREATION_FEE));
|
||||
feeLabel.setText(BtcFormatter.btcToString(FeePolicy.CREATE_OFFER_FEE));
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
<Label text="Collateral (%):" GridPane.rowIndex="3"/>
|
||||
<TextField fx:id="collateralTextField" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
|
||||
|
||||
|
||||
<Label id="form-header-text" text="Offer details" GridPane.rowIndex="4">
|
||||
<GridPane.margin>
|
||||
<Insets top="10.0"/>
|
||||
@ -73,7 +72,6 @@
|
||||
</ConfidenceProgressIndicator>
|
||||
<Label fx:id="confirmationLabel" text="Checking confirmations..." visible="false" GridPane.columnIndex="3" GridPane.rowIndex="12"/>
|
||||
|
||||
|
||||
<Button fx:id="closeButton" visible="false" defaultButton="true" onAction="#onClose" text="Close" GridPane.columnIndex="1" GridPane.rowIndex="13"/>
|
||||
|
||||
</children>
|
||||
|
@ -1,6 +1,8 @@
|
||||
package io.bitsquare.gui.market.orderbook;
|
||||
|
||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.bank.BankAccountTypeInfo;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
@ -109,6 +111,67 @@ public class OrderBookController implements Initializable, ChildController
|
||||
// Interface implementation: Initializable
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private boolean isRegistered()
|
||||
{
|
||||
if (user.getAccountID() == null)
|
||||
{
|
||||
Dialogs.CommandLink settingsCommandLink = new Dialogs.CommandLink("Open settings", "You need to configure your settings before you can actively trade.");
|
||||
Dialogs.CommandLink depositFeeCommandLink = new Dialogs.CommandLink("Deposit funds", "You need to pay the registration fee before you can actively trade. That is needed as prevention against fraud.");
|
||||
Dialogs.CommandLink sendRegistrationCommandLink = new Dialogs.CommandLink("Publish registration", "When settings are configured and the fee deposit is done your registration transaction will be published to the Bitcoin \nnetwork.");
|
||||
List<Dialogs.CommandLink> commandLinks = Arrays.asList(settingsCommandLink, depositFeeCommandLink, sendRegistrationCommandLink);
|
||||
|
||||
boolean settingsValid = settings.getAcceptedLanguageLocales().size() > 0;
|
||||
settingsValid &= settings.getAcceptedCountries().size() > 0;
|
||||
settingsValid &= settings.getAcceptedArbitrators().size() > 0;
|
||||
settingsValid &= user.getCurrentBankAccount() != null;
|
||||
|
||||
boolean registrationFeeDeposited = walletFacade.getRegistrationBalance().compareTo(BigInteger.ZERO) > 0;
|
||||
int selectedIndex = settingsValid ? (registrationFeeDeposited ? 2 : 1) : 0;
|
||||
|
||||
Action registrationMissingAction = Popups.openRegistrationMissingPopup("Registration missing", "Please follow these steps:", "You need to register before you can place an offer.", commandLinks, selectedIndex);
|
||||
if (registrationMissingAction == settingsCommandLink)
|
||||
{
|
||||
MainController.getInstance().navigateToView(NavigationController.SETTINGS);
|
||||
}
|
||||
else if (registrationMissingAction == depositFeeCommandLink)
|
||||
{
|
||||
MainController.getInstance().navigateToView(NavigationController.FUNDS);
|
||||
}
|
||||
else if (registrationMissingAction == sendRegistrationCommandLink)
|
||||
{
|
||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction)
|
||||
{
|
||||
log.debug("payRegistrationFee onSuccess");
|
||||
log.info("payRegistrationFee onSuccess txid:" + transaction.getHashAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.debug("payRegistrationFee onFailure");
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
walletFacade.payRegistrationFee(user.getStringifiedBankAccounts(), callback);
|
||||
user.setAccountID(walletFacade.getRegistrationAddressInfo().toString());
|
||||
user.setMessagePubKeyAsHex(DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey()));
|
||||
|
||||
storage.write(user.getClass().getName(), user);
|
||||
} catch (InsufficientMoneyException e1)
|
||||
{
|
||||
Popups.openErrorPopup("Not enough money available", "There is not enough money available. Please pay in first to your wallet.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb)
|
||||
{
|
||||
@ -166,46 +229,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||
});
|
||||
|
||||
createOfferButton.setOnAction(e -> {
|
||||
if (user.getAccountID() == null)
|
||||
{
|
||||
Dialogs.CommandLink settingsCommandLink = new Dialogs.CommandLink("Open settings", "You need to configure your settings before you can actively trade.");
|
||||
Dialogs.CommandLink depositFeeCommandLink = new Dialogs.CommandLink("Deposit funds", "You need to pay the registration fee before you can actively trade. That is needed as prevention against fraud.");
|
||||
Dialogs.CommandLink sendRegistrationCommandLink = new Dialogs.CommandLink("Publish registration", "When settings are configured and the fee deposit is done your registration transaction will be published to the Bitcoin \nnetwork.");
|
||||
List<Dialogs.CommandLink> commandLinks = Arrays.asList(settingsCommandLink, depositFeeCommandLink, sendRegistrationCommandLink);
|
||||
|
||||
boolean settingsValid = settings.getAcceptedLanguageLocales().size() > 0;
|
||||
settingsValid &= settings.getAcceptedCountries().size() > 0;
|
||||
settingsValid &= settings.getAcceptedArbitrators().size() > 0;
|
||||
settingsValid &= user.getCurrentBankAccount() != null;
|
||||
|
||||
boolean registrationFeeDeposited = walletFacade.getRegistrationBalance().compareTo(BigInteger.ZERO) > 0;
|
||||
int selectedIndex = settingsValid ? (registrationFeeDeposited ? 2 : 1) : 0;
|
||||
|
||||
Action registrationMissingAction = Popups.openRegistrationMissingPopup("Registration missing", "Please follow these steps:", "You need to register before you can place an offer.", commandLinks, selectedIndex);
|
||||
if (registrationMissingAction == settingsCommandLink)
|
||||
{
|
||||
MainController.getInstance().navigateToView(NavigationController.SETTINGS);
|
||||
}
|
||||
else if (registrationMissingAction == depositFeeCommandLink)
|
||||
{
|
||||
MainController.getInstance().navigateToView(NavigationController.FUNDS);
|
||||
}
|
||||
else if (registrationMissingAction == sendRegistrationCommandLink)
|
||||
{
|
||||
try
|
||||
{
|
||||
walletFacade.publishRegistrationTxWithExtraData(user.getStringifiedBankAccounts());
|
||||
user.setAccountID(walletFacade.getRegistrationAddressInfo().toString());
|
||||
user.setMessagePubKeyAsHex(DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey()));
|
||||
|
||||
storage.write(user.getClass().getName(), user);
|
||||
} catch (InsufficientMoneyException e1)
|
||||
{
|
||||
Popups.openErrorPopup("Not enough money available", "There is not enough money available. Please pay in first to your wallet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (isRegistered())
|
||||
{
|
||||
ChildController nextController = navigationController.navigateToView(NavigationController.CREATE_OFFER, "Create offer");
|
||||
((CreateOfferController) nextController).setOrderBookFilter(orderBookFilter);
|
||||
@ -262,14 +286,17 @@ public class OrderBookController implements Initializable, ChildController
|
||||
|
||||
private void takeOffer(Offer offer)
|
||||
{
|
||||
String title = offer.getDirection() == Direction.BUY ? "Trade: Sell Bitcoin" : "Trade: Buy Bitcoin";
|
||||
TakerTradeController takerTradeController = (TakerTradeController) navigationController.navigateToView(NavigationController.TAKER_TRADE, title);
|
||||
if (isRegistered())
|
||||
{
|
||||
String title = offer.getDirection() == Direction.BUY ? "Trade: Sell Bitcoin" : "Trade: Buy Bitcoin";
|
||||
TakerTradeController takerTradeController = (TakerTradeController) navigationController.navigateToView(NavigationController.TAKER_TRADE, title);
|
||||
|
||||
BigInteger requestedAmount = offer.getAmount();
|
||||
if (!amount.getText().equals(""))
|
||||
requestedAmount = BtcFormatter.stringValueToSatoshis(amount.getText());
|
||||
BigInteger requestedAmount = offer.getAmount();
|
||||
if (!amount.getText().equals(""))
|
||||
requestedAmount = BtcFormatter.stringValueToSatoshis(amount.getText());
|
||||
|
||||
takerTradeController.initWithData(offer, requestedAmount);
|
||||
takerTradeController.initWithData(offer, requestedAmount);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeOffer(Offer offer)
|
||||
|
@ -1,12 +1,8 @@
|
||||
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;
|
||||
import io.bitsquare.btc.Fees;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.btc.*;
|
||||
import io.bitsquare.gui.ChildController;
|
||||
import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
|
||||
@ -160,7 +156,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
amountTextField.textProperty().addListener(e -> {
|
||||
applyVolume();
|
||||
applyCollateral();
|
||||
totalToPayLabel.setText(getTotalToPay());
|
||||
totalToPayLabel.setText(getTotalToPayAsString());
|
||||
|
||||
});
|
||||
Label amountRangeLabel = new Label("(" + BtcFormatter.formatSatoshis(offer.getMinAmount(), false) + " - " + BtcFormatter.formatSatoshis(offer.getAmount(), false) + ")");
|
||||
@ -170,8 +166,8 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
totalLabel = FormBuilder.addTextField(gridPane, "Total (" + offer.getCurrency() + "):", BitSquareFormatter.formatVolume(getVolume()), ++row);
|
||||
collateralTextField = FormBuilder.addTextField(gridPane, "Collateral (BTC):", "", ++row);
|
||||
applyCollateral();
|
||||
FormBuilder.addTextField(gridPane, "Offer fee (BTC):", Utils.bitcoinValueToFriendlyString(Fees.OFFER_TAKER_FEE.add(Fees.TX_FEE)), ++row);
|
||||
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPay(), ++row);
|
||||
FormBuilder.addTextField(gridPane, "Offer fee (BTC):", BtcFormatter.btcToString(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE)), ++row);
|
||||
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPayAsString(), ++row);
|
||||
|
||||
isOnlineTextField = FormBuilder.addTextField(gridPane, "Online status:", "Checking offerers online status...", ++row);
|
||||
ConfidenceProgressIndicator isOnlineChecker = new ConfidenceProgressIndicator();
|
||||
@ -223,6 +219,19 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
return;
|
||||
}
|
||||
|
||||
// offerId = tradeId
|
||||
// we don't want to create the trade before the balance check
|
||||
AddressInfo addressInfo = walletFacade.getAddressInfoByTradeID(offer.getId());
|
||||
log.debug("balance " + walletFacade.getBalanceForAddress(addressInfo.getAddress()).toString());
|
||||
if (getTotalToPay().compareTo(walletFacade.getBalanceForAddress(addressInfo.getAddress())) > 0)
|
||||
{
|
||||
Popups.openErrorPopup("Insufficient money", "You don't have enough funds for that trade.");
|
||||
return;
|
||||
}
|
||||
|
||||
trade = trading.createTrade(offer);
|
||||
trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText()));
|
||||
|
||||
/* if (!blockChainFacade.verifyAccountRegistration(offer.getAccountID()))
|
||||
{
|
||||
Popups.openErrorPopup("Offerers account ID not valid", "Offerers registration tx is not found in blockchain or does not match the requirements.");
|
||||
@ -259,9 +268,6 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
progressIndicatorHolder.getChildren().addAll(progressIndicator);
|
||||
gridPane.add(progressIndicatorHolder, 1, row);
|
||||
|
||||
trade = trading.createTrade(offer);
|
||||
trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText()));
|
||||
|
||||
takerPaymentProtocol = trading.addTakerPaymentProtocol(trade, new TakerPaymentProtocolListener()
|
||||
{
|
||||
@Override
|
||||
@ -352,7 +358,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
private void releaseBTC(TradeMessage tradeMessage)
|
||||
{
|
||||
processStepBar.next();
|
||||
trading.releaseBTC(trade.getUid(), tradeMessage);
|
||||
trading.releaseBTC(trade.getId(), tradeMessage);
|
||||
|
||||
nextButton.setText("Close");
|
||||
nextButton.setOnAction(e -> close());
|
||||
@ -363,12 +369,12 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
|
||||
String fiatReceived = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()));
|
||||
|
||||
FormBuilder.addTextField(gridPane, "You have sold (BTC):", Utils.bitcoinValueToFriendlyString(trade.getTradeAmount()), ++row);
|
||||
FormBuilder.addTextField(gridPane, "You have sold (BTC):", BtcFormatter.btcToString(trade.getTradeAmount()), ++row);
|
||||
if (takerIsSelling())
|
||||
{
|
||||
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):\"", fiatReceived, ++row);
|
||||
FormBuilder.addTextField(gridPane, "Total fees (take offer fee + tx fee):", Utils.bitcoinValueToFriendlyString(Fees.OFFER_TAKER_FEE.add(Fees.TX_FEE)), ++row);
|
||||
FormBuilder.addTextField(gridPane, "Refunded collateral:", Utils.bitcoinValueToFriendlyString(trade.getCollateralAmount()), ++row);
|
||||
FormBuilder.addTextField(gridPane, "Total fees (take offer fee + tx fee):", BtcFormatter.btcToString(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE)), ++row);
|
||||
FormBuilder.addTextField(gridPane, "Refunded collateral:", BtcFormatter.btcToString(trade.getCollateralAmount()), ++row);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -433,19 +439,31 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
return offer.getPrice() * BitSquareConverter.stringToDouble2(amountTextField.getText());
|
||||
}
|
||||
|
||||
private String getTotalToPay()
|
||||
private String getTotalToPayAsString()
|
||||
{
|
||||
if (takerIsSelling())
|
||||
{
|
||||
return BtcFormatter.formatSatoshis(getAmountInSatoshis().add(Fees.OFFER_TAKER_FEE).add(Transaction.MIN_NONDUST_OUTPUT).add(Fees.TX_FEE).add(getCollateralInSatoshis()), false);
|
||||
return BtcFormatter.formatSatoshis(getTotalToPay(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Fees.TX_FEE).add(getCollateralInSatoshis()), false) + "\n" +
|
||||
return BtcFormatter.formatSatoshis(getTotalToPay(), false) + "\n" +
|
||||
BitSquareFormatter.formatVolume(getVolume(), offer.getCurrency());
|
||||
}
|
||||
}
|
||||
|
||||
private BigInteger getTotalToPay()
|
||||
{
|
||||
if (takerIsSelling())
|
||||
{
|
||||
return getAmountInSatoshis().add(FeePolicy.TAKE_OFFER_FEE).add(Transaction.MIN_NONDUST_OUTPUT).add(FeePolicy.TX_FEE).add(getCollateralInSatoshis());
|
||||
}
|
||||
else
|
||||
{
|
||||
return FeePolicy.TAKE_OFFER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(FeePolicy.TX_FEE).add(getCollateralInSatoshis());
|
||||
}
|
||||
}
|
||||
|
||||
private void applyCollateral()
|
||||
{
|
||||
collateralTextField.setText(BtcFormatter.formatSatoshis(getCollateralInSatoshis(), false));
|
||||
|
@ -1,6 +1,9 @@
|
||||
package io.bitsquare.gui.orders;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.bitcoin.core.ECKey;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
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;
|
||||
@ -8,7 +11,7 @@ import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.bank.BankAccountTypeInfo;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.btc.Fees;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.gui.ChildController;
|
||||
import io.bitsquare.gui.NavigationController;
|
||||
@ -172,7 +175,7 @@ public class OrdersController implements Initializable, ChildController
|
||||
|
||||
public void bankTransferInited(ActionEvent actionEvent)
|
||||
{
|
||||
trading.onBankTransferInited(currentTrade.getUid());
|
||||
trading.onBankTransferInited(currentTrade.getId());
|
||||
bankTransferInitedButton.setDisable(true);
|
||||
}
|
||||
|
||||
@ -311,10 +314,10 @@ public class OrdersController implements Initializable, ChildController
|
||||
|
||||
String fiatPayed = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()));
|
||||
|
||||
bankAccountTypeTextField.setText(Utils.bitcoinValueToFriendlyString(trade.getTradeAmount()));
|
||||
bankAccountTypeTextField.setText(BtcFormatter.btcToString(trade.getTradeAmount()));
|
||||
holderNameTextField.setText(fiatPayed);
|
||||
primaryBankAccountIDTextField.setText(Utils.bitcoinValueToFriendlyString(Fees.OFFER_CREATION_FEE.add(Fees.TX_FEE)));
|
||||
secondaryBankAccountIDTextField.setText(Utils.bitcoinValueToFriendlyString(trade.getCollateralAmount()));
|
||||
primaryBankAccountIDTextField.setText(BtcFormatter.btcToString(FeePolicy.CREATE_OFFER_FEE.add(FeePolicy.TX_FEE)));
|
||||
secondaryBankAccountIDTextField.setText(BtcFormatter.btcToString(trade.getCollateralAmount()));
|
||||
|
||||
holderNameCopyIcon.setVisible(false);
|
||||
primaryBankAccountIDCopyIcon.setVisible(false);
|
||||
|
@ -135,47 +135,52 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||
public void initialize(URL url, ResourceBundle rb)
|
||||
{
|
||||
setupGeneralSettingsScreen();
|
||||
|
||||
initBankAccountScreen();
|
||||
|
||||
addMockArbitrator();
|
||||
}
|
||||
|
||||
private void addMockArbitrator()
|
||||
{
|
||||
String pubKeyAsHex = Utils.bytesToHexString(new ECKey().getPubKey());
|
||||
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey());
|
||||
List<Locale> languages = new ArrayList<>();
|
||||
languages.add(LanguageUtil.getDefaultLanguageLocale());
|
||||
List<Arbitrator.METHODS> arbitrationMethods = new ArrayList<>();
|
||||
arbitrationMethods.add(Arbitrator.METHODS.TLS_NOTARY);
|
||||
List<Arbitrator.ID_VERIFICATIONS> idVerifications = new ArrayList<>();
|
||||
idVerifications.add(Arbitrator.ID_VERIFICATIONS.PASSPORT);
|
||||
idVerifications.add(Arbitrator.ID_VERIFICATIONS.GOV_ID);
|
||||
|
||||
Arbitrator arbitrator = new Arbitrator(pubKeyAsHex,
|
||||
messagePubKeyAsHex,
|
||||
"Manfred Karrer",
|
||||
Arbitrator.ID_TYPE.REAL_LIFE_ID,
|
||||
languages,
|
||||
new Reputation(),
|
||||
1,
|
||||
0.01,
|
||||
0.001,
|
||||
10,
|
||||
0.1,
|
||||
arbitrationMethods,
|
||||
idVerifications,
|
||||
"http://bitsquare.io/",
|
||||
"Bla bla..."
|
||||
);
|
||||
|
||||
try
|
||||
if (settings.getAcceptedArbitrators() == null || settings.getAcceptedArbitrators().size() == 0)
|
||||
{
|
||||
messageFacade.addArbitrator(arbitrator);
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
String pubKeyAsHex = Utils.bytesToHexString(new ECKey().getPubKey());
|
||||
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey());
|
||||
List<Locale> languages = new ArrayList<>();
|
||||
languages.add(LanguageUtil.getDefaultLanguageLocale());
|
||||
List<Arbitrator.METHODS> arbitrationMethods = new ArrayList<>();
|
||||
arbitrationMethods.add(Arbitrator.METHODS.TLS_NOTARY);
|
||||
List<Arbitrator.ID_VERIFICATIONS> idVerifications = new ArrayList<>();
|
||||
idVerifications.add(Arbitrator.ID_VERIFICATIONS.PASSPORT);
|
||||
idVerifications.add(Arbitrator.ID_VERIFICATIONS.GOV_ID);
|
||||
|
||||
Arbitrator arbitrator = new Arbitrator(pubKeyAsHex,
|
||||
messagePubKeyAsHex,
|
||||
"Manfred Karrer",
|
||||
Arbitrator.ID_TYPE.REAL_LIFE_ID,
|
||||
languages,
|
||||
new Reputation(),
|
||||
1,
|
||||
0.01,
|
||||
0.001,
|
||||
10,
|
||||
0.1,
|
||||
arbitrationMethods,
|
||||
idVerifications,
|
||||
"http://bitsquare.io/",
|
||||
"Bla bla..."
|
||||
);
|
||||
|
||||
arbitratorList.add(arbitrator);
|
||||
settings.addAcceptedArbitrator(arbitrator);
|
||||
storage.write(settings.getClass().getName(), settings);
|
||||
|
||||
try
|
||||
{
|
||||
messageFacade.addArbitrator(arbitrator);
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,6 +656,18 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||
{
|
||||
resetBankAccountInput();
|
||||
}
|
||||
|
||||
//TODO
|
||||
bankAccountTypesComboBox.getSelectionModel().selectFirst();
|
||||
bankAccountCurrencyComboBox.getSelectionModel().selectFirst();
|
||||
bankAccountRegionComboBox.getSelectionModel().select(3);
|
||||
bankAccountCountryComboBox.getSelectionModel().select(5);
|
||||
bankAccountTitleTextField.setText("dummy");
|
||||
bankAccountHolderNameTextField.setText("dummy");
|
||||
bankAccountPrimaryIDTextField.setText("dummy");
|
||||
bankAccountSecondaryIDTextField.setText("dummy");
|
||||
if (user.getCurrentBankAccount() == null)
|
||||
onSaveBankAccount(null);
|
||||
}
|
||||
|
||||
private void resetBankAccountInput()
|
||||
@ -798,7 +815,6 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||
bankAccountCountryComboBox.setVisible(true);
|
||||
int countryIndex = bankAccountCountryComboBox.getItems().indexOf(currentCountry);
|
||||
bankAccountCountryComboBox.getSelectionModel().select(countryIndex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package io.bitsquare.gui.util;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.bitcoin.script.Script;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
@ -205,7 +206,7 @@ public class ConfidenceDisplay
|
||||
}
|
||||
|
||||
if (balanceTextField != null)
|
||||
balanceTextField.setText(Utils.bitcoinValueToFriendlyString(balance));
|
||||
balanceTextField.setText(BtcFormatter.btcToString(balance));
|
||||
}
|
||||
|
||||
private void updateConfidence(Transaction tx)
|
||||
|
@ -48,10 +48,7 @@ public class CountryUtil
|
||||
@Override
|
||||
public boolean apply(@Nullable Country country)
|
||||
{
|
||||
if (selectedRegion != null && country != null)
|
||||
return country.getRegion().equals(selectedRegion);
|
||||
else
|
||||
return false;
|
||||
return selectedRegion != null && country != null && country.getRegion().equals(selectedRegion);
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -211,7 +211,7 @@ public class MessageFacade
|
||||
public void addOffer(Offer offer) throws IOException
|
||||
{
|
||||
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
final Number160 contentKey = Number160.createHash(offer.getUID());
|
||||
final Number160 contentKey = Number160.createHash(offer.getId());
|
||||
final Data offerData = new Data(offer);
|
||||
//offerData.setTTLSeconds(5);
|
||||
final FutureDHT addFuture = myPeer.put(locationKey).setData(contentKey, offerData).start();
|
||||
@ -267,7 +267,7 @@ public class MessageFacade
|
||||
public void removeOffer(Offer offer) throws IOException
|
||||
{
|
||||
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
Number160 contentKey = Number160.createHash(offer.getUID());
|
||||
Number160 contentKey = Number160.createHash(offer.getId());
|
||||
log.debug("removeOffer");
|
||||
FutureDHT removeFuture = myPeer.remove(locationKey).setReturnResults().setContentKey(contentKey).start();
|
||||
removeFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
|
@ -11,6 +11,7 @@ public class TradeMessage implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 7916445031849763995L;
|
||||
|
||||
|
||||
private String uid;
|
||||
|
||||
private String takerMessagePubKey;
|
||||
@ -37,7 +38,8 @@ public class TradeMessage implements Serializable
|
||||
private String accountID;
|
||||
private String offererPubKey;
|
||||
private String preparedOffererDepositTxAsHex;
|
||||
|
||||
private long offererTxOutIndex;
|
||||
private long takerTxOutIndex;
|
||||
private String payoutTxAsHex;
|
||||
|
||||
public TradeMessage(TradeMessageType type, String offerUID)
|
||||
@ -60,7 +62,7 @@ public class TradeMessage implements Serializable
|
||||
uid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public TradeMessage(TradeMessageType type, String offerUID, BankAccount bankAccount, String accountID, String offererPubKey, String preparedOffererDepositTxAsHex)
|
||||
public TradeMessage(TradeMessageType type, String offerUID, BankAccount bankAccount, String accountID, String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex)
|
||||
{
|
||||
this.offerUID = offerUID;
|
||||
this.type = type;
|
||||
@ -68,6 +70,7 @@ public class TradeMessage implements Serializable
|
||||
this.accountID = accountID;
|
||||
this.offererPubKey = offererPubKey;
|
||||
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
|
||||
this.offererTxOutIndex = offererTxOutIndex;
|
||||
|
||||
uid = UUID.randomUUID().toString();
|
||||
}
|
||||
@ -81,7 +84,9 @@ public class TradeMessage implements Serializable
|
||||
String txConnOutAsHex,
|
||||
String contractAsJson,
|
||||
String takerContractSignature,
|
||||
String takerPayoutAddress)
|
||||
String takerPayoutAddress,
|
||||
long takerTxOutIndex,
|
||||
long offererTxOutIndex)
|
||||
{
|
||||
this.offerUID = offerUID;
|
||||
this.type = type;
|
||||
@ -94,6 +99,8 @@ public class TradeMessage implements Serializable
|
||||
this.contractAsJson = contractAsJson;
|
||||
this.takerContractSignature = takerContractSignature;
|
||||
this.takerPayoutAddress = takerPayoutAddress;
|
||||
this.takerTxOutIndex = takerTxOutIndex;
|
||||
this.offererTxOutIndex = offererTxOutIndex;
|
||||
|
||||
uid = UUID.randomUUID().toString();
|
||||
}
|
||||
@ -260,4 +267,13 @@ public class TradeMessage implements Serializable
|
||||
return payoutTxAsHex;
|
||||
}
|
||||
|
||||
public long getOffererTxOutIndex()
|
||||
{
|
||||
return offererTxOutIndex;
|
||||
}
|
||||
|
||||
public long getTakerTxOutIndex()
|
||||
{
|
||||
return takerTxOutIndex;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public class Offer implements Serializable
|
||||
private Direction direction;
|
||||
private Currency currency;
|
||||
|
||||
private String uid;
|
||||
private String id;
|
||||
|
||||
private double price;
|
||||
private BigInteger amount;
|
||||
@ -69,7 +69,7 @@ public class Offer implements Serializable
|
||||
this.acceptedCountries = acceptedCountries;
|
||||
this.acceptedLanguageLocales = acceptedLanguageLocales;
|
||||
|
||||
this.uid = UUID.randomUUID().toString();
|
||||
this.id = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
|
||||
@ -92,9 +92,9 @@ public class Offer implements Serializable
|
||||
return messagePubKeyAsHex;
|
||||
}
|
||||
|
||||
public String getUID()
|
||||
public String getId()
|
||||
{
|
||||
return uid;
|
||||
return id;
|
||||
}
|
||||
|
||||
public double getPrice()
|
||||
@ -178,7 +178,7 @@ public class Offer implements Serializable
|
||||
return "Offer{" +
|
||||
"direction=" + direction +
|
||||
", currency=" + currency +
|
||||
", uid='" + uid + '\'' +
|
||||
", uid='" + id + '\'' +
|
||||
", price=" + price +
|
||||
", amount=" + amount +
|
||||
", minAmount=" + minAmount +
|
||||
|
@ -93,9 +93,9 @@ public class Trade implements Serializable
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getUid()
|
||||
public String getId()
|
||||
{
|
||||
return offer.getUID();
|
||||
return offer.getId();
|
||||
}
|
||||
|
||||
public Offer getOffer()
|
||||
|
@ -7,7 +7,6 @@ import com.google.bitcoin.core.Utils;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.Fees;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
@ -99,39 +98,37 @@ public class Trading
|
||||
|
||||
public void placeNewOffer(Offer offer, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
{
|
||||
if (myOffers.containsKey(offer.getUID()))
|
||||
throw new IllegalStateException("offers contains already a offer with the ID " + offer.getUID());
|
||||
if (myOffers.containsKey(offer.getId()))
|
||||
throw new IllegalStateException("offers contains already a offer with the ID " + offer.getId());
|
||||
|
||||
myOffers.put(offer.getUID(), offer);
|
||||
//TODO for testing
|
||||
//storage.write(storageKey + ".offers", myOffers);
|
||||
walletFacade.payOfferFee(Fees.OFFER_CREATION_FEE, callback);
|
||||
myOffers.put(offer.getId(), offer);
|
||||
walletFacade.payCreateOfferFee(callback);
|
||||
}
|
||||
|
||||
public void removeOffer(Offer offer) throws IOException
|
||||
{
|
||||
myOffers.remove(offer.getUID());
|
||||
myOffers.remove(offer.getId());
|
||||
storage.write(storageKey + ".offers", myOffers);
|
||||
}
|
||||
|
||||
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.getId()))
|
||||
throw new IllegalStateException("trades contains already a trade with the ID " + offer.getId());
|
||||
|
||||
Trade trade = new Trade(offer);
|
||||
trades.put(offer.getUID(), trade);
|
||||
trades.put(offer.getId(), trade);
|
||||
//TODO for testing
|
||||
//storage.write(storageKey + ".trades", trades);
|
||||
|
||||
this.newTradeProperty.set(trade.getUid());
|
||||
this.newTradeProperty.set(trade.getId());
|
||||
|
||||
return trade;
|
||||
}
|
||||
|
||||
public void removeTrade(Trade trade) throws IOException
|
||||
{
|
||||
trades.remove(trade.getUid());
|
||||
trades.remove(trade.getId());
|
||||
storage.write(storageKey + ".trades", trades);
|
||||
}
|
||||
|
||||
@ -143,14 +140,14 @@ public class Trading
|
||||
public TakerPaymentProtocol addTakerPaymentProtocol(Trade trade, TakerPaymentProtocolListener listener)
|
||||
{
|
||||
TakerPaymentProtocol takerPaymentProtocol = new TakerPaymentProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
||||
takerPaymentProtocols.put(trade.getUid(), takerPaymentProtocol);
|
||||
takerPaymentProtocols.put(trade.getId(), takerPaymentProtocol);
|
||||
return takerPaymentProtocol;
|
||||
}
|
||||
|
||||
public OffererPaymentProtocol addOffererPaymentProtocol(Trade trade, OffererPaymentProtocolListener listener)
|
||||
{
|
||||
OffererPaymentProtocol offererPaymentProtocol = new OffererPaymentProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
||||
offererPaymentProtocols.put(trade.getUid(), offererPaymentProtocol);
|
||||
offererPaymentProtocols.put(trade.getId(), offererPaymentProtocol);
|
||||
return offererPaymentProtocol;
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ public class OrderBook implements OrderBookListener
|
||||
&& priceResult
|
||||
&& arbitratorResult;
|
||||
|
||||
/*
|
||||
/*
|
||||
log.debug("result = " + result +
|
||||
", currencyResult = " + currencyResult +
|
||||
", countryResult = " + countryResult +
|
||||
@ -241,7 +241,7 @@ public class OrderBook implements OrderBookListener
|
||||
@Override
|
||||
public boolean test(OrderBookListItem orderBookListItem)
|
||||
{
|
||||
return orderBookListItem.getOffer().getUID().equals(offer.getUID());
|
||||
return orderBookListItem.getOffer().getId().equals(offer.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import com.google.bitcoin.core.*;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
@ -140,13 +141,13 @@ public class OffererPaymentProtocol
|
||||
offererPaymentProtocolListener.onProgress(getProgress());
|
||||
|
||||
// 1.3a Send accept take offer message
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.ACCEPT_TAKE_OFFER_REQUEST, trade.getUid());
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.ACCEPT_TAKE_OFFER_REQUEST, trade.getId());
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("1.3 offer already requested REJECT_TAKE_OFFER_REQUEST");
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REJECT_TAKE_OFFER_REQUEST, trade.getUid());
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REJECT_TAKE_OFFER_REQUEST, trade.getId());
|
||||
TradeMessageListener listener = new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
@ -215,7 +216,7 @@ public class OffererPaymentProtocol
|
||||
log.debug("2.5 createDepositTx");
|
||||
|
||||
BigInteger offererInputAmount = trade.getCollateralAmount();
|
||||
String offererPubKey = walletFacade.getPubKeyAsHex();
|
||||
String offererPubKey = walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString();
|
||||
String takerPubKey = requestTradeMessage.getTakerMultiSigPubKey();
|
||||
String arbitratorPubKey = offer.getArbitrator().getPubKeyAsHex();
|
||||
|
||||
@ -225,17 +226,18 @@ public class OffererPaymentProtocol
|
||||
checkNotNull(arbitratorPubKey);
|
||||
|
||||
log.debug("2.5 offererCreatesMSTxAndAddPayment");
|
||||
log.debug("offererInputAmount " + Utils.bitcoinValueToFriendlyString(offererInputAmount));
|
||||
log.debug("offererInputAmount " + BtcFormatter.btcToString(offererInputAmount));
|
||||
log.debug("offerer pubkey " + offererPubKey);
|
||||
log.debug("taker pubkey " + takerPubKey);
|
||||
log.debug("arbitrator pubkey " + arbitratorPubKey);
|
||||
try
|
||||
{
|
||||
Transaction tx = walletFacade.offererCreatesMSTxAndAddPayment(offererInputAmount, offererPubKey, takerPubKey, arbitratorPubKey);
|
||||
Transaction tx = walletFacade.offererCreatesMSTxAndAddPayment(offererInputAmount, offererPubKey, takerPubKey, arbitratorPubKey, trade.getId());
|
||||
preparedOffererDepositTxAsHex = Utils.bytesToHexString(tx.bitcoinSerialize());
|
||||
long offererTxOutIndex = tx.getInput(0).getOutpoint().getIndex();
|
||||
log.debug("2.5 deposit tx created: " + tx);
|
||||
log.debug("2.5 deposit txAsHex: " + preparedOffererDepositTxAsHex);
|
||||
sendDepositTxAndDataForContract(preparedOffererDepositTxAsHex, offererPubKey);
|
||||
sendDepositTxAndDataForContract(preparedOffererDepositTxAsHex, offererPubKey, offererTxOutIndex);
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
log.warn("2.5 InsufficientMoneyException " + e.getMessage());
|
||||
@ -250,7 +252,7 @@ public class OffererPaymentProtocol
|
||||
// Step 2.6
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void sendDepositTxAndDataForContract(String preparedOffererDepositTxAsHex, String offererPubKey)
|
||||
private void sendDepositTxAndDataForContract(String preparedOffererDepositTxAsHex, String offererPubKey, long offererTxOutIndex)
|
||||
{
|
||||
log.debug("2.6 sendDepositTxAndDataForContract");
|
||||
// Send all the requested data
|
||||
@ -280,12 +282,12 @@ public class OffererPaymentProtocol
|
||||
BankAccount bankAccount = user.getBankAccount(offer.getBankAccountUID());
|
||||
String accountID = user.getAccountID();
|
||||
|
||||
checkNotNull(trade.getUid());
|
||||
checkNotNull(trade.getId());
|
||||
checkNotNull(bankAccount);
|
||||
checkNotNull(accountID);
|
||||
checkNotNull(preparedOffererDepositTxAsHex);
|
||||
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKER_DEPOSIT_PAYMENT, trade.getUid(), bankAccount, accountID, offererPubKey, preparedOffererDepositTxAsHex);
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKER_DEPOSIT_PAYMENT, trade.getId(), bankAccount, accountID, offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex);
|
||||
log.debug("2.6 sendTradingMessage");
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
@ -352,13 +354,13 @@ public class OffererPaymentProtocol
|
||||
log.debug("3.3 offerer contract created: " + contract.toString());
|
||||
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
log.debug("3.3 contractAsJson: " + contractAsJson);
|
||||
// log.debug("3.3 contractAsJson: " + contractAsJson);
|
||||
log.debug("3.3 requestTradingMessage.getContractAsJson(): " + requestTradeMessage.getContractAsJson());
|
||||
|
||||
if (contractAsJson.equals(requestTradeMessage.getContractAsJson()))
|
||||
{
|
||||
log.debug("3.3 The 2 contracts as json does match");
|
||||
String signature = cryptoFacade.signContract(walletFacade.getRegistrationKey(), contractAsJson);
|
||||
String signature = cryptoFacade.signContract(walletFacade.getRegistrationAddressInfo().getKey(), contractAsJson);
|
||||
trade.setContract(contract);
|
||||
trade.setContractAsJson(contractAsJson);
|
||||
trade.setContractTakerSignature(signature);
|
||||
@ -407,7 +409,8 @@ public class OffererPaymentProtocol
|
||||
try
|
||||
{
|
||||
log.debug("3.4 offererSignAndSendTx");
|
||||
depositTransaction = walletFacade.offererSignAndPublishTx(preparedOffererDepositTxAsHex, signedTakerDepositTxAsHex, txConnOutAsHex, txScriptSigAsHex, callback);
|
||||
depositTransaction = walletFacade.offererSignAndPublishTx(preparedOffererDepositTxAsHex, signedTakerDepositTxAsHex, txConnOutAsHex, txScriptSigAsHex,
|
||||
requestTradeMessage.getOffererTxOutIndex(), requestTradeMessage.getTakerTxOutIndex(), callback);
|
||||
} catch (Exception e)
|
||||
{
|
||||
log.error("3.4 error at walletFacade.offererSignAndSendTx: " + e.getMessage());
|
||||
@ -440,7 +443,7 @@ public class OffererPaymentProtocol
|
||||
offererPaymentProtocolListener.onFailure("sendDepositTxAndDataForContract onSendTradingMessageFailed");
|
||||
}
|
||||
};
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.DEPOSIT_TX_PUBLISHED, trade.getUid(), Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.DEPOSIT_TX_PUBLISHED, trade.getId(), Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
||||
log.debug("3.5 sendTradingMessage");
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
|
||||
@ -476,10 +479,10 @@ public class OffererPaymentProtocol
|
||||
updateConfirmation(tx.getConfidence());
|
||||
|
||||
//todo just for testing now, dont like to wait so long...
|
||||
/* if (tx.getConfidence().numBroadcastPeers() > 3)
|
||||
/* if (tx.getConfidenceForAddress().numBroadcastPeers() > 3)
|
||||
{
|
||||
onDepositTxConfirmedInBlockchain();
|
||||
transaction.getConfidence().removeEventListener(this);
|
||||
transaction.getConfidenceForAddress().removeEventListener(this);
|
||||
} */
|
||||
|
||||
}
|
||||
@ -555,14 +558,14 @@ public class OffererPaymentProtocol
|
||||
log.debug("depositTransaction.getHashAsString() " + depositTransaction.getHashAsString());
|
||||
log.debug("takerPayoutAddress " + takerPayoutAddress);
|
||||
log.debug("walletFacade.offererCreatesAndSignsPayoutTx");
|
||||
Pair<ECKey.ECDSASignature, String> result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransaction.getHashAsString(), offererPaybackAmount, takerPaybackAmount, takerPayoutAddress);
|
||||
Pair<ECKey.ECDSASignature, String> result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransaction.getHashAsString(), offererPaybackAmount, takerPaybackAmount, takerPayoutAddress, trade.getId());
|
||||
|
||||
ECKey.ECDSASignature offererSignature = result.getKey();
|
||||
String offererSignatureR = offererSignature.r.toString();
|
||||
String offererSignatureS = offererSignature.s.toString();
|
||||
String depositTxAsHex = result.getValue();
|
||||
String offererPayoutAddress = walletFacade.getTradingAddress();
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.BANK_TX_INITED, trade.getUid(),
|
||||
String offererPayoutAddress = walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString();
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.BANK_TX_INITED, trade.getId(),
|
||||
depositTxAsHex,
|
||||
offererSignatureR,
|
||||
offererSignatureS,
|
||||
|
@ -7,7 +7,7 @@ import com.google.bitcoin.core.Utils;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.Fees;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
@ -152,7 +152,7 @@ public class TakerPaymentProtocol
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
|
||||
// Send the take offer request
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKE_OFFER, trade.getUid());
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKE_OFFER, trade.getId());
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
|
||||
@ -190,13 +190,13 @@ public class TakerPaymentProtocol
|
||||
|
||||
private void payOfferFee(Trade trade)
|
||||
{
|
||||
log.debug("2.1 payOfferFee");
|
||||
log.debug("2.1 payTakeOfferFee");
|
||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction)
|
||||
{
|
||||
log.debug("2.1 payOfferFee onSuccess");
|
||||
log.debug("2.1 payTakeOfferFee onSuccess");
|
||||
log.info("sendResult onSuccess txid:" + transaction.getHashAsString());
|
||||
|
||||
// Offer fee payed successfully.
|
||||
@ -211,15 +211,15 @@ public class TakerPaymentProtocol
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.debug("2.1 payOfferFee onFailure");
|
||||
takerPaymentProtocolListener.onFailure("payOfferFee onFailure " + t.getMessage());
|
||||
log.debug("2.1 payTakeOfferFee onFailure");
|
||||
takerPaymentProtocolListener.onFailure("payTakeOfferFee onFailure " + t.getMessage());
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
// Pay the offer fee
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
walletFacade.payOfferFee(Fees.OFFER_TAKER_FEE, callback);
|
||||
walletFacade.payTakeOfferFee(callback);
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
@ -263,10 +263,10 @@ public class TakerPaymentProtocol
|
||||
|
||||
// 2.3. send request for the account details and send fee tx id so offerer can verify that the fee has been paid.
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.TAKE_OFFER_FEE_PAYED,
|
||||
trade.getUid(),
|
||||
trade.getId(),
|
||||
trade.getTradeAmount(),
|
||||
takeOfferFeeTxID,
|
||||
walletFacade.getPubKeyAsHex());
|
||||
walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString());
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
|
||||
@ -343,7 +343,7 @@ public class TakerPaymentProtocol
|
||||
|
||||
log.debug("2.9 contract created: " + contract.toString());
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
String signature = cryptoFacade.signContract(walletFacade.getRegistrationKey(), contractAsJson);
|
||||
String signature = cryptoFacade.signContract(walletFacade.getRegistrationAddressInfo().getKey(), contractAsJson);
|
||||
|
||||
//log.debug("2.9 contractAsJson: " + contractAsJson);
|
||||
log.debug("2.9 contract signature: " + signature);
|
||||
@ -369,7 +369,7 @@ public class TakerPaymentProtocol
|
||||
BigInteger msOutputAmount = trade.getTradeAmount().add(collateralAmount).add(collateralAmount);
|
||||
|
||||
String offererPubKey = requestTradeMessage.getOffererPubKey();
|
||||
String takerPubKey = walletFacade.getPubKeyAsHex();
|
||||
String takerPubKey = walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString();
|
||||
String arbitratorPubKey = offer.getArbitrator().getPubKeyAsHex();
|
||||
String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex();
|
||||
|
||||
@ -381,17 +381,18 @@ public class TakerPaymentProtocol
|
||||
checkNotNull(preparedOffererDepositTxAsHex);
|
||||
|
||||
log.debug("2.10 offererCreatesMSTxAndAddPayment");
|
||||
log.debug("takerAmount " + Utils.bitcoinValueToFriendlyString(takerInputAmount));
|
||||
log.debug("msOutputAmount " + Utils.bitcoinValueToFriendlyString(msOutputAmount));
|
||||
log.debug("takerAmount " + BtcFormatter.btcToString(takerInputAmount));
|
||||
log.debug("msOutputAmount " + BtcFormatter.btcToString(msOutputAmount));
|
||||
log.debug("offerer pubkey " + offererPubKey);
|
||||
log.debug("taker pubkey " + takerPubKey);
|
||||
log.debug("arbitrator pubkey " + arbitratorPubKey);
|
||||
log.debug("preparedOffererDepositTxAsHex " + preparedOffererDepositTxAsHex);
|
||||
try
|
||||
{
|
||||
Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSignTx(takerInputAmount, msOutputAmount, offererPubKey, takerPubKey, arbitratorPubKey, preparedOffererDepositTxAsHex);
|
||||
Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSignTx(takerInputAmount, msOutputAmount, offererPubKey, takerPubKey, arbitratorPubKey, preparedOffererDepositTxAsHex, trade.getId());
|
||||
log.debug("2.10 deposit tx created: " + signedTakerDepositTx);
|
||||
sendSignedTakerDepositTxAsHex(signedTakerDepositTx);
|
||||
long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex();
|
||||
sendSignedTakerDepositTxAsHex(signedTakerDepositTx, takerTxOutIndex, requestTradeMessage.getOffererTxOutIndex());
|
||||
} catch (InterruptedException | AddressFormatException | ExecutionException | InsufficientMoneyException e)
|
||||
{
|
||||
log.error("2.10 error at walletFacade.takerAddPaymentAndSign: " + e.getMessage());
|
||||
@ -403,7 +404,7 @@ public class TakerPaymentProtocol
|
||||
// Step 2.11 Send the tx to the offerer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void sendSignedTakerDepositTxAsHex(Transaction signedTakerDepositTx)
|
||||
private void sendSignedTakerDepositTxAsHex(Transaction signedTakerDepositTx, long takerTxOutIndex, long offererTxOutIndex)
|
||||
{
|
||||
log.debug("2.11 sendSignedTakerDepositTxAsHex");
|
||||
|
||||
@ -437,14 +438,14 @@ public class TakerPaymentProtocol
|
||||
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.getTradingAddress();
|
||||
String payoutAddress = walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString();
|
||||
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(),
|
||||
trade.getId(),
|
||||
bankAccount,
|
||||
accountID,
|
||||
messagePubKey,
|
||||
@ -453,7 +454,10 @@ public class TakerPaymentProtocol
|
||||
txConnOutAsHex,
|
||||
contractAsJson,
|
||||
signature,
|
||||
payoutAddress);
|
||||
payoutAddress,
|
||||
takerTxOutIndex,
|
||||
offererTxOutIndex
|
||||
);
|
||||
|
||||
log.debug("2.11 sendTradingMessage");
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
@ -542,6 +546,7 @@ public class TakerPaymentProtocol
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
offererPayoutAddress,
|
||||
trade.getId(),
|
||||
callback);
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
@ -577,7 +582,7 @@ public class TakerPaymentProtocol
|
||||
}
|
||||
};
|
||||
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.PAYOUT_TX_PUBLISHED, trade.getUid());
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.PAYOUT_TX_PUBLISHED, trade.getId());
|
||||
tradeMessage.setPayoutTxAsHex(payoutTxAsHex);
|
||||
log.debug("3.13 sendTradeMessage PAYOUT_TX_PUBLISHED");
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
|
@ -93,7 +93,8 @@ public class Arbitrator implements Serializable
|
||||
this.webUrl = webUrl;
|
||||
this.description = description;
|
||||
|
||||
UID = pubKeyAsHex;
|
||||
//TODO for mock arbitrator
|
||||
UID = name;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user