mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-21 05:14:31 -04:00
refactoring trade protocol, reformatting
This commit is contained in:
parent
cb4ca6b2a7
commit
fd1f23ea62
95 changed files with 2207 additions and 2621 deletions
13
pom.xml
13
pom.xml
|
@ -198,17 +198,10 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.typesafe.akka</groupId>
|
<groupId>org.jetbrains</groupId>
|
||||||
<artifactId>akka-actor_2.11</artifactId>
|
<artifactId>annotations</artifactId>
|
||||||
<version>2.3.3</version>
|
<version>13.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.netflix.rxjava</groupId>
|
|
||||||
<artifactId>rxjava-core</artifactId>
|
|
||||||
<version>0.5.3</version>
|
|
||||||
</dependency>
|
|
||||||
-->
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<reporting>
|
<reporting>
|
||||||
|
|
|
@ -36,7 +36,9 @@ public class BitSquare extends Application
|
||||||
{
|
{
|
||||||
log.debug("Startup: main");
|
log.debug("Startup: main");
|
||||||
if (args != null && args.length > 0)
|
if (args != null && args.length > 0)
|
||||||
|
{
|
||||||
ID = args[0];
|
ID = args[0];
|
||||||
|
}
|
||||||
|
|
||||||
launch(args);
|
launch(args);
|
||||||
}
|
}
|
||||||
|
@ -73,9 +75,13 @@ public class BitSquare extends Application
|
||||||
settings.updateFromStorage((Settings) storage.read(settings.getClass().getName()));
|
settings.updateFromStorage((Settings) storage.read(settings.getClass().getName()));
|
||||||
|
|
||||||
if (ID.isEmpty())
|
if (ID.isEmpty())
|
||||||
|
{
|
||||||
stage.setTitle("BitSquare");
|
stage.setTitle("BitSquare");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
stage.setTitle("BitSquare (" + ID + ")");
|
stage.setTitle("BitSquare (" + ID + ")");
|
||||||
|
}
|
||||||
|
|
||||||
GuiceFXMLLoader.setInjector(injector);
|
GuiceFXMLLoader.setInjector(injector);
|
||||||
|
|
||||||
|
@ -101,9 +107,11 @@ public class BitSquare extends Application
|
||||||
stage.show();
|
stage.show();
|
||||||
Action response = Popups.openExceptionPopup(e);
|
Action response = Popups.openExceptionPopup(e);
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
|
{
|
||||||
Platform.exit();
|
Platform.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() throws Exception
|
public void stop() throws Exception
|
||||||
|
|
|
@ -16,10 +16,14 @@ class RelayNode
|
||||||
public static void main(String[] args) throws Exception
|
public static void main(String[] args) throws Exception
|
||||||
{
|
{
|
||||||
if (args != null && args.length == 1)
|
if (args != null && args.length == 1)
|
||||||
|
{
|
||||||
INSTANCE(new Integer(args[0]));
|
INSTANCE(new Integer(args[0]));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
INSTANCE(5000);
|
INSTANCE(5000);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void INSTANCE(int port) throws Exception
|
private static void INSTANCE(int port) throws Exception
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,13 +26,7 @@ public class BankAccount implements Serializable
|
||||||
|
|
||||||
private final String accountTitle;
|
private final String accountTitle;
|
||||||
|
|
||||||
public BankAccount(BankAccountType bankAccountType,
|
public BankAccount(BankAccountType bankAccountType, Currency currency, Country country, String accountTitle, String accountHolderName, String accountPrimaryID, String accountSecondaryID)
|
||||||
Currency currency,
|
|
||||||
Country country,
|
|
||||||
String accountTitle,
|
|
||||||
String accountHolderName,
|
|
||||||
String accountPrimaryID,
|
|
||||||
String accountSecondaryID)
|
|
||||||
{
|
{
|
||||||
this.bankAccountType = bankAccountType;
|
this.bankAccountType = bankAccountType;
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
|
@ -53,9 +47,13 @@ public class BankAccount implements Serializable
|
||||||
public boolean equals(Object obj)
|
public boolean equals(Object obj)
|
||||||
{
|
{
|
||||||
if (!(obj instanceof BankAccount))
|
if (!(obj instanceof BankAccount))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (obj == this)
|
if (obj == this)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
final BankAccount other = (BankAccount) obj;
|
final BankAccount other = (BankAccount) obj;
|
||||||
return uid.equals(other.getUid());
|
return uid.equals(other.getUid());
|
||||||
|
|
|
@ -51,18 +51,28 @@ class AddressBasedCoinSelector extends DefaultCoinSelector
|
||||||
TransactionConfidence conf1 = a.getParentTransaction().getConfidence();
|
TransactionConfidence conf1 = a.getParentTransaction().getConfidence();
|
||||||
TransactionConfidence conf2 = b.getParentTransaction().getConfidence();
|
TransactionConfidence conf2 = b.getParentTransaction().getConfidence();
|
||||||
if (conf1.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
if (conf1.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||||
|
{
|
||||||
depth1 = conf1.getDepthInBlocks();
|
depth1 = conf1.getDepthInBlocks();
|
||||||
|
}
|
||||||
if (conf2.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
if (conf2.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||||
|
{
|
||||||
depth2 = conf2.getDepthInBlocks();
|
depth2 = conf2.getDepthInBlocks();
|
||||||
|
}
|
||||||
BigInteger aValue = a.getValue();
|
BigInteger aValue = a.getValue();
|
||||||
BigInteger bValue = b.getValue();
|
BigInteger bValue = b.getValue();
|
||||||
BigInteger aCoinDepth = aValue.multiply(BigInteger.valueOf(depth1));
|
BigInteger aCoinDepth = aValue.multiply(BigInteger.valueOf(depth1));
|
||||||
BigInteger bCoinDepth = bValue.multiply(BigInteger.valueOf(depth2));
|
BigInteger bCoinDepth = bValue.multiply(BigInteger.valueOf(depth2));
|
||||||
int c1 = bCoinDepth.compareTo(aCoinDepth);
|
int c1 = bCoinDepth.compareTo(aCoinDepth);
|
||||||
if (c1 != 0) return c1;
|
if (c1 != 0)
|
||||||
|
{
|
||||||
|
return c1;
|
||||||
|
}
|
||||||
// The "coin*days" destroyed are equal, sort by value alone to get the lowest transaction size.
|
// The "coin*days" destroyed are equal, sort by value alone to get the lowest transaction size.
|
||||||
int c2 = bValue.compareTo(aValue);
|
int c2 = bValue.compareTo(aValue);
|
||||||
if (c2 != 0) return c2;
|
if (c2 != 0)
|
||||||
|
{
|
||||||
|
return c2;
|
||||||
|
}
|
||||||
// They are entirely equivalent (possibly pending) so sort by hash to ensure a total ordering.
|
// They are entirely equivalent (possibly pending) so sort by hash to ensure a total ordering.
|
||||||
BigInteger aHash = a.getParentTransaction().getHash().toBigInteger();
|
BigInteger aHash = a.getParentTransaction().getHash().toBigInteger();
|
||||||
BigInteger bHash = b.getParentTransaction().getHash().toBigInteger();
|
BigInteger bHash = b.getParentTransaction().getHash().toBigInteger();
|
||||||
|
@ -75,8 +85,7 @@ class AddressBasedCoinSelector extends DefaultCoinSelector
|
||||||
// Pick chain-included transactions and transactions that are pending.
|
// Pick chain-included transactions and transactions that are pending.
|
||||||
TransactionConfidence confidence = tx.getConfidence();
|
TransactionConfidence confidence = tx.getConfidence();
|
||||||
TransactionConfidence.ConfidenceType type = confidence.getConfidenceType();
|
TransactionConfidence.ConfidenceType type = confidence.getConfidenceType();
|
||||||
return type.equals(TransactionConfidence.ConfidenceType.BUILDING) ||
|
return type.equals(TransactionConfidence.ConfidenceType.BUILDING) || type.equals(TransactionConfidence.ConfidenceType.PENDING) &&
|
||||||
type.equals(TransactionConfidence.ConfidenceType.PENDING) &&
|
|
||||||
// In regtest mode we expect to have only one peer, so we won't see transactions propagate.
|
// 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
|
// 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());
|
(confidence.numBroadcastPeers() > 1 || tx.getParams() == RegTestParams.get());
|
||||||
|
@ -96,10 +105,14 @@ class AddressBasedCoinSelector extends DefaultCoinSelector
|
||||||
protected boolean shouldSelect(Transaction tx)
|
protected boolean shouldSelect(Transaction tx)
|
||||||
{
|
{
|
||||||
if (includePending)
|
if (includePending)
|
||||||
|
{
|
||||||
return isInBlockChainOrPending(tx);
|
return isInBlockChainOrPending(tx);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return isInBlockChain(tx);
|
return isInBlockChain(tx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected boolean matchesRequiredAddress(TransactionOutput transactionOutput)
|
protected boolean matchesRequiredAddress(TransactionOutput transactionOutput)
|
||||||
|
@ -134,11 +147,16 @@ class AddressBasedCoinSelector extends DefaultCoinSelector
|
||||||
long total = 0;
|
long total = 0;
|
||||||
for (TransactionOutput output : sortedOutputs)
|
for (TransactionOutput output : sortedOutputs)
|
||||||
{
|
{
|
||||||
if (total >= target) break;
|
if (total >= target)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
// Only pick chain-included transactions, or transactions that are ours and pending.
|
// Only pick chain-included transactions, or transactions that are ours and pending.
|
||||||
// Only select outputs from our defined address(es)
|
// Only select outputs from our defined address(es)
|
||||||
if (!shouldSelect(output.getParentTransaction()) || !matchesRequiredAddress(output))
|
if (!shouldSelect(output.getParentTransaction()) || !matchesRequiredAddress(output))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
selected.add(output);
|
selected.add(output);
|
||||||
total += output.getValue().longValue();
|
total += output.getValue().longValue();
|
||||||
|
|
|
@ -63,7 +63,9 @@ public class BitSquareWalletAppKit extends WalletAppKit
|
||||||
vPeerGroup.setBloomFilterFalsePositiveRate(0.001); // 0,1% instead of default 0,05%
|
vPeerGroup.setBloomFilterFalsePositiveRate(0.001); // 0,1% instead of default 0,05%
|
||||||
|
|
||||||
if (this.userAgent != null)
|
if (this.userAgent != null)
|
||||||
|
{
|
||||||
vPeerGroup.setUserAgent(userAgent, version);
|
vPeerGroup.setUserAgent(userAgent, version);
|
||||||
|
}
|
||||||
if (vWalletFile.exists())
|
if (vWalletFile.exists())
|
||||||
{
|
{
|
||||||
walletStream = new FileInputStream(vWalletFile);
|
walletStream = new FileInputStream(vWalletFile);
|
||||||
|
@ -71,20 +73,28 @@ public class BitSquareWalletAppKit extends WalletAppKit
|
||||||
addWalletExtensions(); // All extensions must be present before we deserialize
|
addWalletExtensions(); // All extensions must be present before we deserialize
|
||||||
new WalletProtobufSerializer().readWallet(WalletProtobufSerializer.parseToProto(walletStream), vWallet);
|
new WalletProtobufSerializer().readWallet(WalletProtobufSerializer.parseToProto(walletStream), vWallet);
|
||||||
if (shouldReplayWallet)
|
if (shouldReplayWallet)
|
||||||
|
{
|
||||||
vWallet.clearTransactions(0);
|
vWallet.clearTransactions(0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vWallet = new BitSquareWallet(params);
|
vWallet = new BitSquareWallet(params);
|
||||||
vWallet.addKey(new ECKey());
|
vWallet.addKey(new ECKey());
|
||||||
addWalletExtensions();
|
addWalletExtensions();
|
||||||
}
|
}
|
||||||
if (useAutoSave) vWallet.autosaveToFile(vWalletFile, 1, TimeUnit.SECONDS, null);
|
if (useAutoSave)
|
||||||
|
{
|
||||||
|
vWallet.autosaveToFile(vWalletFile, 1, TimeUnit.SECONDS, null);
|
||||||
|
}
|
||||||
// Set up peer addresses or discovery first, so if wallet extensions try to broadcast a transaction
|
// Set up peer addresses or discovery first, so if wallet extensions try to broadcast a transaction
|
||||||
// before we're actually connected the broadcast waits for an appropriate number of connections.
|
// before we're actually connected the broadcast waits for an appropriate number of connections.
|
||||||
if (peerAddresses != null)
|
if (peerAddresses != null)
|
||||||
{
|
{
|
||||||
for (PeerAddress addr : peerAddresses) vPeerGroup.addAddress(addr);
|
for (PeerAddress addr : peerAddresses)
|
||||||
|
{
|
||||||
|
vPeerGroup.addAddress(addr);
|
||||||
|
}
|
||||||
peerAddresses = null;
|
peerAddresses = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -130,13 +140,18 @@ public class BitSquareWalletAppKit extends WalletAppKit
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
} finally
|
} finally
|
||||||
{
|
{
|
||||||
if (walletStream != null) walletStream.close();
|
if (walletStream != null)
|
||||||
|
{
|
||||||
|
walletStream.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void installShutdownHook()
|
private void installShutdownHook()
|
||||||
{
|
{
|
||||||
if (autoStop) Runtime.getRuntime().addShutdownHook(new Thread()
|
if (autoStop)
|
||||||
|
{
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
|
@ -154,3 +169,4 @@ public class BitSquareWalletAppKit extends WalletAppKit
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -124,7 +124,9 @@ public class WalletFacade
|
||||||
//walletAppKit.peerGroup().setMaxConnections(11);
|
//walletAppKit.peerGroup().setMaxConnections(11);
|
||||||
|
|
||||||
if (params == RegTestParams.get())
|
if (params == RegTestParams.get())
|
||||||
|
{
|
||||||
walletAppKit.peerGroup().setMinBroadcastConnections(1);
|
walletAppKit.peerGroup().setMinBroadcastConnections(1);
|
||||||
|
}
|
||||||
/* else
|
/* else
|
||||||
walletAppKit.peerGroup().setMinBroadcastConnections(2); */
|
walletAppKit.peerGroup().setMinBroadcastConnections(2); */
|
||||||
|
|
||||||
|
@ -262,7 +264,9 @@ public class WalletFacade
|
||||||
{
|
{
|
||||||
AddressEntry arbitratorDepositAddressEntry = getAddressInfoByAddressContext(AddressEntry.AddressContext.ARBITRATOR_DEPOSIT);
|
AddressEntry arbitratorDepositAddressEntry = getAddressInfoByAddressContext(AddressEntry.AddressContext.ARBITRATOR_DEPOSIT);
|
||||||
if (arbitratorDepositAddressEntry == null)
|
if (arbitratorDepositAddressEntry == null)
|
||||||
|
{
|
||||||
arbitratorDepositAddressEntry = getNewArbitratorDepositAddressEntry();
|
arbitratorDepositAddressEntry = getNewArbitratorDepositAddressEntry();
|
||||||
|
}
|
||||||
|
|
||||||
return arbitratorDepositAddressEntry;
|
return arbitratorDepositAddressEntry;
|
||||||
}
|
}
|
||||||
|
@ -270,24 +274,38 @@ public class WalletFacade
|
||||||
|
|
||||||
AddressEntry getUnusedTradeAddressInfo()
|
AddressEntry getUnusedTradeAddressInfo()
|
||||||
{
|
{
|
||||||
List<AddressEntry> filteredList = Lists.newArrayList(Collections2.filter(ImmutableList.copyOf(addressEntryList), addressInfo -> (addressInfo != null && addressInfo.getAddressContext().equals(AddressEntry.AddressContext.TRADE) && addressInfo.getTradeId() == null)));
|
List<AddressEntry> filteredList = Lists.newArrayList(Collections2.filter(ImmutableList.copyOf(addressEntryList),
|
||||||
|
addressInfo -> (addressInfo != null && addressInfo.getAddressContext()
|
||||||
|
.equals(AddressEntry.AddressContext.TRADE) && addressInfo
|
||||||
|
.getTradeId() == null)));
|
||||||
|
|
||||||
if (filteredList != null && !filteredList.isEmpty())
|
if (filteredList != null && !filteredList.isEmpty())
|
||||||
|
{
|
||||||
return filteredList.get(0);
|
return filteredList.get(0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return getNewTradeAddressEntry();
|
return getNewTradeAddressEntry();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private AddressEntry getAddressInfoByAddressContext(AddressEntry.AddressContext addressContext)
|
private AddressEntry getAddressInfoByAddressContext(AddressEntry.AddressContext addressContext)
|
||||||
{
|
{
|
||||||
List<AddressEntry> filteredList = Lists.newArrayList(Collections2.filter(ImmutableList.copyOf(addressEntryList), addressInfo -> (addressInfo != null && addressInfo.getAddressContext() != null && addressInfo.getAddressContext().equals(addressContext))));
|
List<AddressEntry> filteredList = Lists.newArrayList(Collections2.filter(ImmutableList.copyOf(addressEntryList),
|
||||||
|
addressInfo -> (addressInfo != null && addressInfo.getAddressContext() != null && addressInfo.getAddressContext()
|
||||||
|
.equals(addressContext)
|
||||||
|
)));
|
||||||
|
|
||||||
if (filteredList != null && !filteredList.isEmpty())
|
if (filteredList != null && !filteredList.isEmpty())
|
||||||
|
{
|
||||||
return filteredList.get(0);
|
return filteredList.get(0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public AddressEntry getAddressInfoByTradeID(String tradeId)
|
public AddressEntry getAddressInfoByTradeID(String tradeId)
|
||||||
|
@ -295,8 +313,10 @@ public class WalletFacade
|
||||||
for (AddressEntry addressEntry : ImmutableList.copyOf(addressEntryList))
|
for (AddressEntry addressEntry : ImmutableList.copyOf(addressEntryList))
|
||||||
{
|
{
|
||||||
if (addressEntry.getTradeId() != null && addressEntry.getTradeId().equals(tradeId))
|
if (addressEntry.getTradeId() != null && addressEntry.getTradeId().equals(tradeId))
|
||||||
|
{
|
||||||
return addressEntry;
|
return addressEntry;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AddressEntry addressEntry = getUnusedTradeAddressInfo();
|
AddressEntry addressEntry = getUnusedTradeAddressInfo();
|
||||||
assert addressEntry != null;
|
assert addressEntry != null;
|
||||||
|
@ -343,8 +363,10 @@ public class WalletFacade
|
||||||
for (AddressEntry addressEntry : addressEntryList)
|
for (AddressEntry addressEntry : addressEntryList)
|
||||||
{
|
{
|
||||||
if (addressEntry.getAddressString().equals(address))
|
if (addressEntry.getAddressString().equals(address))
|
||||||
|
{
|
||||||
return addressEntry;
|
return addressEntry;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,8 +446,10 @@ public class WalletFacade
|
||||||
{
|
{
|
||||||
TransactionOutput transactionOutput = transactionInput.getConnectedOutput();
|
TransactionOutput transactionOutput = transactionInput.getConnectedOutput();
|
||||||
if (transactionOutput != null)
|
if (transactionOutput != null)
|
||||||
|
{
|
||||||
connectedOutputs.add(transactionOutput);
|
connectedOutputs.add(transactionOutput);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<TransactionOutput> mergedOutputs = new ArrayList<>();
|
List<TransactionOutput> mergedOutputs = new ArrayList<>();
|
||||||
mergedOutputs.addAll(transactionOutputs);
|
mergedOutputs.addAll(transactionOutputs);
|
||||||
|
@ -460,7 +484,9 @@ public class WalletFacade
|
||||||
{
|
{
|
||||||
TransactionConfidence transactionConfidence = null;
|
TransactionConfidence transactionConfidence = null;
|
||||||
if (getRegistrationAddressInfo() != null)
|
if (getRegistrationAddressInfo() != null)
|
||||||
|
{
|
||||||
transactionConfidence = getConfidenceForAddress(getRegistrationAddressInfo().getAddress());
|
transactionConfidence = getConfidenceForAddress(getRegistrationAddressInfo().getAddress());
|
||||||
|
}
|
||||||
return transactionConfidence != null && transactionConfidence.getConfidenceType().equals(TransactionConfidence.ConfidenceType.BUILDING);
|
return transactionConfidence != null && transactionConfidence.getConfidenceType().equals(TransactionConfidence.ConfidenceType.BUILDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,9 +523,13 @@ public class WalletFacade
|
||||||
{
|
{
|
||||||
BigInteger balance;
|
BigInteger balance;
|
||||||
if (balanceListener.getAddress() != null)
|
if (balanceListener.getAddress() != null)
|
||||||
|
{
|
||||||
balance = getBalanceForAddress(balanceListener.getAddress());
|
balance = getBalanceForAddress(balanceListener.getAddress());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
balance = getWalletBalance();
|
balance = getWalletBalance();
|
||||||
|
}
|
||||||
|
|
||||||
balanceListener.onBalanceChanged(balance);
|
balanceListener.onBalanceChanged(balance);
|
||||||
}
|
}
|
||||||
|
@ -667,7 +697,11 @@ public class WalletFacade
|
||||||
// 1. step: deposit tx
|
// 1. step: deposit tx
|
||||||
// Offerer creates the 2of3 multiSig deposit tx with his unsigned input and change output
|
// 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, String tradeId) throws InsufficientMoneyException
|
public Transaction offererCreatesMSTxAndAddPayment(BigInteger offererInputAmount,
|
||||||
|
String offererPubKey,
|
||||||
|
String takerPubKey,
|
||||||
|
String arbitratorPubKey,
|
||||||
|
String tradeId) throws InsufficientMoneyException
|
||||||
{
|
{
|
||||||
log.debug("offererCreatesMSTxAndAddPayment");
|
log.debug("offererCreatesMSTxAndAddPayment");
|
||||||
log.trace("inputs: ");
|
log.trace("inputs: ");
|
||||||
|
@ -724,8 +758,7 @@ public class WalletFacade
|
||||||
String takerPubKey,
|
String takerPubKey,
|
||||||
String arbitratorPubKey,
|
String arbitratorPubKey,
|
||||||
String offerersPartialDepositTxAsHex,
|
String offerersPartialDepositTxAsHex,
|
||||||
String tradeId
|
String tradeId) throws InsufficientMoneyException
|
||||||
) throws InsufficientMoneyException
|
|
||||||
{
|
{
|
||||||
log.debug("takerAddPaymentAndSignTx");
|
log.debug("takerAddPaymentAndSignTx");
|
||||||
log.trace("inputs: ");
|
log.trace("inputs: ");
|
||||||
|
@ -782,7 +815,9 @@ public class WalletFacade
|
||||||
// Now we add the inputs and outputs from our temp tx and change the multiSig amount to the correct value
|
// Now we add the inputs and outputs from our temp tx and change the multiSig amount to the correct value
|
||||||
tx.addInput(tempTx.getInput(0));
|
tx.addInput(tempTx.getInput(0));
|
||||||
if (tempTx.getOutputs().size() == 2)
|
if (tempTx.getOutputs().size() == 2)
|
||||||
|
{
|
||||||
tx.addOutput(tempTx.getOutput(1));
|
tx.addOutput(tempTx.getOutput(1));
|
||||||
|
}
|
||||||
|
|
||||||
// We add the btc tx fee to the msOutputAmount and apply the change to the multiSig output
|
// We add the btc tx fee to the msOutputAmount and apply the change to the multiSig output
|
||||||
msOutputAmount = msOutputAmount.add(FeePolicy.TX_FEE);
|
msOutputAmount = msOutputAmount.add(FeePolicy.TX_FEE);
|
||||||
|
@ -791,7 +826,9 @@ public class WalletFacade
|
||||||
// Now we sign our input
|
// Now we sign our input
|
||||||
TransactionInput input = tx.getInput(1);
|
TransactionInput input = tx.getInput(1);
|
||||||
if (input == null || input.getConnectedOutput() == null)
|
if (input == null || input.getConnectedOutput() == null)
|
||||||
|
{
|
||||||
log.error("input or input.getConnectedOutput() is null: " + input);
|
log.error("input or input.getConnectedOutput() is null: " + input);
|
||||||
|
}
|
||||||
|
|
||||||
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
||||||
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
|
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
|
||||||
|
@ -799,11 +836,17 @@ public class WalletFacade
|
||||||
ECKey.ECDSASignature ecSig = sigKey.sign(hash);
|
ECKey.ECDSASignature ecSig = sigKey.sign(hash);
|
||||||
TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false);
|
TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false);
|
||||||
if (scriptPubKey.isSentToRawPubKey())
|
if (scriptPubKey.isSentToRawPubKey())
|
||||||
|
{
|
||||||
input.setScriptSig(ScriptBuilder.createInputScript(txSig));
|
input.setScriptSig(ScriptBuilder.createInputScript(txSig));
|
||||||
|
}
|
||||||
else if (scriptPubKey.isSentToAddress())
|
else if (scriptPubKey.isSentToAddress())
|
||||||
|
{
|
||||||
input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey));
|
input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
|
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 1");
|
log.trace("check if it can be correctly spent for input 1");
|
||||||
input.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false);
|
input.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false);
|
||||||
|
@ -862,7 +905,8 @@ public class WalletFacade
|
||||||
// add input
|
// add input
|
||||||
Transaction offerersFirstTxConnOut = wallet.getTransaction(offerersFirstTx.getInput(0).getOutpoint().getHash()); // pass that around!
|
Transaction offerersFirstTxConnOut = wallet.getTransaction(offerersFirstTx.getInput(0).getOutpoint().getHash()); // pass that around!
|
||||||
TransactionOutPoint offerersFirstTxOutPoint = new TransactionOutPoint(params, offererTxOutIndex, 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 array
|
//TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, offerersFirstTx.getInput(0).getScriptBytes(), offerersFirstTxOutPoint); // pass that around! getScriptBytes =
|
||||||
|
// empty bytes array
|
||||||
TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, new byte[]{}, offerersFirstTxOutPoint); // pass that around! getScriptBytes = empty bytes array
|
TransactionInput offerersFirstTxInput = new TransactionInput(params, tx, new byte[]{}, offerersFirstTxOutPoint); // pass that around! getScriptBytes = empty bytes array
|
||||||
offerersFirstTxInput.setParent(tx);
|
offerersFirstTxInput.setParent(tx);
|
||||||
tx.addInput(offerersFirstTxInput);
|
tx.addInput(offerersFirstTxInput);
|
||||||
|
@ -884,9 +928,13 @@ public class WalletFacade
|
||||||
// add outputs from takers tx, they are already correct
|
// add outputs from takers tx, they are already correct
|
||||||
tx.addOutput(takersSignedTx.getOutput(0));
|
tx.addOutput(takersSignedTx.getOutput(0));
|
||||||
if (takersSignedTx.getOutputs().size() > 1)
|
if (takersSignedTx.getOutputs().size() > 1)
|
||||||
|
{
|
||||||
tx.addOutput(takersSignedTx.getOutput(1));
|
tx.addOutput(takersSignedTx.getOutput(1));
|
||||||
|
}
|
||||||
if (takersSignedTx.getOutputs().size() == 3)
|
if (takersSignedTx.getOutputs().size() == 3)
|
||||||
|
{
|
||||||
tx.addOutput(takersSignedTx.getOutput(2));
|
tx.addOutput(takersSignedTx.getOutput(2));
|
||||||
|
}
|
||||||
|
|
||||||
printInputs("tx", tx);
|
printInputs("tx", tx);
|
||||||
log.trace("tx = " + tx);
|
log.trace("tx = " + tx);
|
||||||
|
@ -895,7 +943,9 @@ public class WalletFacade
|
||||||
// sign the input
|
// sign the input
|
||||||
TransactionInput input = tx.getInput(0);
|
TransactionInput input = tx.getInput(0);
|
||||||
if (input == null || input.getConnectedOutput() == null)
|
if (input == null || input.getConnectedOutput() == null)
|
||||||
|
{
|
||||||
log.error("input or input.getConnectedOutput() is null: " + input);
|
log.error("input or input.getConnectedOutput() is null: " + input);
|
||||||
|
}
|
||||||
|
|
||||||
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
||||||
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
|
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
|
||||||
|
@ -903,11 +953,17 @@ public class WalletFacade
|
||||||
ECKey.ECDSASignature ecSig = sigKey.sign(hash);
|
ECKey.ECDSASignature ecSig = sigKey.sign(hash);
|
||||||
TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false);
|
TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false);
|
||||||
if (scriptPubKey.isSentToRawPubKey())
|
if (scriptPubKey.isSentToRawPubKey())
|
||||||
|
{
|
||||||
input.setScriptSig(ScriptBuilder.createInputScript(txSig));
|
input.setScriptSig(ScriptBuilder.createInputScript(txSig));
|
||||||
|
}
|
||||||
else if (scriptPubKey.isSentToAddress())
|
else if (scriptPubKey.isSentToAddress())
|
||||||
|
{
|
||||||
input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey));
|
input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
|
throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
|
||||||
|
}
|
||||||
|
|
||||||
input.getScriptSig().correctlySpends(tx, 0, scriptPubKey, false);
|
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 0 OK");
|
||||||
|
@ -1089,11 +1145,7 @@ public class WalletFacade
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Transaction createPayoutTx(String depositTxAsHex,
|
private Transaction createPayoutTx(String depositTxAsHex, BigInteger offererPaybackAmount, BigInteger takerPaybackAmount, String offererAddress, String takerAddress) throws AddressFormatException
|
||||||
BigInteger offererPaybackAmount,
|
|
||||||
BigInteger takerPaybackAmount,
|
|
||||||
String offererAddress,
|
|
||||||
String takerAddress) throws AddressFormatException
|
|
||||||
{
|
{
|
||||||
log.trace("createPayoutTx");
|
log.trace("createPayoutTx");
|
||||||
log.trace("inputs: ");
|
log.trace("inputs: ");
|
||||||
|
@ -1116,11 +1168,17 @@ public class WalletFacade
|
||||||
private void printInputs(String tracePrefix, Transaction tx)
|
private void printInputs(String tracePrefix, Transaction tx)
|
||||||
{
|
{
|
||||||
for (TransactionInput input : tx.getInputs())
|
for (TransactionInput input : tx.getInputs())
|
||||||
|
{
|
||||||
if (input.getConnectedOutput() != null)
|
if (input.getConnectedOutput() != null)
|
||||||
|
{
|
||||||
log.trace(tracePrefix + " input value : " + BtcFormatter.formatSatoshis(input.getConnectedOutput().getValue()));
|
log.trace(tracePrefix + " input value : " + BtcFormatter.formatSatoshis(input.getConnectedOutput().getValue()));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
log.trace(tracePrefix + ": " + "Transaction already has inputs but we don't have the connected outputs, so we don't know the value.");
|
log.trace(tracePrefix + ": " + "Transaction already has inputs but we don't have the connected outputs, so we don't know the value.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1153,14 +1211,18 @@ public class WalletFacade
|
||||||
private void onProgressInUserThread(double percent, int blocksSoFar, final Date date)
|
private void onProgressInUserThread(double percent, int blocksSoFar, final Date date)
|
||||||
{
|
{
|
||||||
for (DownloadListener downloadListener : downloadListeners)
|
for (DownloadListener downloadListener : downloadListeners)
|
||||||
|
{
|
||||||
downloadListener.progress(percent);
|
downloadListener.progress(percent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onDoneDownloadInUserThread()
|
private void onDoneDownloadInUserThread()
|
||||||
{
|
{
|
||||||
for (DownloadListener downloadListener : downloadListeners)
|
for (DownloadListener downloadListener : downloadListeners)
|
||||||
|
{
|
||||||
downloadListener.doneDownload();
|
downloadListener.doneDownload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -48,7 +48,9 @@ public class GuiceFXMLLoader extends FXMLLoader
|
||||||
private void setupControllerFactory()
|
private void setupControllerFactory()
|
||||||
{
|
{
|
||||||
if (GuiceFXMLLoader.injector != null)
|
if (GuiceFXMLLoader.injector != null)
|
||||||
|
{
|
||||||
setControllerFactory(new GuiceControllerFactory(GuiceFXMLLoader.injector));
|
setControllerFactory(new GuiceControllerFactory(GuiceFXMLLoader.injector));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,9 @@ public class MainController implements Initializable, NavigationController
|
||||||
private ChildController loadView(NavigationItem navigationItem)
|
private ChildController loadView(NavigationItem navigationItem)
|
||||||
{
|
{
|
||||||
if (childController != null)
|
if (childController != null)
|
||||||
|
{
|
||||||
childController.cleanup();
|
childController.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||||
try
|
try
|
||||||
|
@ -205,7 +207,9 @@ public class MainController implements Initializable, NavigationController
|
||||||
|
|
||||||
NavigationItem selectedNavigationItem = (NavigationItem) storage.read(this, "selectedNavigationItem");
|
NavigationItem selectedNavigationItem = (NavigationItem) storage.read(this, "selectedNavigationItem");
|
||||||
if (selectedNavigationItem == null)
|
if (selectedNavigationItem == null)
|
||||||
|
{
|
||||||
selectedNavigationItem = NavigationItem.HOME;
|
selectedNavigationItem = NavigationItem.HOME;
|
||||||
|
}
|
||||||
|
|
||||||
navigateToView(selectedNavigationItem);
|
navigateToView(selectedNavigationItem);
|
||||||
}
|
}
|
||||||
|
@ -268,7 +272,9 @@ public class MainController implements Initializable, NavigationController
|
||||||
childController = loadView(navigationItem);
|
childController = loadView(navigationItem);
|
||||||
|
|
||||||
if (childController instanceof MarketController)
|
if (childController instanceof MarketController)
|
||||||
|
{
|
||||||
((MarketController) childController).setDirection(navigationItem == NavigationItem.BUY ? Direction.BUY : Direction.SELL);
|
((MarketController) childController).setDirection(navigationItem == NavigationItem.BUY ? Direction.BUY : Direction.SELL);
|
||||||
|
}
|
||||||
|
|
||||||
storage.write(this, "selectedNavigationItem", navigationItem);
|
storage.write(this, "selectedNavigationItem", navigationItem);
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,9 @@ public class ArbitratorOverviewController implements Initializable, ChildControl
|
||||||
public ChildController navigateToView(NavigationItem navigationItem)
|
public ChildController navigateToView(NavigationItem navigationItem)
|
||||||
{
|
{
|
||||||
if (arbitratorProfileController != null)
|
if (arbitratorProfileController != null)
|
||||||
|
{
|
||||||
arbitratorProfileController.cleanup();
|
arbitratorProfileController.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||||
try
|
try
|
||||||
|
|
|
@ -28,8 +28,8 @@ public class ArbitratorProfileController implements Initializable, ChildControll
|
||||||
@FXML
|
@FXML
|
||||||
private Label nameLabel;
|
private Label nameLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private TextField nameTextField, languagesTextField, reputationTextField, maxTradeVolumeTextField, passiveServiceFeeTextField,
|
private TextField nameTextField, languagesTextField, reputationTextField, maxTradeVolumeTextField, passiveServiceFeeTextField, arbitrationFeeTextField, methodsTextField,
|
||||||
arbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField;
|
idVerificationsTextField, webPageTextField;
|
||||||
@FXML
|
@FXML
|
||||||
private TextArea descriptionTextArea;
|
private TextArea descriptionTextArea;
|
||||||
|
|
||||||
|
|
|
@ -79,8 +79,8 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
@FXML
|
@FXML
|
||||||
private ComboBox<Arbitrator.ID_VERIFICATION> idVerificationsComboBox;
|
private ComboBox<Arbitrator.ID_VERIFICATION> idVerificationsComboBox;
|
||||||
@FXML
|
@FXML
|
||||||
private TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField, passiveServiceFeeTextField, minPassiveServiceFeeTextField,
|
private TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField, passiveServiceFeeTextField, minPassiveServiceFeeTextField, arbitrationFeeTextField,
|
||||||
arbitrationFeeTextField, minArbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField, collateralAddressTextField, balanceTextField;
|
minArbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField, collateralAddressTextField, balanceTextField;
|
||||||
@FXML
|
@FXML
|
||||||
private TextArea descriptionTextArea;
|
private TextArea descriptionTextArea;
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -467,7 +467,11 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
BitSquareValidator.textFieldsNotEmptyWithReset(nameTextField, idTypeTextField, languagesTextField, methodsTextField, idVerificationsTextField);
|
BitSquareValidator.textFieldsNotEmptyWithReset(nameTextField, idTypeTextField, languagesTextField, methodsTextField, idVerificationsTextField);
|
||||||
BitSquareValidator.textFieldsHasDoubleValueWithReset(maxTradeVolumeTextField, passiveServiceFeeTextField, minPassiveServiceFeeTextField, arbitrationFeeTextField, minArbitrationFeeTextField);
|
BitSquareValidator.textFieldsHasDoubleValueWithReset(maxTradeVolumeTextField,
|
||||||
|
passiveServiceFeeTextField,
|
||||||
|
minPassiveServiceFeeTextField,
|
||||||
|
arbitrationFeeTextField,
|
||||||
|
minArbitrationFeeTextField);
|
||||||
|
|
||||||
String pubKeyAsHex = walletFacade.getArbitratorDepositAddressInfo().getPubKeyAsHexString();
|
String pubKeyAsHex = walletFacade.getArbitratorDepositAddressInfo().getPubKeyAsHexString();
|
||||||
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey());
|
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey());
|
||||||
|
|
|
@ -42,7 +42,9 @@ public class LazyLoadingTabPane extends TabPane
|
||||||
public void initialize(NavigationController navigationController, Storage storage, String... tabContentFXMLUrls)
|
public void initialize(NavigationController navigationController, Storage storage, String... tabContentFXMLUrls)
|
||||||
{
|
{
|
||||||
if (tabContentFXMLUrls.length == 0)
|
if (tabContentFXMLUrls.length == 0)
|
||||||
|
{
|
||||||
throw new IllegalArgumentException("No tabContentFXMLUrls defined");
|
throw new IllegalArgumentException("No tabContentFXMLUrls defined");
|
||||||
|
}
|
||||||
|
|
||||||
this.tabContentFXMLUrls = tabContentFXMLUrls;
|
this.tabContentFXMLUrls = tabContentFXMLUrls;
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
|
@ -59,8 +61,10 @@ public class LazyLoadingTabPane extends TabPane
|
||||||
Object indexObject = storage.read(storageId);
|
Object indexObject = storage.read(storageId);
|
||||||
log.trace("saved index" + indexObject);
|
log.trace("saved index" + indexObject);
|
||||||
if (indexObject != null)
|
if (indexObject != null)
|
||||||
|
{
|
||||||
selectionModel.select((int) indexObject);
|
selectionModel.select((int) indexObject);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
selectionModel.select(selectedTabIndex);
|
selectionModel.select(selectedTabIndex);
|
||||||
|
@ -72,8 +76,10 @@ public class LazyLoadingTabPane extends TabPane
|
||||||
public void cleanup()
|
public void cleanup()
|
||||||
{
|
{
|
||||||
if (childController != null)
|
if (childController != null)
|
||||||
|
{
|
||||||
childController.cleanup();
|
childController.cleanup();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ChildController navigateToView(String fxmlView)
|
public ChildController navigateToView(String fxmlView)
|
||||||
|
@ -97,7 +103,9 @@ public class LazyLoadingTabPane extends TabPane
|
||||||
if (index < tabContentFXMLUrls.length && index >= 0)
|
if (index < tabContentFXMLUrls.length && index >= 0)
|
||||||
{
|
{
|
||||||
if (childController != null)
|
if (childController != null)
|
||||||
|
{
|
||||||
((Hibernate) childController).sleep();
|
((Hibernate) childController).sleep();
|
||||||
|
}
|
||||||
|
|
||||||
Node view = null;
|
Node view = null;
|
||||||
if (index < views.size())
|
if (index < views.size())
|
||||||
|
|
|
@ -91,8 +91,7 @@ public class ConfidenceProgressIndicator extends Control
|
||||||
* Pseudoclass indicating this is a determinate (i.e., progress can be
|
* Pseudoclass indicating this is a determinate (i.e., progress can be
|
||||||
* determined) progress indicator.
|
* determined) progress indicator.
|
||||||
*/
|
*/
|
||||||
private static final PseudoClass PSEUDO_CLASS_DETERMINATE =
|
private static final PseudoClass PSEUDO_CLASS_DETERMINATE = PseudoClass.getPseudoClass("determinate");
|
||||||
PseudoClass.getPseudoClass("determinate");
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* *
|
* *
|
||||||
* Properties *
|
* Properties *
|
||||||
|
@ -102,8 +101,7 @@ public class ConfidenceProgressIndicator extends Control
|
||||||
* Pseudoclass indicating this is an indeterminate (i.e., progress cannot
|
* Pseudoclass indicating this is an indeterminate (i.e., progress cannot
|
||||||
* be determined) progress indicator.
|
* be determined) progress indicator.
|
||||||
*/
|
*/
|
||||||
private static final PseudoClass PSEUDO_CLASS_INDETERMINATE =
|
private static final PseudoClass PSEUDO_CLASS_INDETERMINATE = PseudoClass.getPseudoClass("indeterminate");
|
||||||
PseudoClass.getPseudoClass("indeterminate");
|
|
||||||
/**
|
/**
|
||||||
* A flag indicating whether it is possible to determine the progress
|
* A flag indicating whether it is possible to determine the progress
|
||||||
* of the ProgressIndicator. Typically indeterminate progress bars are
|
* of the ProgressIndicator. Typically indeterminate progress bars are
|
||||||
|
|
|
@ -88,14 +88,16 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
* The number of segments in the spinner.
|
* The number of segments in the spinner.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private final IntegerProperty indeterminateSegmentCount =
|
private final IntegerProperty indeterminateSegmentCount = new StyleableIntegerProperty(8)
|
||||||
new StyleableIntegerProperty(8)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void invalidated()
|
protected void invalidated()
|
||||||
{
|
{
|
||||||
if (spinner != null) spinner.rebuild();
|
if (spinner != null)
|
||||||
|
{
|
||||||
|
spinner.rebuild();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,7 +130,10 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
@Override
|
@Override
|
||||||
protected void invalidated()
|
protected void invalidated()
|
||||||
{
|
{
|
||||||
if (spinner != null) spinner.setSpinEnabled(get());
|
if (spinner != null)
|
||||||
|
{
|
||||||
|
spinner.setSpinEnabled(get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,24 +163,27 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
* The colour of the progress segment.
|
* The colour of the progress segment.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private final ObjectProperty<Paint> progressColor =
|
private final ObjectProperty<Paint> progressColor = new StyleableObjectProperty<Paint>(null)
|
||||||
new StyleableObjectProperty<Paint>(null)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(Paint newProgressColor)
|
public void set(Paint newProgressColor)
|
||||||
{
|
{
|
||||||
final Paint color = (newProgressColor instanceof Color)
|
final Paint color = (newProgressColor instanceof Color) ? newProgressColor : null;
|
||||||
? newProgressColor
|
|
||||||
: null;
|
|
||||||
super.set(color);
|
super.set(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void invalidated()
|
protected void invalidated()
|
||||||
{
|
{
|
||||||
if (spinner != null) spinner.setFillOverride(get());
|
if (spinner != null)
|
||||||
if (determinateIndicator != null) determinateIndicator.setFillOverride(get());
|
{
|
||||||
|
spinner.setFillOverride(get());
|
||||||
|
}
|
||||||
|
if (determinateIndicator != null)
|
||||||
|
{
|
||||||
|
determinateIndicator.setFillOverride(get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -338,8 +346,7 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void layoutChildren(final double x, final double y,
|
protected void layoutChildren(final double x, final double y, final double w, final double h)
|
||||||
final double w, final double h)
|
|
||||||
{
|
{
|
||||||
if (spinner != null && getSkinnable().isIndeterminate())
|
if (spinner != null && getSkinnable().isIndeterminate())
|
||||||
{
|
{
|
||||||
|
@ -509,9 +516,7 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
final double iRight = snapSize(indicatorInsets.getRight());
|
final double iRight = snapSize(indicatorInsets.getRight());
|
||||||
final double iTop = snapSize(indicatorInsets.getTop());
|
final double iTop = snapSize(indicatorInsets.getTop());
|
||||||
final double iBottom = snapSize(indicatorInsets.getBottom());
|
final double iBottom = snapSize(indicatorInsets.getBottom());
|
||||||
final double progressRadius = snapSize(Math.min(
|
final double progressRadius = snapSize(Math.min(Math.min(radius - iLeft, radius - iRight), Math.min(radius - iTop, radius - iBottom)));
|
||||||
Math.min(radius - iLeft, radius - iRight),
|
|
||||||
Math.min(radius - iTop, radius - iBottom)));
|
|
||||||
|
|
||||||
indicatorCircle.setRadius(radius);
|
indicatorCircle.setRadius(radius);
|
||||||
indicator.setLayoutX(centerX);
|
indicator.setLayoutX(centerX);
|
||||||
|
@ -528,9 +533,7 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
final double pRight = snapSize(progressInsets.getRight());
|
final double pRight = snapSize(progressInsets.getRight());
|
||||||
final double pTop = snapSize(progressInsets.getTop());
|
final double pTop = snapSize(progressInsets.getTop());
|
||||||
final double pBottom = snapSize(progressInsets.getBottom());
|
final double pBottom = snapSize(progressInsets.getBottom());
|
||||||
final double indicatorRadius = snapSize(Math.min(
|
final double indicatorRadius = snapSize(Math.min(Math.min(progressRadius - pLeft, progressRadius - pRight), Math.min(progressRadius - pTop, progressRadius - pBottom)));
|
||||||
Math.min(progressRadius - pLeft, progressRadius - pRight),
|
|
||||||
Math.min(progressRadius - pTop, progressRadius - pBottom)));
|
|
||||||
|
|
||||||
// find size of spare box that fits inside indicator radius
|
// find size of spare box that fits inside indicator radius
|
||||||
double squareBoxHalfWidth = Math.ceil(Math.sqrt((indicatorRadius * indicatorRadius) / 2));
|
double squareBoxHalfWidth = Math.ceil(Math.sqrt((indicatorRadius * indicatorRadius) / 2));
|
||||||
|
@ -680,9 +683,7 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
}
|
}
|
||||||
for (int i = 100; i <= 3900; i += 100)
|
for (int i = 100; i <= 3900; i += 100)
|
||||||
{
|
{
|
||||||
keyFrames.add(
|
keyFrames.add(new KeyFrame(Duration.millis(i), event -> shiftColors()));
|
||||||
new KeyFrame(
|
|
||||||
Duration.millis(i), event -> shiftColors()));
|
|
||||||
}
|
}
|
||||||
indeterminateTimeline.getKeyFrames().setAll(keyFrames);
|
indeterminateTimeline.getKeyFrames().setAll(keyFrames);
|
||||||
}
|
}
|
||||||
|
@ -750,7 +751,10 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
|
|
||||||
private void shiftColors()
|
private void shiftColors()
|
||||||
{
|
{
|
||||||
if (opacities.size() <= 0) return;
|
if (opacities.size() <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
final int segments = skin.indeterminateSegmentCount.get();
|
final int segments = skin.indeterminateSegmentCount.get();
|
||||||
Collections.rotate(opacities, -1);
|
Collections.rotate(opacities, -1);
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
|
@ -834,10 +838,7 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
Region region = (Region) child;
|
Region region = (Region) child;
|
||||||
if (region.getShape() != null)
|
if (region.getShape() != null)
|
||||||
{
|
{
|
||||||
region.resize(
|
region.resize(region.getShape().getLayoutBounds().getMaxX(), region.getShape().getLayoutBounds().getMaxY());
|
||||||
region.getShape().getLayoutBounds().getMaxX(),
|
|
||||||
region.getShape().getLayoutBounds().getMaxY()
|
|
||||||
);
|
|
||||||
region.getTransforms().setAll(new Scale(scale, scale, 0, 0));
|
region.getTransforms().setAll(new Scale(scale, scale, 0, 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -857,17 +858,16 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
{
|
{
|
||||||
public static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
|
public static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
|
||||||
|
|
||||||
private static final CssMetaData<ConfidenceProgressIndicator, Paint> PROGRESS_COLOR =
|
private static final CssMetaData<ConfidenceProgressIndicator, Paint> PROGRESS_COLOR = new CssMetaData<ConfidenceProgressIndicator, Paint>("-fx-progress-color",
|
||||||
new CssMetaData<ConfidenceProgressIndicator, Paint>("-fx-progress-color",
|
PaintConverter.getInstance(),
|
||||||
PaintConverter.getInstance(), null)
|
null)
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSettable(ConfidenceProgressIndicator n)
|
public boolean isSettable(ConfidenceProgressIndicator n)
|
||||||
{
|
{
|
||||||
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin();
|
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin();
|
||||||
return skin.progressColor == null ||
|
return skin.progressColor == null || !skin.progressColor.isBound();
|
||||||
!skin.progressColor.isBound();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -880,9 +880,9 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private static final CssMetaData<ConfidenceProgressIndicator, Number> INDETERMINATE_SEGMENT_COUNT =
|
private static final CssMetaData<ConfidenceProgressIndicator, Number> INDETERMINATE_SEGMENT_COUNT = new CssMetaData<ConfidenceProgressIndicator, Number>("-fx-indeterminate-segment-count",
|
||||||
new CssMetaData<ConfidenceProgressIndicator, Number>("-fx-indeterminate-segment-count",
|
SizeConverter.getInstance(),
|
||||||
SizeConverter.getInstance(), 8)
|
8)
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -895,8 +895,7 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
public boolean isSettable(ConfidenceProgressIndicator n)
|
public boolean isSettable(ConfidenceProgressIndicator n)
|
||||||
{
|
{
|
||||||
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin();
|
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin();
|
||||||
return skin.indeterminateSegmentCount == null ||
|
return skin.indeterminateSegmentCount == null || !skin.indeterminateSegmentCount.isBound();
|
||||||
!skin.indeterminateSegmentCount.isBound();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -908,9 +907,9 @@ public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<Confidence
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final CssMetaData<ConfidenceProgressIndicator, Boolean> SPIN_ENABLED =
|
private static final CssMetaData<ConfidenceProgressIndicator, Boolean> SPIN_ENABLED = new CssMetaData<ConfidenceProgressIndicator, Boolean>("-fx-spin-enabled",
|
||||||
new CssMetaData<ConfidenceProgressIndicator, Boolean>("-fx-spin-enabled",
|
BooleanConverter.getInstance(),
|
||||||
BooleanConverter.getInstance(), Boolean.FALSE)
|
Boolean.FALSE)
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -37,8 +37,10 @@ public class ProcessStepBar<T> extends Control
|
||||||
{
|
{
|
||||||
this.processStepItems = processStepItems;
|
this.processStepItems = processStepItems;
|
||||||
if (getSkin() != null)
|
if (getSkin() != null)
|
||||||
|
{
|
||||||
((ProcessStepBarSkin) getSkin()).dataChanged();
|
((ProcessStepBarSkin) getSkin()).dataChanged();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void next()
|
public void next()
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,7 +52,9 @@ class ProcessStepBarSkin<T> extends BehaviorSkinBase<ProcessStepBar<T>, Behavior
|
||||||
getChildren().add(labelWithBorder);
|
getChildren().add(labelWithBorder);
|
||||||
labelWithBorders.add(labelWithBorder);
|
labelWithBorders.add(labelWithBorder);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
{
|
||||||
currentLabelWithBorder = prevLabelWithBorder = labelWithBorder;
|
currentLabelWithBorder = prevLabelWithBorder = labelWithBorder;
|
||||||
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +90,9 @@ class ProcessStepBarSkin<T> extends BehaviorSkinBase<ProcessStepBar<T>, Behavior
|
||||||
double newHeight = snapSize(node.prefHeight(-1) + 10);
|
double newHeight = snapSize(node.prefHeight(-1) + 10);
|
||||||
|
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
|
{
|
||||||
x = snapPosition(x - ((LabelWithBorder) node).getArrowWidth());
|
x = snapPosition(x - ((LabelWithBorder) node).getArrowWidth());
|
||||||
|
}
|
||||||
|
|
||||||
x = snapPosition(x);
|
x = snapPosition(x);
|
||||||
y = snapPosition(y);
|
y = snapPosition(y);
|
||||||
|
@ -124,15 +128,13 @@ class ProcessStepBarSkin<T> extends BehaviorSkinBase<ProcessStepBar<T>, Behavior
|
||||||
|
|
||||||
this.setShape(createButtonShape());
|
this.setShape(createButtonShape());
|
||||||
|
|
||||||
BorderStroke borderStroke = new BorderStroke(Color.LIGHTGRAY, BorderStrokeStyle.SOLID, null,
|
BorderStroke borderStroke = new BorderStroke(Color.LIGHTGRAY, BorderStrokeStyle.SOLID, null, new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY);
|
||||||
new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY);
|
|
||||||
this.setBorder(new Border(borderStroke));
|
this.setBorder(new Border(borderStroke));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void select()
|
public void select()
|
||||||
{
|
{
|
||||||
BorderStroke borderStroke = new BorderStroke(processStepItem.getColor(), BorderStrokeStyle.SOLID, null,
|
BorderStroke borderStroke = new BorderStroke(processStepItem.getColor(), BorderStrokeStyle.SOLID, null, new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY);
|
||||||
new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY);
|
|
||||||
this.setBorder(new Border(borderStroke));
|
this.setBorder(new Border(borderStroke));
|
||||||
setTextFill(processStepItem.getColor());
|
setTextFill(processStepItem.getColor());
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,10 @@ public class WithdrawalController implements Initializable, ChildController, Hib
|
||||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
||||||
{
|
{
|
||||||
BitSquareValidator.resetTextFields(withdrawFromTextField, withdrawToTextField, amountTextField, changeAddressTextField);
|
BitSquareValidator.resetTextFields(withdrawFromTextField, withdrawToTextField, amountTextField, changeAddressTextField);
|
||||||
if (transaction != null) log.info("onWithdraw onSuccess txid:" + transaction.getHashAsString());
|
if (transaction != null)
|
||||||
|
{
|
||||||
|
log.info("onWithdraw onSuccess txid:" + transaction.getHashAsString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -126,9 +126,13 @@ public class WithdrawalListItem
|
||||||
return "Registration fee";
|
return "Registration fee";
|
||||||
case TRADE:
|
case TRADE:
|
||||||
if (addressEntry.getTradeId() != null)
|
if (addressEntry.getTradeId() != null)
|
||||||
|
{
|
||||||
return "Trade ID: " + addressEntry.getTradeId();
|
return "Trade ID: " + addressEntry.getTradeId();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return "Trade (not used yet)";
|
return "Trade (not used yet)";
|
||||||
|
}
|
||||||
case ARBITRATOR_DEPOSIT:
|
case ARBITRATOR_DEPOSIT:
|
||||||
return "Arbitration deposit";
|
return "Arbitration deposit";
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,9 @@ public class HomeController implements Initializable, ChildController, Navigatio
|
||||||
public ChildController navigateToView(NavigationItem navigationItem)
|
public ChildController navigateToView(NavigationItem navigationItem)
|
||||||
{
|
{
|
||||||
if (arbitratorRegistrationController != null)
|
if (arbitratorRegistrationController != null)
|
||||||
|
{
|
||||||
arbitratorRegistrationController.cleanup();
|
arbitratorRegistrationController.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||||
try
|
try
|
||||||
|
|
|
@ -60,7 +60,9 @@ public class MarketController implements Initializable, NavigationController, Ch
|
||||||
childController.setNavigationController(this);
|
childController.setNavigationController(this);
|
||||||
|
|
||||||
if (childController instanceof OrderBookController)
|
if (childController instanceof OrderBookController)
|
||||||
|
{
|
||||||
orderBookController = (OrderBookController) childController;
|
orderBookController = (OrderBookController) childController;
|
||||||
|
}
|
||||||
|
|
||||||
String tabLabel;
|
String tabLabel;
|
||||||
switch (navigationItem)
|
switch (navigationItem)
|
||||||
|
@ -125,8 +127,10 @@ public class MarketController implements Initializable, NavigationController, Ch
|
||||||
{
|
{
|
||||||
tabPane.getSelectionModel().select(0);
|
tabPane.getSelectionModel().select(0);
|
||||||
if (orderBookController != null)
|
if (orderBookController != null)
|
||||||
|
{
|
||||||
orderBookController.setDirection(direction);
|
orderBookController.setDirection(direction);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,8 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||||
@FXML
|
@FXML
|
||||||
private Button placeOfferButton, closeButton;
|
private Button placeOfferButton, closeButton;
|
||||||
@FXML
|
@FXML
|
||||||
private TextField collateralTextField, minAmountTextField, bankAccountTypeTextField, bankAccountCurrencyTextField, bankAccountCountyTextField,
|
private TextField collateralTextField, minAmountTextField, bankAccountTypeTextField, bankAccountCurrencyTextField, bankAccountCountyTextField, acceptedCountriesTextField,
|
||||||
acceptedCountriesTextField, acceptedLanguagesTextField, feeLabel, txTextField;
|
acceptedLanguagesTextField, feeLabel, txTextField;
|
||||||
@FXML
|
@FXML
|
||||||
private ConfidenceProgressIndicator progressIndicator;
|
private ConfidenceProgressIndicator progressIndicator;
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,8 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Action response = Popups.openErrorPopup("Registration fee not confirmed yet", "The registration fee transaction has not been confirmed yet in the blockchain. Please wait until it has at least 1 confirmation.");
|
Action response = Popups.openErrorPopup("Registration fee not confirmed yet",
|
||||||
|
"The registration fee transaction has not been confirmed yet in the blockchain. Please wait until it has at least 1 confirmation.");
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
{
|
{
|
||||||
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||||
|
@ -229,7 +230,8 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Action response = Popups.openErrorPopup("Missing registration fee", "You have not funded the full registration fee of " + BtcFormatter.formatSatoshis(FeePolicy.ACCOUNT_REGISTRATION_FEE) + " BTC.");
|
Action response = Popups.openErrorPopup("Missing registration fee",
|
||||||
|
"You have not funded the full registration fee of " + BtcFormatter.formatSatoshis(FeePolicy.ACCOUNT_REGISTRATION_FEE) + " BTC.");
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
{
|
{
|
||||||
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||||
|
@ -249,10 +251,17 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
if (selectedIndex >= 0)
|
if (selectedIndex >= 0)
|
||||||
{
|
{
|
||||||
Dialogs.CommandLink settingsCommandLink = new Dialogs.CommandLink("Open settings", "You need to configure your settings before you can actively trade.");
|
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 depositFeeCommandLink = new Dialogs.CommandLink("Deposit funds",
|
||||||
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.");
|
"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);
|
List<Dialogs.CommandLink> commandLinks = Arrays.asList(settingsCommandLink, depositFeeCommandLink, sendRegistrationCommandLink);
|
||||||
Action registrationMissingAction = Popups.openRegistrationMissingPopup("Not registered yet", "Please follow these steps:", "You need to register before you can place an offer.", commandLinks, selectedIndex);
|
Action registrationMissingAction = Popups.openRegistrationMissingPopup("Not registered yet",
|
||||||
|
"Please follow these steps:",
|
||||||
|
"You need to register before you can place an offer.",
|
||||||
|
commandLinks,
|
||||||
|
selectedIndex);
|
||||||
if (registrationMissingAction == settingsCommandLink)
|
if (registrationMissingAction == settingsCommandLink)
|
||||||
{
|
{
|
||||||
MainController.GET_INSTANCE().navigateToView(NavigationItem.SETTINGS);
|
MainController.GET_INSTANCE().navigateToView(NavigationItem.SETTINGS);
|
||||||
|
@ -276,7 +285,10 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
||||||
{
|
{
|
||||||
log.debug("payRegistrationFee onSuccess");
|
log.debug("payRegistrationFee onSuccess");
|
||||||
if (transaction != null) log.info("payRegistrationFee onSuccess tx id:" + transaction.getHashAsString());
|
if (transaction != null)
|
||||||
|
{
|
||||||
|
log.info("payRegistrationFee onSuccess tx id:" + transaction.getHashAsString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -289,8 +301,13 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
walletFacade.payRegistrationFee(user.getStringifiedBankAccounts(), callback);
|
walletFacade.payRegistrationFee(user.getStringifiedBankAccounts(), callback);
|
||||||
if (walletFacade.getRegistrationAddressInfo() != null)
|
if (walletFacade.getRegistrationAddressInfo() != null)
|
||||||
|
{
|
||||||
user.setAccountID(walletFacade.getRegistrationAddressInfo().toString());
|
user.setAccountID(walletFacade.getRegistrationAddressInfo().toString());
|
||||||
if (messageFacade != null && messageFacade.getPubKey() != null) user.setMessagePubKeyAsHex(DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey()));
|
}
|
||||||
|
if (messageFacade != null && messageFacade.getPubKey() != null)
|
||||||
|
{
|
||||||
|
user.setMessagePubKeyAsHex(DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey()));
|
||||||
|
}
|
||||||
|
|
||||||
storage.write(user.getClass().getName(), user);
|
storage.write(user.getClass().getName(), user);
|
||||||
} catch (InsufficientMoneyException e1)
|
} catch (InsufficientMoneyException e1)
|
||||||
|
@ -308,8 +325,10 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
ChildController nextController = navigationController.navigateToView(NavigationItem.CREATE_OFFER);
|
ChildController nextController = navigationController.navigateToView(NavigationItem.CREATE_OFFER);
|
||||||
if (nextController != null)
|
if (nextController != null)
|
||||||
|
{
|
||||||
((CreateOfferController) nextController).setOrderBookFilter(orderBookFilter);
|
((CreateOfferController) nextController).setOrderBookFilter(orderBookFilter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Action response = Popups.openErrorPopup("No funds for a trade", "You have to add some funds before you create a new offer.");
|
Action response = Popups.openErrorPopup("No funds for a trade", "You have to add some funds before you create a new offer.");
|
||||||
|
@ -333,13 +352,19 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
|
|
||||||
BigInteger requestedAmount;
|
BigInteger requestedAmount;
|
||||||
if (!"".equals(amount.getText()))
|
if (!"".equals(amount.getText()))
|
||||||
|
{
|
||||||
requestedAmount = BtcFormatter.stringValueToSatoshis(amount.getText());
|
requestedAmount = BtcFormatter.stringValueToSatoshis(amount.getText());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
requestedAmount = offer.getAmount();
|
requestedAmount = offer.getAmount();
|
||||||
|
}
|
||||||
|
|
||||||
if (takerOfferController != null)
|
if (takerOfferController != null)
|
||||||
|
{
|
||||||
takerOfferController.initWithData(offer, requestedAmount);
|
takerOfferController.initWithData(offer, requestedAmount);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
showRegistrationDialog();
|
showRegistrationDialog();
|
||||||
|
@ -359,16 +384,22 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
orderBookTable.sort();
|
orderBookTable.sort();
|
||||||
|
|
||||||
if (orderBookTable.getItems() != null)
|
if (orderBookTable.getItems() != null)
|
||||||
|
{
|
||||||
createOfferButton.setDefaultButton(orderBookTable.getItems().isEmpty());
|
createOfferButton.setDefaultButton(orderBookTable.getItems().isEmpty());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setupPolling()
|
private void setupPolling()
|
||||||
{
|
{
|
||||||
pollingTimer = Utilities.setInterval(1000, (animationTimer) -> {
|
pollingTimer = Utilities.setInterval(1000, (animationTimer) -> {
|
||||||
if (user.getCurrentBankAccount() != null)
|
if (user.getCurrentBankAccount() != null)
|
||||||
|
{
|
||||||
messageFacade.getDirtyFlag(user.getCurrentBankAccount().getCurrency());
|
messageFacade.getDirtyFlag(user.getCurrentBankAccount().getCurrency());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
messageFacade.getDirtyFlag(CurrencyUtil.getDefaultCurrency());
|
messageFacade.getDirtyFlag(CurrencyUtil.getDefaultCurrency());
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.Trading;
|
import io.bitsquare.trade.Trading;
|
||||||
import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocol;
|
import io.bitsquare.trade.protocol.taker.ProtocolForTakerAsSeller;
|
||||||
import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocolListener;
|
import io.bitsquare.trade.protocol.taker.ProtocolForTakerAsSellerListener;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
@ -53,9 +53,9 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
@FXML
|
@FXML
|
||||||
private ValidatedTextField amountTextField;
|
private ValidatedTextField amountTextField;
|
||||||
@FXML
|
@FXML
|
||||||
private TextField priceTextField, volumeTextField, collateralTextField, feeTextField, totalTextField, bankAccountTypeTextField, countryTextField,
|
private TextField priceTextField, volumeTextField, collateralTextField, feeTextField, totalTextField, bankAccountTypeTextField, countryTextField, arbitratorsTextField,
|
||||||
arbitratorsTextField, supportedLanguagesTextField, supportedCountriesTextField, depositTxIdTextField, summaryPaidTextField, summaryReceivedTextField, summaryFeesTextField,
|
supportedLanguagesTextField, supportedCountriesTextField, depositTxIdTextField, summaryPaidTextField, summaryReceivedTextField, summaryFeesTextField, summaryCollateralTextField,
|
||||||
summaryCollateralTextField, summaryDepositTxIdTextField, summaryPayoutTxIdTextField;
|
summaryDepositTxIdTextField, summaryPayoutTxIdTextField;
|
||||||
@FXML
|
@FXML
|
||||||
private Label infoLabel, headLineLabel;
|
private Label infoLabel, headLineLabel;
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -84,8 +84,10 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
this.requestedAmount = requestedAmount.compareTo(BigInteger.ZERO) == 0 ? offer.getAmount() : requestedAmount;
|
this.requestedAmount = requestedAmount.compareTo(BigInteger.ZERO) == 0 ? offer.getAmount() : requestedAmount;
|
||||||
|
|
||||||
if (amountTextField != null)
|
if (amountTextField != null)
|
||||||
|
{
|
||||||
applyData();
|
applyData();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Interface implementation: Initializable
|
// Interface implementation: Initializable
|
||||||
|
@ -172,7 +174,7 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
takeOfferButton.setDisable(true);
|
takeOfferButton.setDisable(true);
|
||||||
amountTextField.setEditable(false);
|
amountTextField.setEditable(false);
|
||||||
trading.takeOffer(amount, offer, new TakerAsSellerProtocolListener()
|
trading.takeOffer(amount, offer, new ProtocolForTakerAsSellerListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onDepositTxPublished(String depositTxId)
|
public void onDepositTxPublished(String depositTxId)
|
||||||
|
@ -190,8 +192,7 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
setTradeId(tradeId);
|
setTradeId(tradeId);
|
||||||
headLineLabel.setText("Bank transfer inited");
|
headLineLabel.setText("Bank transfer inited");
|
||||||
infoLabel.setText("Check your bank account and continue \n" +
|
infoLabel.setText("Check your bank account and continue \n" + "when you have received the money.");
|
||||||
"when you have received the money.");
|
|
||||||
receivedFiatButton.setDisable(false);
|
receivedFiatButton.setDisable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,20 +209,20 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFault(Throwable throwable, TakerAsSellerProtocol.State state)
|
public void onFault(Throwable throwable, ProtocolForTakerAsSeller.State state)
|
||||||
{
|
{
|
||||||
log.error("Error while executing trade process at state: " + state + " / " + throwable);
|
log.error("Error while executing trade process at state: " + state + " / " + throwable);
|
||||||
Popups.openErrorPopup("Error while executing trade process", "Error while executing trade process at state: " + state + " / " + throwable);
|
Popups.openErrorPopup("Error while executing trade process", "Error while executing trade process at state: " + state + " / " + throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWaitingForPeerResponse(TakerAsSellerProtocol.State state)
|
public void onWaitingForPeerResponse(ProtocolForTakerAsSeller.State state)
|
||||||
{
|
{
|
||||||
log.debug("Waiting for peers response at state " + state);
|
log.debug("Waiting for peers response at state " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCompleted(TakerAsSellerProtocol.State state)
|
public void onCompleted(ProtocolForTakerAsSeller.State state)
|
||||||
{
|
{
|
||||||
log.debug("Trade protocol completed at state " + state);
|
log.debug("Trade protocol completed at state " + state);
|
||||||
}
|
}
|
||||||
|
@ -230,10 +231,10 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
public void onTakeOfferRequestRejected(Trade trade)
|
public void onTakeOfferRequestRejected(Trade trade)
|
||||||
{
|
{
|
||||||
log.error("Take offer request rejected");
|
log.error("Take offer request rejected");
|
||||||
Popups.openErrorPopup("Take offer request rejected", "Your take offer request has been rejected. It might be that the offerer got another request shortly before your request arrived.");
|
Popups.openErrorPopup("Take offer request rejected",
|
||||||
|
"Your take offer request has been rejected. It might be that the offerer got another request shortly before your request arrived.");
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,9 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (offer.getArbitrator() != null && offer.getArbitrator().getWebUrl() != null)
|
if (offer.getArbitrator() != null && offer.getArbitrator().getWebUrl() != null)
|
||||||
|
{
|
||||||
Utilities.openURL(offer.getArbitrator().getWebUrl());
|
Utilities.openURL(offer.getArbitrator().getWebUrl());
|
||||||
|
}
|
||||||
} catch (Exception e1)
|
} catch (Exception e1)
|
||||||
{
|
{
|
||||||
log.warn(e1.toString());
|
log.warn(e1.toString());
|
||||||
|
@ -230,13 +232,13 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
trade = trading.createTrade(offer);
|
trade = trading.createTrade(offer);
|
||||||
trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText()));
|
trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText()));
|
||||||
|
|
||||||
/* if (!blockChainFacade.verifyAccountRegistration(offer.getAccountId()))
|
/* if (!blockChainFacade.verifyAccountRegistration(offer.getTakerAccountId()))
|
||||||
{
|
{
|
||||||
Popups.openErrorPopup("Offerers account ID not valid", "Offerers registration tx is not found in blockchain or does not match the requirements.");
|
Popups.openErrorPopup("Offerers account ID not valid", "Offerers registration tx is not found in blockchain or does not match the requirements.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockChainFacade.isAccountIDBlacklisted(offer.getAccountId()))
|
if (blockChainFacade.isAccountIDBlacklisted(offer.getTakerAccountId()))
|
||||||
{
|
{
|
||||||
Popups.openErrorPopup("Offerers account ID is blacklisted", "Offerers account ID is blacklisted.");
|
Popups.openErrorPopup("Offerers account ID is blacklisted", "Offerers account ID is blacklisted.");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -155,7 +155,9 @@ public class PendingTradeController implements Initializable, ChildController, H
|
||||||
trading.getNewTradeProperty().addListener((observableValue, oldTradeId, newTradeId) -> {
|
trading.getNewTradeProperty().addListener((observableValue, oldTradeId, newTradeId) -> {
|
||||||
Trade newTrade = trading.getTrade(newTradeId);
|
Trade newTrade = trading.getTrade(newTradeId);
|
||||||
if (newTrade != null)
|
if (newTrade != null)
|
||||||
|
{
|
||||||
tradeItems.add(new PendingTradesListItem(newTrade));
|
tradeItems.add(new PendingTradesListItem(newTrade));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
initCopyIcons();
|
initCopyIcons();
|
||||||
|
@ -163,7 +165,9 @@ public class PendingTradeController implements Initializable, ChildController, H
|
||||||
// select
|
// select
|
||||||
Optional<PendingTradesListItem> currentTradeItemOptional = tradeItems.stream().filter((e) -> e.getTrade().getId().equals(trading.getPendingTrade().getId())).findFirst();
|
Optional<PendingTradesListItem> currentTradeItemOptional = tradeItems.stream().filter((e) -> e.getTrade().getId().equals(trading.getPendingTrade().getId())).findFirst();
|
||||||
if (currentTradeItemOptional.isPresent())
|
if (currentTradeItemOptional.isPresent())
|
||||||
|
{
|
||||||
openTradesTable.getSelectionModel().select(currentTradeItemOptional.get());
|
openTradesTable.getSelectionModel().select(currentTradeItemOptional.get());
|
||||||
|
}
|
||||||
|
|
||||||
tradeItems.addListener((ListChangeListener<PendingTradesListItem>) change -> {
|
tradeItems.addListener((ListChangeListener<PendingTradesListItem>) change -> {
|
||||||
if (openTradesTable.getSelectionModel().getSelectedItem() == null && tradeItems.size() > 0)
|
if (openTradesTable.getSelectionModel().getSelectedItem() == null && tradeItems.size() > 0)
|
||||||
|
|
|
@ -22,12 +22,7 @@ public class Popups
|
||||||
|
|
||||||
public static void openInformationPopup(String title, String message, String masthead)
|
public static void openInformationPopup(String title, String message, String masthead)
|
||||||
{
|
{
|
||||||
Dialogs.create()
|
Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showInformation();
|
||||||
.owner(BitSquare.getStage())
|
|
||||||
.title(title)
|
|
||||||
.message(message)
|
|
||||||
.masthead(masthead)
|
|
||||||
.showInformation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm
|
// Confirm
|
||||||
|
@ -41,13 +36,7 @@ public class Popups
|
||||||
List<Action> actions = new ArrayList<>();
|
List<Action> actions = new ArrayList<>();
|
||||||
actions.add(Dialog.Actions.OK);
|
actions.add(Dialog.Actions.OK);
|
||||||
actions.add(Dialog.Actions.CANCEL);
|
actions.add(Dialog.Actions.CANCEL);
|
||||||
return Dialogs.create()
|
return Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).actions(actions).showConfirm();
|
||||||
.owner(BitSquare.getStage())
|
|
||||||
.title(title)
|
|
||||||
.message(message)
|
|
||||||
.masthead(masthead)
|
|
||||||
.actions(actions)
|
|
||||||
.showConfirm();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warning
|
// Warning
|
||||||
|
@ -63,12 +52,7 @@ public class Popups
|
||||||
|
|
||||||
public static void openWarningPopup(String title, String message, String masthead)
|
public static void openWarningPopup(String title, String message, String masthead)
|
||||||
{
|
{
|
||||||
Dialogs.create()
|
Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showWarning();
|
||||||
.owner(BitSquare.getStage())
|
|
||||||
.title(title)
|
|
||||||
.message(message)
|
|
||||||
.masthead(masthead)
|
|
||||||
.showWarning();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error
|
// Error
|
||||||
|
@ -84,12 +68,7 @@ public class Popups
|
||||||
|
|
||||||
public static Action openErrorPopup(String title, String message, String masthead)
|
public static Action openErrorPopup(String title, String message, String masthead)
|
||||||
{
|
{
|
||||||
return Dialogs.create()
|
return Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showError();
|
||||||
.owner(BitSquare.getStage())
|
|
||||||
.title(title)
|
|
||||||
.message(message)
|
|
||||||
.masthead(masthead)
|
|
||||||
.showError();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exception
|
// Exception
|
||||||
|
@ -105,12 +84,7 @@ public class Popups
|
||||||
|
|
||||||
public static Action openExceptionPopup(Throwable throwable, String title, String message, String masthead)
|
public static Action openExceptionPopup(Throwable throwable, String title, String message, String masthead)
|
||||||
{
|
{
|
||||||
return Dialogs.create()
|
return Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showException(throwable);
|
||||||
.owner(BitSquare.getStage())
|
|
||||||
.title(title)
|
|
||||||
.message(message)
|
|
||||||
.masthead(masthead)
|
|
||||||
.showException(throwable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support handling of uncaught exception from any thread (also non gui thread)
|
// Support handling of uncaught exception from any thread (also non gui thread)
|
||||||
|
@ -120,26 +94,36 @@ public class Popups
|
||||||
// while dev
|
// while dev
|
||||||
throwable.printStackTrace();
|
throwable.printStackTrace();
|
||||||
|
|
||||||
Runnable runnable = () ->
|
Runnable runnable = () -> {
|
||||||
{
|
|
||||||
if (Throwables.getRootCause(throwable) instanceof BlockStoreException)
|
if (Throwables.getRootCause(throwable) instanceof BlockStoreException)
|
||||||
{
|
{
|
||||||
Action response = Popups.openErrorPopup("Application already running", "This application is already running and cannot be started twice.", "");
|
Action response = Popups.openErrorPopup("Application already running", "This application is already running and cannot be started twice.", "");
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
|
{
|
||||||
Platform.exit();
|
Platform.exit();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Action response = Popups.openExceptionPopup(throwable, "Exception", "", "A critical error has occurred.\nPlease copy the exception details and send a bug report to bugs@bitsquare.io.");
|
Action response = Popups.openExceptionPopup(throwable,
|
||||||
|
"Exception",
|
||||||
|
"",
|
||||||
|
"A critical error has occurred.\nPlease copy the exception details and send a bug report to bugs@bitsquare.io.");
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
|
{
|
||||||
Platform.exit();
|
Platform.exit();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Platform.isFxApplicationThread())
|
if (Platform.isFxApplicationThread())
|
||||||
|
{
|
||||||
runnable.run();
|
runnable.run();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Platform.runLater(runnable);
|
Platform.runLater(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -152,11 +136,6 @@ public class Popups
|
||||||
|
|
||||||
public static Action openRegistrationMissingPopup(String title, String message, String masthead, List<Dialogs.CommandLink> commandLinks, int selectedIndex)
|
public static Action openRegistrationMissingPopup(String title, String message, String masthead, List<Dialogs.CommandLink> commandLinks, int selectedIndex)
|
||||||
{
|
{
|
||||||
return Dialogs.create()
|
return Dialogs.create().owner(BitSquare.getStage()).title(title).message(message).masthead(masthead).showCommandLinks(commandLinks.get(selectedIndex), commandLinks);
|
||||||
.owner(BitSquare.getStage())
|
|
||||||
.title(title)
|
|
||||||
.message(message)
|
|
||||||
.masthead(masthead)
|
|
||||||
.showCommandLinks(commandLinks.get(selectedIndex), commandLinks);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,8 +162,7 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
arbitrationMethods,
|
arbitrationMethods,
|
||||||
idVerifications,
|
idVerifications,
|
||||||
"http://bitsquare.io/",
|
"http://bitsquare.io/",
|
||||||
"Bla bla..."
|
"Bla bla...");
|
||||||
);
|
|
||||||
|
|
||||||
arbitratorList.add(arbitrator);
|
arbitratorList.add(arbitrator);
|
||||||
settings.addAcceptedArbitrator(arbitrator);
|
settings.addAcceptedArbitrator(arbitrator);
|
||||||
|
@ -207,7 +206,9 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
{
|
{
|
||||||
|
|
||||||
if (childController != null)
|
if (childController != null)
|
||||||
|
{
|
||||||
childController.cleanup();
|
childController.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||||
try
|
try
|
||||||
|
@ -231,7 +232,9 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
stage.setOnHidden(windowEvent -> {
|
stage.setOnHidden(windowEvent -> {
|
||||||
if (navigationItem == NavigationItem.ARBITRATOR_OVERVIEW)
|
if (navigationItem == NavigationItem.ARBITRATOR_OVERVIEW)
|
||||||
|
{
|
||||||
updateArbitrators();
|
updateArbitrators();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
stage.show();
|
stage.show();
|
||||||
|
|
||||||
|
@ -395,8 +398,7 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
languagesListView.setItems(languageList);
|
languagesListView.setItems(languageList);
|
||||||
|
|
||||||
languageComboBox.setItems(FXCollections.observableArrayList(LanguageUtil.getAllLanguageLocales()));
|
languageComboBox.setItems(FXCollections.observableArrayList(LanguageUtil.getAllLanguageLocales()));
|
||||||
|
@ -482,8 +484,7 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
countriesListView.setItems(countryList);
|
countriesListView.setItems(countryList);
|
||||||
|
|
||||||
countryComboBox.setConverter(new StringConverter<Country>()
|
countryComboBox.setConverter(new StringConverter<Country>()
|
||||||
|
@ -553,8 +554,7 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
arbitratorsListView.setItems(arbitratorList);
|
arbitratorsListView.setItems(arbitratorList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,8 +645,10 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
bankAccountPrimaryIDTextField.setText("dummy");
|
bankAccountPrimaryIDTextField.setText("dummy");
|
||||||
bankAccountSecondaryIDTextField.setText("dummy");
|
bankAccountSecondaryIDTextField.setText("dummy");
|
||||||
if (user.getCurrentBankAccount() == null)
|
if (user.getCurrentBankAccount() == null)
|
||||||
|
{
|
||||||
onSaveBankAccount();
|
onSaveBankAccount();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void resetBankAccountInput()
|
private void resetBankAccountInput()
|
||||||
{
|
{
|
||||||
|
@ -809,8 +811,7 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
{
|
{
|
||||||
if (verifyBankAccountData())
|
if (verifyBankAccountData())
|
||||||
{
|
{
|
||||||
BankAccount bankAccount = new BankAccount(
|
BankAccount bankAccount = new BankAccount(bankAccountTypesComboBox.getSelectionModel().getSelectedItem(),
|
||||||
bankAccountTypesComboBox.getSelectionModel().getSelectedItem(),
|
|
||||||
bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem(),
|
bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem(),
|
||||||
bankAccountCountryComboBox.getSelectionModel().getSelectedItem(),
|
bankAccountCountryComboBox.getSelectionModel().getSelectedItem(),
|
||||||
bankAccountTitleTextField.getText(),
|
bankAccountTitleTextField.getText(),
|
||||||
|
@ -844,9 +845,10 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||||
BitSquareValidator.textFieldBankAccountPrimaryIDIsValid(bankAccountPrimaryIDTextField, bankAccountTypeInfo);
|
BitSquareValidator.textFieldBankAccountPrimaryIDIsValid(bankAccountPrimaryIDTextField, bankAccountTypeInfo);
|
||||||
BitSquareValidator.textFieldBankAccountSecondaryIDIsValid(bankAccountSecondaryIDTextField, bankAccountTypeInfo);
|
BitSquareValidator.textFieldBankAccountSecondaryIDIsValid(bankAccountSecondaryIDTextField, bankAccountTypeInfo);
|
||||||
|
|
||||||
return bankAccountTypesComboBox.getSelectionModel().getSelectedItem() != null
|
return bankAccountTypesComboBox.getSelectionModel().getSelectedItem() != null && bankAccountCountryComboBox.getSelectionModel()
|
||||||
&& bankAccountCountryComboBox.getSelectionModel().getSelectedItem() != null
|
.getSelectedItem() != null && bankAccountCurrencyComboBox.getSelectionModel()
|
||||||
&& bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem() != null;
|
.getSelectedItem() !=
|
||||||
|
null;
|
||||||
} catch (BitSquareValidator.ValidationException e)
|
} catch (BitSquareValidator.ValidationException e)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -50,10 +50,14 @@ public class BitSquareFormatter
|
||||||
public static String formatAmountWithMinAmount(double amount, double minAmount, boolean useBTC)
|
public static String formatAmountWithMinAmount(double amount, double minAmount, boolean useBTC)
|
||||||
{
|
{
|
||||||
if (useBTC)
|
if (useBTC)
|
||||||
|
{
|
||||||
return formatDouble(amount) + " BTC (" + formatDouble(minAmount) + " BTC)";
|
return formatDouble(amount) + " BTC (" + formatDouble(minAmount) + " BTC)";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return formatDouble(amount) + " (" + formatDouble(minAmount) + ")";
|
return formatDouble(amount) + " (" + formatDouble(minAmount) + ")";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String formatAmountWithMinAmount(double amount, double minAmount)
|
public static String formatAmountWithMinAmount(double amount, double minAmount)
|
||||||
|
@ -95,7 +99,9 @@ public class BitSquareFormatter
|
||||||
{
|
{
|
||||||
String result = (direction == Direction.BUY) ? "Buy" : "Sell";
|
String result = (direction == Direction.BUY) ? "Buy" : "Sell";
|
||||||
if (allUpperCase)
|
if (allUpperCase)
|
||||||
|
{
|
||||||
result = result.toUpperCase();
|
result = result.toUpperCase();
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,8 +149,10 @@ public class BitSquareFormatter
|
||||||
result += country.getName();
|
result += country.getName();
|
||||||
i++;
|
i++;
|
||||||
if (i < countries.size())
|
if (i < countries.size())
|
||||||
|
{
|
||||||
result += ", ";
|
result += ", ";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,8 +165,10 @@ public class BitSquareFormatter
|
||||||
result += locale.getDisplayLanguage();
|
result += locale.getDisplayLanguage();
|
||||||
i++;
|
i++;
|
||||||
if (i < languageLocales.size())
|
if (i < languageLocales.size())
|
||||||
|
{
|
||||||
result += ", ";
|
result += ", ";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,8 +182,10 @@ public class BitSquareFormatter
|
||||||
result += Localisation.get(item.toString());
|
result += Localisation.get(item.toString());
|
||||||
i++;
|
i++;
|
||||||
if (i < items.size())
|
if (i < items.size())
|
||||||
|
{
|
||||||
result += ", ";
|
result += ", ";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,8 +199,10 @@ public class BitSquareFormatter
|
||||||
result += Localisation.get(item.toString());
|
result += Localisation.get(item.toString());
|
||||||
i++;
|
i++;
|
||||||
if (i < items.size())
|
if (i < items.size())
|
||||||
|
{
|
||||||
result += ", ";
|
result += ", ";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,9 @@ public class ConfidenceDisplay
|
||||||
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
||||||
{
|
{
|
||||||
if (tx.getHashAsString().equals(transaction.getHashAsString()))
|
if (tx.getHashAsString().equals(transaction.getHashAsString()))
|
||||||
|
{
|
||||||
updateBalance(newBalance);
|
updateBalance(newBalance);
|
||||||
|
}
|
||||||
// log.debug("onCoinsReceived " + newBalance);
|
// log.debug("onCoinsReceived " + newBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +117,9 @@ public class ConfidenceDisplay
|
||||||
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
|
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
|
||||||
{
|
{
|
||||||
if (tx.getHashAsString().equals(transaction.getHashAsString()))
|
if (tx.getHashAsString().equals(transaction.getHashAsString()))
|
||||||
|
{
|
||||||
updateConfidence(transaction);
|
updateConfidence(transaction);
|
||||||
|
}
|
||||||
// log.debug("onTransactionConfidenceChanged newTransaction " + newTransaction.getHashAsString());
|
// log.debug("onTransactionConfidenceChanged newTransaction " + newTransaction.getHashAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +127,10 @@ public class ConfidenceDisplay
|
||||||
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
||||||
{
|
{
|
||||||
if (tx.getHashAsString().equals(transaction.getHashAsString()))
|
if (tx.getHashAsString().equals(transaction.getHashAsString()))
|
||||||
|
{
|
||||||
updateBalance(newBalance);
|
updateBalance(newBalance);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReorganize(Wallet wallet)
|
public void onReorganize(Wallet wallet)
|
||||||
|
@ -155,8 +161,10 @@ public class ConfidenceDisplay
|
||||||
progressIndicator.setProgress(0);
|
progressIndicator.setProgress(0);
|
||||||
confirmationLabel.setText("");
|
confirmationLabel.setText("");
|
||||||
if (balanceTextField != null)
|
if (balanceTextField != null)
|
||||||
|
{
|
||||||
balanceTextField.setText("");
|
balanceTextField.setText("");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateBalance(BigInteger balance)
|
private void updateBalance(BigInteger balance)
|
||||||
{
|
{
|
||||||
|
@ -183,12 +191,16 @@ public class ConfidenceDisplay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (latestTransaction != null && (transaction == null || latestTransaction.getHashAsString().equals(transaction.getHashAsString())))
|
if (latestTransaction != null && (transaction == null || latestTransaction.getHashAsString().equals(transaction.getHashAsString())))
|
||||||
|
{
|
||||||
updateConfidence(latestTransaction);
|
updateConfidence(latestTransaction);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (balanceTextField != null)
|
if (balanceTextField != null)
|
||||||
|
{
|
||||||
balanceTextField.setText(BtcFormatter.formatSatoshis(balance));
|
balanceTextField.setText(BtcFormatter.formatSatoshis(balance));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateConfidence(Transaction tx)
|
private void updateConfidence(Transaction tx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,9 +29,13 @@ public class Country implements Serializable
|
||||||
public boolean equals(Object obj)
|
public boolean equals(Object obj)
|
||||||
{
|
{
|
||||||
if (!(obj instanceof Country))
|
if (!(obj instanceof Country))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (obj == this)
|
if (obj == this)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
final Country other = (Country) obj;
|
final Country other = (Country) obj;
|
||||||
return code.equals(other.getCode());
|
return code.equals(other.getCode());
|
||||||
|
|
|
@ -7,211 +7,17 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class CountryUtil
|
public class CountryUtil
|
||||||
{
|
{
|
||||||
private static final String[] countryCodes = new String[]{"AE",
|
private static final String[] countryCodes = new String[]{"AE", "AL", "AR", "AT", "AU", "BA", "BE", "BG", "BH", "BO", "BR", "BY", "CA", "CH", "CL", "CN", "CO", "CR", "CS", "CU", "CY", "CZ",
|
||||||
"AL",
|
"DE", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "FI", "FR", "GB", "GR", "GT", "HK", "HN", "HR", "HU", "ID", "IE", "IL", "IN", "IQ", "IS", "IT", "JO", "JP", "KR", "KW", "LB", "LT", "LU",
|
||||||
"AR",
|
"LV", "LY", "MA", "ME", "MK", "MT", "MX", "MY", "NI", "NL", "NO", "NZ", "OM", "PA", "PE", "PH", "PL", "PR", "PT", "PY", "QA", "RO", "RS", "RU", "SA", "SD", "SE", "SG", "SI", "SK", "SV",
|
||||||
"AT",
|
"SY", "TH", "TN", "TR", "TW", "UA", "US", "UY", "VE", "VN", "YE", "ZA"};
|
||||||
"AU",
|
|
||||||
"BA",
|
|
||||||
"BE",
|
|
||||||
"BG",
|
|
||||||
"BH",
|
|
||||||
"BO",
|
|
||||||
"BR",
|
|
||||||
"BY",
|
|
||||||
"CA",
|
|
||||||
"CH",
|
|
||||||
"CL",
|
|
||||||
"CN",
|
|
||||||
"CO",
|
|
||||||
"CR",
|
|
||||||
"CS",
|
|
||||||
"CU",
|
|
||||||
"CY",
|
|
||||||
"CZ",
|
|
||||||
"DE",
|
|
||||||
"DK",
|
|
||||||
"DO",
|
|
||||||
"DZ",
|
|
||||||
"EC",
|
|
||||||
"EE",
|
|
||||||
"EG",
|
|
||||||
"ES",
|
|
||||||
"FI",
|
|
||||||
"FR",
|
|
||||||
"GB",
|
|
||||||
"GR",
|
|
||||||
"GT",
|
|
||||||
"HK",
|
|
||||||
"HN",
|
|
||||||
"HR",
|
|
||||||
"HU",
|
|
||||||
"ID",
|
|
||||||
"IE",
|
|
||||||
"IL",
|
|
||||||
"IN",
|
|
||||||
"IQ",
|
|
||||||
"IS",
|
|
||||||
"IT",
|
|
||||||
"JO",
|
|
||||||
"JP",
|
|
||||||
"KR",
|
|
||||||
"KW",
|
|
||||||
"LB",
|
|
||||||
"LT",
|
|
||||||
"LU",
|
|
||||||
"LV",
|
|
||||||
"LY",
|
|
||||||
"MA",
|
|
||||||
"ME",
|
|
||||||
"MK",
|
|
||||||
"MT",
|
|
||||||
"MX",
|
|
||||||
"MY",
|
|
||||||
"NI",
|
|
||||||
"NL",
|
|
||||||
"NO",
|
|
||||||
"NZ",
|
|
||||||
"OM",
|
|
||||||
"PA",
|
|
||||||
"PE",
|
|
||||||
"PH",
|
|
||||||
"PL",
|
|
||||||
"PR",
|
|
||||||
"PT",
|
|
||||||
"PY",
|
|
||||||
"QA",
|
|
||||||
"RO",
|
|
||||||
"RS",
|
|
||||||
"RU",
|
|
||||||
"SA",
|
|
||||||
"SD",
|
|
||||||
"SE",
|
|
||||||
"SG",
|
|
||||||
"SI",
|
|
||||||
"SK",
|
|
||||||
"SV",
|
|
||||||
"SY",
|
|
||||||
"TH",
|
|
||||||
"TN",
|
|
||||||
"TR",
|
|
||||||
"TW",
|
|
||||||
"UA",
|
|
||||||
"US",
|
|
||||||
"UY",
|
|
||||||
"VE",
|
|
||||||
"VN",
|
|
||||||
"YE",
|
|
||||||
"ZA"
|
|
||||||
};
|
|
||||||
private static final List<String> countryCodeList = Arrays.asList(countryCodes);
|
private static final List<String> countryCodeList = Arrays.asList(countryCodes);
|
||||||
private static final String[] regionCodes = new String[]{
|
private static final String[] regionCodes = new String[]{"AS", "EU", "SA", "EU", "OC", "EU", "EU", "EU", "AS", "SA", "SA", "EU", "NA", "EU", "SA", "AS", "SA", "NA", "EU", "NA", "AS", "EU",
|
||||||
"AS",
|
"EU", "EU", "NA", "AF", "SA", "EU", "AF", "EU", "EU", "EU", "EU", "EU", "NA", "AS", "NA", "EU", "EU", "AS", "EU", "AS", "AS", "AS", "EU", "EU", "AS", "AS", "AS", "AS", "AS", "EU", "EU",
|
||||||
"EU",
|
"EU", "AF", "AF", "EU", "EU", "EU", "NA", "AS", "NA", "EU", "EU", "OC", "AS", "NA", "SA", "AS", "EU", "NA", "EU", "SA", "AS", "EU", "EU", "EU", "AS", "AF", "EU", "AS", "EU", "EU", "NA",
|
||||||
"SA",
|
"AS", "AS", "AF", "AS", "AS", "EU", "NA", "SA", "SA", "AS", "AS", "AF"};
|
||||||
"EU",
|
|
||||||
"OC",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"AS",
|
|
||||||
"SA",
|
|
||||||
"SA",
|
|
||||||
"EU",
|
|
||||||
"NA",
|
|
||||||
"EU",
|
|
||||||
"SA",
|
|
||||||
"AS",
|
|
||||||
"SA",
|
|
||||||
"NA",
|
|
||||||
"EU",
|
|
||||||
"NA",
|
|
||||||
"AS",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"NA",
|
|
||||||
"AF",
|
|
||||||
"SA",
|
|
||||||
"EU",
|
|
||||||
"AF",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"NA",
|
|
||||||
"AS",
|
|
||||||
"NA",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"AS",
|
|
||||||
"EU",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"AF",
|
|
||||||
"AF",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"NA",
|
|
||||||
"AS",
|
|
||||||
"NA",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"OC",
|
|
||||||
"AS",
|
|
||||||
"NA",
|
|
||||||
"SA",
|
|
||||||
"AS",
|
|
||||||
"EU",
|
|
||||||
"NA",
|
|
||||||
"EU",
|
|
||||||
"SA",
|
|
||||||
"AS",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"AS",
|
|
||||||
"AF",
|
|
||||||
"EU",
|
|
||||||
"AS",
|
|
||||||
"EU",
|
|
||||||
"EU",
|
|
||||||
"NA",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"AF",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"EU",
|
|
||||||
"NA",
|
|
||||||
"SA",
|
|
||||||
"SA",
|
|
||||||
"AS",
|
|
||||||
"AS",
|
|
||||||
"AF"
|
|
||||||
};
|
|
||||||
private static final List<String> regionCodeList = Arrays.asList(regionCodes);
|
private static final List<String> regionCodeList = Arrays.asList(regionCodes);
|
||||||
private static final String[][] regionCodeToName = new String[][]{
|
private static final String[][] regionCodeToName = new String[][]{{"NA", "North America"}, {"SA", "South America"}, {"AF", "Africa"}, {"EU", "Europe"}, {"AS", "Asia"}, {"OC", "Oceania"}};
|
||||||
{"NA", "North America"},
|
|
||||||
{"SA", "South America"},
|
|
||||||
{"AF", "Africa"},
|
|
||||||
{"EU", "Europe"},
|
|
||||||
{"AS", "Asia"},
|
|
||||||
{"OC", "Oceania"}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public static List<Region> getAllRegions()
|
public static List<Region> getAllRegions()
|
||||||
|
@ -279,8 +85,10 @@ public class CountryUtil
|
||||||
for (final String[] regionName : regionCodeToName)
|
for (final String[] regionName : regionCodeToName)
|
||||||
{
|
{
|
||||||
if (regionName[0].equals(regionCode))
|
if (regionName[0].equals(regionCode))
|
||||||
|
{
|
||||||
return regionName[1];
|
return regionName[1];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return regionCode;
|
return regionCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,9 +118,13 @@ public class CountryUtil
|
||||||
private static String getRegionCode(String countryCode)
|
private static String getRegionCode(String countryCode)
|
||||||
{
|
{
|
||||||
if (!countryCode.isEmpty() && countryCodeList.contains(countryCode))
|
if (!countryCode.isEmpty() && countryCodeList.contains(countryCode))
|
||||||
|
{
|
||||||
return regionCodeList.get(countryCodeList.indexOf(countryCode));
|
return regionCodeList.get(countryCodeList.indexOf(countryCode));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return "Undefined";
|
return "Undefined";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,13 @@ public class Region implements Serializable
|
||||||
public boolean equals(Object obj)
|
public boolean equals(Object obj)
|
||||||
{
|
{
|
||||||
if (!(obj instanceof Region))
|
if (!(obj instanceof Region))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (obj == this)
|
if (obj == this)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Region other = (Region) obj;
|
Region other = (Region) obj;
|
||||||
return code.equals(other.getCode());
|
return code.equals(other.getCode());
|
||||||
|
|
|
@ -72,9 +72,13 @@ public class MessageFacade
|
||||||
{
|
{
|
||||||
int port = Bindings.MAX_PORT - Math.abs(new Random().nextInt()) % (Bindings.MAX_PORT - Bindings.MIN_DYN_PORT);
|
int port = Bindings.MAX_PORT - Math.abs(new Random().nextInt()) % (Bindings.MAX_PORT - Bindings.MIN_DYN_PORT);
|
||||||
if (BitSquare.ID.contains("taker"))
|
if (BitSquare.ID.contains("taker"))
|
||||||
|
{
|
||||||
port = 4501;
|
port = 4501;
|
||||||
|
}
|
||||||
else if (BitSquare.ID.contains("offerer"))
|
else if (BitSquare.ID.contains("offerer"))
|
||||||
|
{
|
||||||
port = 4500;
|
port = 4500;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -93,8 +97,10 @@ public class MessageFacade
|
||||||
public void shutDown()
|
public void shutDown()
|
||||||
{
|
{
|
||||||
if (myPeer != null)
|
if (myPeer != null)
|
||||||
|
{
|
||||||
myPeer.shutdown();
|
myPeer.shutdown();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -224,12 +230,15 @@ public class MessageFacade
|
||||||
public void operationComplete(BaseFuture baseFuture) throws Exception
|
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||||
{
|
{
|
||||||
if (sendFuture.isSuccess())
|
if (sendFuture.isSuccess())
|
||||||
|
{
|
||||||
Platform.runLater(() -> listener.onResult());
|
Platform.runLater(() -> listener.onResult());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Platform.runLater(() -> listener.onFailed());
|
Platform.runLater(() -> listener.onFailed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,8 +328,10 @@ public class MessageFacade
|
||||||
private void onArbitratorsReceived(Map<Number160, Data> dataMap, boolean success)
|
private void onArbitratorsReceived(Map<Number160, Data> dataMap, boolean success)
|
||||||
{
|
{
|
||||||
for (ArbitratorListener arbitratorListener : arbitratorListeners)
|
for (ArbitratorListener arbitratorListener : arbitratorListeners)
|
||||||
|
{
|
||||||
arbitratorListener.onArbitratorsReceived(dataMap, success);
|
arbitratorListener.onArbitratorsReceived(dataMap, success);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Check dirty flag for a location key
|
// Check dirty flag for a location key
|
||||||
|
@ -346,9 +357,11 @@ public class MessageFacade
|
||||||
{
|
{
|
||||||
Object object = data.getObject();
|
Object object = data.getObject();
|
||||||
if (object instanceof Long)
|
if (object instanceof Long)
|
||||||
|
{
|
||||||
Platform.runLater(() -> onGetDirtyFlag((Long) object));
|
Platform.runLater(() -> onGetDirtyFlag((Long) object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(Throwable t) throws Exception
|
public void exceptionCaught(Throwable t) throws Exception
|
||||||
|
@ -366,10 +379,14 @@ public class MessageFacade
|
||||||
isDirty.setValue(!isDirty.get());
|
isDirty.setValue(!isDirty.get());
|
||||||
}
|
}
|
||||||
if (lastTimeStamp > 0)
|
if (lastTimeStamp > 0)
|
||||||
|
{
|
||||||
lastTimeStamp = timeStamp;
|
lastTimeStamp = timeStamp;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
lastTimeStamp++;
|
lastTimeStamp++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Number160 getDirtyLocationKey(Number160 locationKey)
|
private Number160 getDirtyLocationKey(Number160 locationKey)
|
||||||
{
|
{
|
||||||
|
@ -634,9 +651,13 @@ public class MessageFacade
|
||||||
{
|
{
|
||||||
myPeer.setObjectDataReply((sender, request) -> {
|
myPeer.setObjectDataReply((sender, request) -> {
|
||||||
if (!sender.equals(myPeer.getPeerAddress()))
|
if (!sender.equals(myPeer.getPeerAddress()))
|
||||||
|
{
|
||||||
Platform.runLater(() -> onMessage(request, sender));
|
Platform.runLater(() -> onMessage(request, sender));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
log.error("Received msg from myself. That should never happen.");
|
log.error("Received msg from myself. That should never happen.");
|
||||||
|
}
|
||||||
//noinspection ReturnOfNull
|
//noinspection ReturnOfNull
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,8 +51,10 @@ public class Settings implements Serializable
|
||||||
public void addAcceptedLanguageLocale(Locale locale)
|
public void addAcceptedLanguageLocale(Locale locale)
|
||||||
{
|
{
|
||||||
if (!acceptedLanguageLocales.contains(locale))
|
if (!acceptedLanguageLocales.contains(locale))
|
||||||
|
{
|
||||||
acceptedLanguageLocales.add(locale);
|
acceptedLanguageLocales.add(locale);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeAcceptedLanguageLocale(Locale item)
|
public void removeAcceptedLanguageLocale(Locale item)
|
||||||
{
|
{
|
||||||
|
@ -62,8 +64,10 @@ public class Settings implements Serializable
|
||||||
public void addAcceptedCountry(Country locale)
|
public void addAcceptedCountry(Country locale)
|
||||||
{
|
{
|
||||||
if (!acceptedCountryLocales.contains(locale))
|
if (!acceptedCountryLocales.contains(locale))
|
||||||
|
{
|
||||||
acceptedCountryLocales.add(locale);
|
acceptedCountryLocales.add(locale);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeAcceptedCountry(Country item)
|
public void removeAcceptedCountry(Country item)
|
||||||
{
|
{
|
||||||
|
@ -73,8 +77,10 @@ public class Settings implements Serializable
|
||||||
public void addAcceptedArbitrator(Arbitrator arbitrator)
|
public void addAcceptedArbitrator(Arbitrator arbitrator)
|
||||||
{
|
{
|
||||||
if (!acceptedArbitrators.contains(arbitrator))
|
if (!acceptedArbitrators.contains(arbitrator))
|
||||||
|
{
|
||||||
acceptedArbitrators.add(arbitrator);
|
acceptedArbitrators.add(arbitrator);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeAcceptedArbitrator(Arbitrator item)
|
public void removeAcceptedArbitrator(Arbitrator item)
|
||||||
{
|
{
|
||||||
|
|
|
@ -237,10 +237,14 @@ public class Storage
|
||||||
// Work around an issue on Windows whereby you can't rename over existing files.
|
// Work around an issue on Windows whereby you can't rename over existing files.
|
||||||
final File canonical = storageFile.getCanonicalFile();
|
final File canonical = storageFile.getCanonicalFile();
|
||||||
if (canonical.exists() && !canonical.delete())
|
if (canonical.exists() && !canonical.delete())
|
||||||
|
{
|
||||||
throw new IOException("Failed to delete canonical file for replacement with save");
|
throw new IOException("Failed to delete canonical file for replacement with save");
|
||||||
|
}
|
||||||
if (!tempFile.renameTo(canonical))
|
if (!tempFile.renameTo(canonical))
|
||||||
|
{
|
||||||
throw new IOException("Failed to rename " + tempFile + " to " + canonical);
|
throw new IOException("Failed to rename " + tempFile + " to " + canonical);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (!tempFile.renameTo(storageFile))
|
else if (!tempFile.renameTo(storageFile))
|
||||||
{
|
{
|
||||||
throw new IOException("Failed to rename " + tempFile + " to " + storageFile);
|
throw new IOException("Failed to rename " + tempFile + " to " + storageFile);
|
||||||
|
@ -255,9 +259,11 @@ public class Storage
|
||||||
{
|
{
|
||||||
log.warn("Temp file still exists after failed save.");
|
log.warn("Temp file still exists after failed save.");
|
||||||
if (!tempFile.delete())
|
if (!tempFile.delete())
|
||||||
|
{
|
||||||
log.warn("Cannot delete temp file.");
|
log.warn("Cannot delete temp file.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (IOException e)
|
} catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -12,15 +12,8 @@ import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.TradeMessage;
|
import io.bitsquare.msg.TradeMessage;
|
||||||
import io.bitsquare.msg.listeners.TakeOfferRequestListener;
|
import io.bitsquare.msg.listeners.TakeOfferRequestListener;
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.*;
|
import io.bitsquare.trade.protocol.offerer.*;
|
||||||
import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.taker.*;
|
||||||
import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage;
|
|
||||||
import io.bitsquare.trade.protocol.messages.taker.RequestTakeOfferMessage;
|
|
||||||
import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage;
|
|
||||||
import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocol;
|
|
||||||
import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocolListener;
|
|
||||||
import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocol;
|
|
||||||
import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocolListener;
|
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
@ -49,8 +42,10 @@ public class Trading
|
||||||
private final CryptoFacade cryptoFacade;
|
private final CryptoFacade cryptoFacade;
|
||||||
|
|
||||||
private final List<TakeOfferRequestListener> takeOfferRequestListeners = new ArrayList<>();
|
private final List<TakeOfferRequestListener> takeOfferRequestListeners = new ArrayList<>();
|
||||||
private final Map<String, TakerAsSellerProtocol> takerAsSellerProtocolMap = new HashMap<>();
|
|
||||||
private final Map<String, OffererAsBuyerProtocol> offererAsBuyerProtocolMap = new HashMap<>();
|
//TODO store TakerAsSellerProtocol in trade
|
||||||
|
private final Map<String, ProtocolForTakerAsSeller> takerAsSellerProtocolMap = new HashMap<>();
|
||||||
|
private final Map<String, ProtocolForOffererAsBuyer> offererAsBuyerProtocolMap = new HashMap<>();
|
||||||
|
|
||||||
private final StringProperty newTradeProperty = new SimpleStringProperty();
|
private final StringProperty newTradeProperty = new SimpleStringProperty();
|
||||||
|
|
||||||
|
@ -65,12 +60,7 @@ public class Trading
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Trading(User user,
|
public Trading(User user, Storage storage, MessageFacade messageFacade, BlockChainFacade blockChainFacade, WalletFacade walletFacade, CryptoFacade cryptoFacade)
|
||||||
Storage storage,
|
|
||||||
MessageFacade messageFacade,
|
|
||||||
BlockChainFacade blockChainFacade,
|
|
||||||
WalletFacade walletFacade,
|
|
||||||
CryptoFacade cryptoFacade)
|
|
||||||
{
|
{
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
|
@ -81,15 +71,23 @@ public class Trading
|
||||||
|
|
||||||
Object offersObject = storage.read(storageKey + ".offers");
|
Object offersObject = storage.read(storageKey + ".offers");
|
||||||
if (offersObject instanceof HashMap)
|
if (offersObject instanceof HashMap)
|
||||||
|
{
|
||||||
offers = (Map<String, Offer>) offersObject;
|
offers = (Map<String, Offer>) offersObject;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
offers = new HashMap<>();
|
offers = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
Object tradesObject = storage.read(storageKey + ".trades");
|
Object tradesObject = storage.read(storageKey + ".trades");
|
||||||
if (tradesObject instanceof HashMap)
|
if (tradesObject instanceof HashMap)
|
||||||
|
{
|
||||||
trades = (Map<String, Trade>) tradesObject;
|
trades = (Map<String, Trade>) tradesObject;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
trades = new HashMap<>();
|
trades = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
messageFacade.addIncomingTradeMessageListener(this::onIncomingTradeMessage);
|
messageFacade.addIncomingTradeMessageListener(this::onIncomingTradeMessage);
|
||||||
}
|
}
|
||||||
|
@ -127,7 +125,9 @@ public class Trading
|
||||||
public void addOffer(Offer offer) throws IOException
|
public void addOffer(Offer offer) throws IOException
|
||||||
{
|
{
|
||||||
if (offers.containsKey(offer.getId()))
|
if (offers.containsKey(offer.getId()))
|
||||||
|
{
|
||||||
throw new IllegalStateException("offers contains already an offer with the ID " + offer.getId());
|
throw new IllegalStateException("offers contains already an offer with the ID " + offer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
offers.put(offer.getId(), offer);
|
offers.put(offer.getId(), offer);
|
||||||
saveOffers();
|
saveOffers();
|
||||||
|
@ -138,7 +138,9 @@ public class Trading
|
||||||
public void removeOffer(Offer offer)
|
public void removeOffer(Offer offer)
|
||||||
{
|
{
|
||||||
if (!offers.containsKey(offer.getId()))
|
if (!offers.containsKey(offer.getId()))
|
||||||
|
{
|
||||||
throw new IllegalStateException("offers does not contain the offer with the ID " + offer.getId());
|
throw new IllegalStateException("offers does not contain the offer with the ID " + offer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
offers.remove(offer.getId());
|
offers.remove(offer.getId());
|
||||||
saveOffers();
|
saveOffers();
|
||||||
|
@ -146,14 +148,14 @@ public class Trading
|
||||||
messageFacade.removeOffer(offer);
|
messageFacade.removeOffer(offer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Trade takeOffer(BigInteger amount, Offer offer, TakerAsSellerProtocolListener listener)
|
public Trade takeOffer(BigInteger amount, Offer offer, ProtocolForTakerAsSellerListener listener)
|
||||||
{
|
{
|
||||||
Trade trade = createTrade(offer);
|
Trade trade = createTrade(offer);
|
||||||
trade.setTradeAmount(amount);
|
trade.setTradeAmount(amount);
|
||||||
|
|
||||||
TakerAsSellerProtocol takerAsSellerProtocol = new TakerAsSellerProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
ProtocolForTakerAsSeller protocolForTakerAsSeller = new ProtocolForTakerAsSeller(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
||||||
takerAsSellerProtocolMap.put(trade.getId(), takerAsSellerProtocol);
|
takerAsSellerProtocolMap.put(trade.getId(), protocolForTakerAsSeller);
|
||||||
takerAsSellerProtocol.start();
|
protocolForTakerAsSeller.start();
|
||||||
|
|
||||||
return trade;
|
return trade;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +168,9 @@ public class Trading
|
||||||
public Trade createTrade(Offer offer)
|
public Trade createTrade(Offer offer)
|
||||||
{
|
{
|
||||||
if (trades.containsKey(offer.getId()))
|
if (trades.containsKey(offer.getId()))
|
||||||
|
{
|
||||||
throw new IllegalStateException("trades contains already an trade with the ID " + offer.getId());
|
throw new IllegalStateException("trades contains already an trade with the ID " + offer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
Trade trade = new Trade(offer);
|
Trade trade = new Trade(offer);
|
||||||
trades.put(offer.getId(), trade);
|
trades.put(offer.getId(), trade);
|
||||||
|
@ -181,7 +185,9 @@ public class Trading
|
||||||
public void removeTrade(Trade trade)
|
public void removeTrade(Trade trade)
|
||||||
{
|
{
|
||||||
if (!trades.containsKey(trade.getId()))
|
if (!trades.containsKey(trade.getId()))
|
||||||
|
{
|
||||||
throw new IllegalStateException("trades does not contain the trade with the ID " + trade.getId());
|
throw new IllegalStateException("trades does not contain the trade with the ID " + trade.getId());
|
||||||
|
}
|
||||||
|
|
||||||
trades.remove(trade.getId());
|
trades.remove(trade.getId());
|
||||||
saveTrades();
|
saveTrades();
|
||||||
|
@ -205,7 +211,14 @@ public class Trading
|
||||||
Trade trade = createTrade(offer);
|
Trade trade = createTrade(offer);
|
||||||
pendingTrade = trade;
|
pendingTrade = trade;
|
||||||
|
|
||||||
OffererAsBuyerProtocol offererAsBuyerProtocol = new OffererAsBuyerProtocol(trade, sender, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user, new OffererAsBuyerProtocolListener()
|
ProtocolForOffererAsBuyer protocolForOffererAsBuyer = new ProtocolForOffererAsBuyer(trade,
|
||||||
|
sender,
|
||||||
|
messageFacade,
|
||||||
|
walletFacade,
|
||||||
|
blockChainFacade,
|
||||||
|
cryptoFacade,
|
||||||
|
user,
|
||||||
|
new ProtocolForOffererAsBuyerListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onOfferAccepted(Offer offer)
|
public void onOfferAccepted(Offer offer)
|
||||||
|
@ -228,33 +241,36 @@ public class Trading
|
||||||
@Override
|
@Override
|
||||||
public void onPayoutTxPublished(String payoutTxAsHex)
|
public void onPayoutTxPublished(String payoutTxAsHex)
|
||||||
{
|
{
|
||||||
Transaction payoutTx = new Transaction(walletFacade.getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex));
|
Transaction payoutTx = new Transaction(walletFacade.getWallet().getParams(),
|
||||||
|
Utils.parseAsHexOrBase58(payoutTxAsHex));
|
||||||
trade.setPayoutTransaction(payoutTx);
|
trade.setPayoutTransaction(payoutTx);
|
||||||
trade.setState(Trade.State.COMPLETED);
|
trade.setState(Trade.State.COMPLETED);
|
||||||
log.debug("trading onPayoutTxPublishedMessage");
|
log.debug("trading onPayoutTxPublishedMessage");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFault(Throwable throwable, OffererAsBuyerProtocol.State state)
|
public void onFault(Throwable throwable, ProtocolForOffererAsBuyer.State state)
|
||||||
{
|
{
|
||||||
log.error("Error while executing trade process at state: " + state + " / " + throwable);
|
log.error("Error while executing trade process at state: " + state + " / " + throwable);
|
||||||
Popups.openErrorPopup("Error while executing trade process", "Error while executing trade process at state: " + state + " / " + throwable);
|
Popups.openErrorPopup("Error while executing trade process",
|
||||||
|
"Error while executing trade process at state: " + state + " / " +
|
||||||
|
throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWaitingForPeerResponse(OffererAsBuyerProtocol.State state)
|
public void onWaitingForPeerResponse(ProtocolForOffererAsBuyer.State state)
|
||||||
{
|
{
|
||||||
log.debug("Waiting for peers response at state " + state);
|
log.debug("Waiting for peers response at state " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCompleted(OffererAsBuyerProtocol.State state)
|
public void onCompleted(ProtocolForOffererAsBuyer.State state)
|
||||||
{
|
{
|
||||||
log.debug("Trade protocol completed at state " + state);
|
log.debug("Trade protocol completed at state " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWaitingForUserInteraction(OffererAsBuyerProtocol.State state)
|
public void onWaitingForUserInteraction(ProtocolForOffererAsBuyer.State state)
|
||||||
{
|
{
|
||||||
log.debug("Waiting for UI activity at state " + state);
|
log.debug("Waiting for UI activity at state " + state);
|
||||||
}
|
}
|
||||||
|
@ -267,8 +283,18 @@ public class Trading
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
this.offererAsBuyerProtocolMap.put(trade.getId(), offererAsBuyerProtocol);
|
|
||||||
offererAsBuyerProtocol.start();
|
if (!offererAsBuyerProtocolMap.containsKey(trade.getId()))
|
||||||
|
{
|
||||||
|
offererAsBuyerProtocolMap.put(trade.getId(), protocolForOffererAsBuyer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We don't store the protocol in case we have already a pending offer. The protocol is only temporary used to reply with a reject message.
|
||||||
|
log.trace("offererAsBuyerProtocol not stored as offer is already pending.");
|
||||||
|
}
|
||||||
|
|
||||||
|
protocolForOffererAsBuyer.start();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -305,13 +331,9 @@ public class Trading
|
||||||
createOffererAsBuyerProtocol(tradeId, sender);
|
createOffererAsBuyerProtocol(tradeId, sender);
|
||||||
takeOfferRequestListeners.stream().forEach(e -> e.onTakeOfferRequested(tradeId, sender));
|
takeOfferRequestListeners.stream().forEach(e -> e.onTakeOfferRequested(tradeId, sender));
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof AcceptTakeOfferRequestMessage)
|
else if (tradeMessage instanceof RespondToTakeOfferRequestMessage)
|
||||||
{
|
{
|
||||||
takerAsSellerProtocolMap.get(tradeId).onAcceptTakeOfferRequestMessage();
|
takerAsSellerProtocolMap.get(tradeId).onRespondToTakeOfferRequestMessage((RespondToTakeOfferRequestMessage) tradeMessage);
|
||||||
}
|
|
||||||
else if (tradeMessage instanceof RejectTakeOfferRequestMessage)
|
|
||||||
{
|
|
||||||
takerAsSellerProtocolMap.get(tradeId).onRejectTakeOfferRequestMessage();
|
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof TakeOfferFeePayedMessage)
|
else if (tradeMessage instanceof TakeOfferFeePayedMessage)
|
||||||
{
|
{
|
||||||
|
@ -398,8 +420,12 @@ public class Trading
|
||||||
public Trade getTrade(String tradeId)
|
public Trade getTrade(String tradeId)
|
||||||
{
|
{
|
||||||
if (trades.containsKey(tradeId))
|
if (trades.containsKey(tradeId))
|
||||||
|
{
|
||||||
return trades.get(trades);
|
return trades.get(trades);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -70,10 +70,14 @@ public class OrderBook implements OrderBookListener
|
||||||
public void loadOffers()
|
public void loadOffers()
|
||||||
{
|
{
|
||||||
if (user.getCurrentBankAccount() != null)
|
if (user.getCurrentBankAccount() != null)
|
||||||
|
{
|
||||||
messageFacade.getOffers(user.getCurrentBankAccount().getCurrency().getCurrencyCode());
|
messageFacade.getOffers(user.getCurrentBankAccount().getCurrency().getCurrencyCode());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
messageFacade.getOffers(CurrencyUtil.getDefaultCurrency().getCurrencyCode());
|
messageFacade.getOffers(CurrencyUtil.getDefaultCurrency().getCurrencyCode());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeOffer(Offer offer)
|
public void removeOffer(Offer offer)
|
||||||
{
|
{
|
||||||
|
@ -86,10 +90,10 @@ public class OrderBook implements OrderBookListener
|
||||||
Offer offer = orderBookListItem.getOffer();
|
Offer offer = orderBookListItem.getOffer();
|
||||||
BankAccount currentBankAccount = user.getCurrentBankAccount();
|
BankAccount currentBankAccount = user.getCurrentBankAccount();
|
||||||
|
|
||||||
if (orderBookFilter == null
|
if (orderBookFilter == null || currentBankAccount == null || orderBookFilter.getDirection() == null)
|
||||||
|| currentBankAccount == null
|
{
|
||||||
|| orderBookFilter.getDirection() == null)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// The users current bank account currency must match the offer currency (1 to 1)
|
// The users current bank account currency must match the offer currency (1 to 1)
|
||||||
boolean currencyResult = currentBankAccount.getCurrency().equals(offer.getCurrency());
|
boolean currencyResult = currentBankAccount.getCurrency().equals(offer.getCurrency());
|
||||||
|
@ -104,7 +108,9 @@ public class OrderBook implements OrderBookListener
|
||||||
// The requested amount must be lower or equal then the offer amount
|
// The requested amount must be lower or equal then the offer amount
|
||||||
boolean amountResult = true;
|
boolean amountResult = true;
|
||||||
if (orderBookFilter.getAmount() > 0)
|
if (orderBookFilter.getAmount() > 0)
|
||||||
|
{
|
||||||
amountResult = orderBookFilter.getAmount() <= offer.getAmount().doubleValue();
|
amountResult = orderBookFilter.getAmount() <= offer.getAmount().doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
// The requested trade direction must be opposite of the offerList trade direction
|
// The requested trade direction must be opposite of the offerList trade direction
|
||||||
boolean directionResult = !orderBookFilter.getDirection().equals(offer.getDirection());
|
boolean directionResult = !orderBookFilter.getDirection().equals(offer.getDirection());
|
||||||
|
@ -114,23 +120,21 @@ public class OrderBook implements OrderBookListener
|
||||||
if (orderBookFilter.getPrice() > 0)
|
if (orderBookFilter.getPrice() > 0)
|
||||||
{
|
{
|
||||||
if (offer.getDirection() == Direction.SELL)
|
if (offer.getDirection() == Direction.SELL)
|
||||||
|
{
|
||||||
priceResult = orderBookFilter.getPrice() >= offer.getPrice();
|
priceResult = orderBookFilter.getPrice() >= offer.getPrice();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
priceResult = orderBookFilter.getPrice() <= offer.getPrice();
|
priceResult = orderBookFilter.getPrice() <= offer.getPrice();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The arbitrator defined in the offer must match one of the accepted arbitrators defined in the settings (1 to n)
|
// The arbitrator defined in the offer must match one of the accepted arbitrators defined in the settings (1 to n)
|
||||||
boolean arbitratorResult = arbitratorInList(offer.getArbitrator(), settings.getAcceptedArbitrators());
|
boolean arbitratorResult = arbitratorInList(offer.getArbitrator(), settings.getAcceptedArbitrators());
|
||||||
|
|
||||||
|
|
||||||
//noinspection UnnecessaryLocalVariable
|
//noinspection UnnecessaryLocalVariable
|
||||||
boolean result = currencyResult
|
boolean result = currencyResult && countryResult && languageResult && amountResult && directionResult && priceResult && arbitratorResult;
|
||||||
&& countryResult
|
|
||||||
&& languageResult
|
|
||||||
&& amountResult
|
|
||||||
&& directionResult
|
|
||||||
&& priceResult
|
|
||||||
&& arbitratorResult;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
log.debug("result = " + result +
|
log.debug("result = " + result +
|
||||||
|
@ -260,8 +264,10 @@ public class OrderBook implements OrderBookListener
|
||||||
for (Country country : list)
|
for (Country country : list)
|
||||||
{
|
{
|
||||||
if (country.getCode().equals(countryToMatch.getCode()))
|
if (country.getCode().equals(countryToMatch.getCode()))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,9 +278,11 @@ public class OrderBook implements OrderBookListener
|
||||||
for (Locale locale2 : list1)
|
for (Locale locale2 : list1)
|
||||||
{
|
{
|
||||||
if (locale1.getLanguage().equals(locale2.getLanguage()))
|
if (locale1.getLanguage().equals(locale2.getLanguage()))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +295,9 @@ public class OrderBook implements OrderBookListener
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (arbitrator.getId().equals(arbitratorToMatch.getId()))
|
if (arbitrator.getId().equals(arbitratorToMatch.getId()))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
} catch (Exception e)
|
} catch (Exception e)
|
||||||
{
|
{
|
||||||
log.error(e.toString());
|
log.error(e.toString());
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.tasks;
|
package io.bitsquare.trade.protocol;
|
||||||
|
|
||||||
public interface FaultHandler
|
public interface FaultHandler
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.tasks;
|
package io.bitsquare.trade.protocol;
|
||||||
|
|
||||||
public interface ResultHandler
|
public interface ResultHandler
|
||||||
{
|
{
|
|
@ -1,22 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.messages.offerer;
|
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
public class AcceptTakeOfferRequestMessage implements Serializable, TradeMessage
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 6177387534087739018L;
|
|
||||||
private final String tradeId;
|
|
||||||
|
|
||||||
public AcceptTakeOfferRequestMessage(String tradeId)
|
|
||||||
{
|
|
||||||
this.tradeId = tradeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTradeId()
|
|
||||||
{
|
|
||||||
return tradeId;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.messages.offerer;
|
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
public class RejectTakeOfferRequestMessage implements Serializable, TradeMessage
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = -8088557759642128139L;
|
|
||||||
private final String tradeId;
|
|
||||||
|
|
||||||
public RejectTakeOfferRequestMessage(String tradeId)
|
|
||||||
{
|
|
||||||
this.tradeId = tradeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTradeId()
|
|
||||||
{
|
|
||||||
return tradeId;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.messages.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
import io.bitsquare.msg.TradeMessage;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -16,7 +16,8 @@ public class BankTransferInitedMessage implements Serializable, TradeMessage
|
||||||
private BigInteger takerPaybackAmount;
|
private BigInteger takerPaybackAmount;
|
||||||
private String offererPayoutAddress;
|
private String offererPayoutAddress;
|
||||||
|
|
||||||
public BankTransferInitedMessage(String tradeId, String depositTxAsHex,
|
public BankTransferInitedMessage(String tradeId,
|
||||||
|
String depositTxAsHex,
|
||||||
String offererSignatureR,
|
String offererSignatureR,
|
||||||
String offererSignatureS,
|
String offererSignatureS,
|
||||||
BigInteger offererPaybackAmount,
|
BigInteger offererPaybackAmount,
|
|
@ -1,10 +1,10 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
import com.google.bitcoin.core.Transaction;
|
import com.google.bitcoin.core.Transaction;
|
||||||
import com.google.bitcoin.core.Utils;
|
import com.google.bitcoin.core.Utils;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -24,11 +24,7 @@ public class CreateDepositTx
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String offererPubKey = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
|
String offererPubKey = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
|
||||||
Transaction transaction = walletFacade.offererCreatesMSTxAndAddPayment(collateralAmount,
|
Transaction transaction = walletFacade.offererCreatesMSTxAndAddPayment(collateralAmount, offererPubKey, takerMultiSigPubKey, arbitratorPubKeyAsHex, tradeId);
|
||||||
offererPubKey,
|
|
||||||
takerMultiSigPubKey,
|
|
||||||
arbitratorPubKeyAsHex,
|
|
||||||
tradeId);
|
|
||||||
|
|
||||||
String preparedOffererDepositTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize());
|
String preparedOffererDepositTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize());
|
||||||
long offererTxOutIndex = transaction.getInput(0).getOutpoint().getIndex();
|
long offererTxOutIndex = transaction.getInput(0).getOutpoint().getIndex();
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.messages.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
import io.bitsquare.msg.TradeMessage;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
|
@ -0,0 +1,44 @@
|
||||||
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
|
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class HandleTakeOfferRequest
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HandleTakeOfferRequest.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade.State tradeState, String tradeId)
|
||||||
|
{
|
||||||
|
boolean takeOfferRequestAccepted = tradeState == Trade.State.OPEN;
|
||||||
|
if (!takeOfferRequestAccepted)
|
||||||
|
{
|
||||||
|
log.info("Received take offer request but the offer not marked as open anymore.");
|
||||||
|
}
|
||||||
|
messageFacade.sendTradeMessage(peerAddress, new RespondToTakeOfferRequestMessage(tradeId, takeOfferRequestAccepted), new OutgoingTradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("RespondToTakeOfferRequestMessage successfully arrived at peer");
|
||||||
|
resultHandler.onResult(takeOfferRequestAccepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer");
|
||||||
|
faultHandler.onFault(new Exception("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ResultHandler
|
||||||
|
{
|
||||||
|
void onResult(boolean takeOfferRequestAccepted);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,368 +10,39 @@ import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.trade.Contract;
|
import io.bitsquare.trade.Contract;
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.taker.PayoutTxPublishedMessage;
|
||||||
import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage;
|
import io.bitsquare.trade.protocol.taker.RequestOffererPublishDepositTxMessage;
|
||||||
import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage;
|
import io.bitsquare.trade.protocol.taker.TakeOfferFeePayedMessage;
|
||||||
import io.bitsquare.trade.protocol.tasks.offerer.*;
|
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.*;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
import static io.bitsquare.util.Validator.*;
|
import static io.bitsquare.util.Validator.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing from the peer.
|
* Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing from the peer.
|
||||||
* That class handles the role of the offerer as the Bitcoin buyer.
|
* <p>
|
||||||
|
* This class handles the role of the offerer as the Bitcoin buyer.
|
||||||
|
* <p>
|
||||||
* It uses sub tasks to not pollute the main class too much with all the async result/fault handling.
|
* It uses sub tasks to not pollute the main class too much with all the async result/fault handling.
|
||||||
* Any data from incoming messages as well data used to send to the peer need to be validated before further processing.
|
* Any data from incoming messages need to be validated before further processing.
|
||||||
*/
|
*/
|
||||||
public class OffererAsBuyerProtocol
|
public class ProtocolForOffererAsBuyer
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(OffererAsBuyerProtocol.class);
|
private static final Logger log = LoggerFactory.getLogger(ProtocolForOffererAsBuyer.class);
|
||||||
public final PeerAddress peerAddress;
|
private final String arbitratorPubKey;
|
||||||
// provided data
|
private final BigInteger collateral;
|
||||||
private final String id;
|
private final BankAccount bankAccount;
|
||||||
private final Trade trade;
|
private final String accountId;
|
||||||
private final OffererAsBuyerProtocolListener listener;
|
private final BigInteger tradeAmount;
|
||||||
private final MessageFacade messageFacade;
|
private final String messagePubKey;
|
||||||
private final WalletFacade walletFacade;
|
private final ECKey accountKey;
|
||||||
private final BlockChainFacade blockChainFacade;
|
private final String payoutAddress;
|
||||||
private final CryptoFacade cryptoFacade;
|
|
||||||
private final User user;
|
|
||||||
private final String tradeId;
|
|
||||||
private final Offer offer;
|
|
||||||
|
|
||||||
// data written/read by tasks
|
|
||||||
private String preparedOffererDepositTxAsHex;
|
|
||||||
private long offererTxOutIndex;
|
|
||||||
// data written by messages, read by tasks
|
|
||||||
private String takeOfferFeeTxId;
|
|
||||||
private String takerMultiSigPubKey;
|
|
||||||
private String takerPayoutAddress;
|
|
||||||
private String peersAccountId;
|
|
||||||
private BankAccount peersBankAccount;
|
|
||||||
private String takerMessagePubKey;
|
|
||||||
private String peersContractAsJson;
|
|
||||||
private String signedTakerDepositTxAsHex;
|
|
||||||
private String txConnOutAsHex;
|
|
||||||
private String txScriptSigAsHex;
|
|
||||||
private long takerTxOutIndex;
|
|
||||||
// private
|
|
||||||
private State state;
|
|
||||||
|
|
||||||
public OffererAsBuyerProtocol(Trade trade,
|
|
||||||
PeerAddress peerAddress,
|
|
||||||
MessageFacade messageFacade,
|
|
||||||
WalletFacade walletFacade,
|
|
||||||
BlockChainFacade blockChainFacade,
|
|
||||||
CryptoFacade cryptoFacade,
|
|
||||||
User user,
|
|
||||||
OffererAsBuyerProtocolListener listener)
|
|
||||||
{
|
|
||||||
this.trade = trade;
|
|
||||||
this.peerAddress = peerAddress;
|
|
||||||
this.listener = listener;
|
|
||||||
this.messageFacade = messageFacade;
|
|
||||||
this.walletFacade = walletFacade;
|
|
||||||
this.blockChainFacade = blockChainFacade;
|
|
||||||
this.cryptoFacade = cryptoFacade;
|
|
||||||
this.user = user;
|
|
||||||
|
|
||||||
id = trade.getId();
|
|
||||||
|
|
||||||
tradeId = trade.getId();
|
|
||||||
offer = trade.getOffer();
|
|
||||||
|
|
||||||
state = State.Init;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void start()
|
|
||||||
{
|
|
||||||
log.debug("start");
|
|
||||||
HandleTakeOfferRequest.run(this::onResultHandleTakeOfferRequest, this::onFault, peerAddress, messageFacade, trade.getState(), tradeId);
|
|
||||||
state = State.HandleTakeOfferRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultHandleTakeOfferRequest(Trade.State tradeState)
|
|
||||||
{
|
|
||||||
log.debug("onResultHandleTakeOfferRequest");
|
|
||||||
trade.setState(tradeState);
|
|
||||||
messageFacade.removeOffer(offer);
|
|
||||||
listener.onOfferAccepted(offer);
|
|
||||||
listener.onWaitingForPeerResponse(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onTakeOfferFeePayedMessage(TakeOfferFeePayedMessage message)
|
|
||||||
{
|
|
||||||
log.debug("onTakeOfferFeePayedMessage");
|
|
||||||
|
|
||||||
// validation
|
|
||||||
checkState(state == State.HandleTakeOfferRequest);
|
|
||||||
checkNotNull(message);
|
|
||||||
String takeOfferFeeTxId = nonEmptyStringOf(message.getTakeOfferFeeTxId());
|
|
||||||
BigInteger tradeAmount = nonNegativeBigIntegerOf(nonZeroBigIntegerOf(message.getTradeAmount()));
|
|
||||||
String takerMultiSigPubKey = nonEmptyStringOf(message.getTakerMultiSigPubKey());
|
|
||||||
|
|
||||||
// apply new state
|
|
||||||
state = State.onTakeOfferFeePayedMessage;
|
|
||||||
this.takeOfferFeeTxId = takeOfferFeeTxId;
|
|
||||||
this.takerMultiSigPubKey = takerMultiSigPubKey;
|
|
||||||
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
|
|
||||||
trade.setTradeAmount(tradeAmount);
|
|
||||||
|
|
||||||
// next task
|
|
||||||
VerifyTakeOfferFeePayment.run(this::onResultVerifyTakeOfferFeePayment, this::onFault, walletFacade, takeOfferFeeTxId);
|
|
||||||
state = State.VerifyTakeOfferFeePayment;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Incoming message from peer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onResultVerifyTakeOfferFeePayment()
|
|
||||||
{
|
|
||||||
log.debug("onResultVerifyTakeOfferFeePayment");
|
|
||||||
BigInteger collateralAmount = trade.getCollateralAmount();
|
|
||||||
String arbitratorPubKeyAsHex = offer.getArbitrator().getPubKeyAsHex();
|
|
||||||
|
|
||||||
CreateDepositTx.run(this::onResultCreateDepositTx,
|
|
||||||
this::onFault,
|
|
||||||
walletFacade,
|
|
||||||
tradeId,
|
|
||||||
collateralAmount,
|
|
||||||
takerMultiSigPubKey,
|
|
||||||
arbitratorPubKeyAsHex);
|
|
||||||
|
|
||||||
state = State.CreateDepositTx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultCreateDepositTx(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex)
|
|
||||||
{
|
|
||||||
log.debug("onResultCreateDepositTx");
|
|
||||||
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
|
|
||||||
this.offererTxOutIndex = offererTxOutIndex;
|
|
||||||
|
|
||||||
BankAccount bankAccount = user.getBankAccount(trade.getOffer().getBankAccountId());
|
|
||||||
String accountId = user.getAccountId();
|
|
||||||
|
|
||||||
RequestTakerDepositPayment.run(this::onResultRequestTakerDepositPayment,
|
|
||||||
this::onFault,
|
|
||||||
peerAddress,
|
|
||||||
messageFacade,
|
|
||||||
tradeId,
|
|
||||||
bankAccount,
|
|
||||||
accountId,
|
|
||||||
offererPubKey,
|
|
||||||
preparedOffererDepositTxAsHex,
|
|
||||||
offererTxOutIndex);
|
|
||||||
|
|
||||||
state = State.RequestTakerDepositPayment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultRequestTakerDepositPayment()
|
|
||||||
{
|
|
||||||
log.debug("onResultRequestTakerDepositPayment");
|
|
||||||
listener.onWaitingForPeerResponse(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message)
|
|
||||||
{
|
|
||||||
log.debug("onRequestOffererPublishDepositTxMessage");
|
|
||||||
|
|
||||||
// validation
|
|
||||||
checkState(state == State.RequestTakerDepositPayment);
|
|
||||||
checkNotNull(message);
|
|
||||||
String takerPayoutAddress = nonEmptyStringOf(message.getTakerPayoutAddress());
|
|
||||||
String peersAccountId = nonEmptyStringOf(message.getAccountId());
|
|
||||||
BankAccount peersBankAccount = checkNotNull(message.getBankAccount());
|
|
||||||
String takerMessagePubKey = nonEmptyStringOf(message.getTakerMessagePubKey());
|
|
||||||
String peersContractAsJson = nonEmptyStringOf(message.getContractAsJson());
|
|
||||||
String signedTakerDepositTxAsHex = nonEmptyStringOf(message.getSignedTakerDepositTxAsHex());
|
|
||||||
String txConnOutAsHex = nonEmptyStringOf(message.getTxConnOutAsHex());
|
|
||||||
String txScriptSigAsHex = nonEmptyStringOf(message.getTxScriptSigAsHex());
|
|
||||||
long takerTxOutIndex = nonNegativeLongOf(message.getTakerTxOutIndex());
|
|
||||||
|
|
||||||
// apply new state
|
|
||||||
state = State.onRequestOffererPublishDepositTxMessage;
|
|
||||||
this.takerPayoutAddress = takerPayoutAddress;
|
|
||||||
this.peersAccountId = peersAccountId;
|
|
||||||
this.peersBankAccount = peersBankAccount;
|
|
||||||
this.takerMessagePubKey = takerMessagePubKey;
|
|
||||||
this.peersContractAsJson = peersContractAsJson;
|
|
||||||
this.signedTakerDepositTxAsHex = signedTakerDepositTxAsHex;
|
|
||||||
this.txConnOutAsHex = txConnOutAsHex;
|
|
||||||
this.txScriptSigAsHex = txScriptSigAsHex;
|
|
||||||
this.takerTxOutIndex = takerTxOutIndex;
|
|
||||||
|
|
||||||
// next task
|
|
||||||
VerifyTakerAccount.run(this::onResultVerifyTakerAccount, this::onFault, blockChainFacade, peersAccountId, peersBankAccount);
|
|
||||||
state = State.VerifyTakerAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Incoming message from peer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onResultVerifyTakerAccount()
|
|
||||||
{
|
|
||||||
log.debug("onResultVerifyTakerAccount");
|
|
||||||
|
|
||||||
String accountId = user.getAccountId();
|
|
||||||
BigInteger tradeAmount = trade.getTradeAmount();
|
|
||||||
String messagePubKeyAsHex = user.getMessagePubKeyAsHex();
|
|
||||||
BankAccount bankAccount = user.getBankAccount(offer.getBankAccountId());
|
|
||||||
ECKey registrationKey = walletFacade.getRegistrationAddressInfo().getKey();
|
|
||||||
|
|
||||||
VerifyAndSignContract.run(this::onResultVerifyAndSignContract,
|
|
||||||
this::onFault,
|
|
||||||
cryptoFacade,
|
|
||||||
accountId,
|
|
||||||
tradeAmount,
|
|
||||||
takeOfferFeeTxId,
|
|
||||||
messagePubKeyAsHex,
|
|
||||||
offer,
|
|
||||||
peersAccountId,
|
|
||||||
bankAccount,
|
|
||||||
peersBankAccount,
|
|
||||||
takerMessagePubKey,
|
|
||||||
peersContractAsJson,
|
|
||||||
registrationKey);
|
|
||||||
|
|
||||||
state = State.VerifyAndSignContract;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultVerifyAndSignContract(Contract contract, String contractAsJson, String signature)
|
|
||||||
{
|
|
||||||
log.debug("onResultVerifyAndSignContract");
|
|
||||||
|
|
||||||
trade.setContract(contract);
|
|
||||||
trade.setContractAsJson(contractAsJson);
|
|
||||||
trade.setContractTakerSignature(signature);
|
|
||||||
|
|
||||||
SignAndPublishDepositTx.run(this::onResultSignAndPublishDepositTx,
|
|
||||||
this::onFault,
|
|
||||||
walletFacade,
|
|
||||||
preparedOffererDepositTxAsHex,
|
|
||||||
signedTakerDepositTxAsHex,
|
|
||||||
txConnOutAsHex,
|
|
||||||
txScriptSigAsHex,
|
|
||||||
offererTxOutIndex,
|
|
||||||
takerTxOutIndex);
|
|
||||||
state = State.SignAndPublishDepositTx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultSignAndPublishDepositTx(Transaction transaction)
|
|
||||||
{
|
|
||||||
log.debug("onResultSignAndPublishDepositTx");
|
|
||||||
|
|
||||||
trade.setDepositTransaction(transaction);
|
|
||||||
listener.onDepositTxPublished(transaction.getHashAsString());
|
|
||||||
|
|
||||||
Transaction depositTransaction = trade.getDepositTransaction();
|
|
||||||
SendDepositTxIdToTaker.run(this::onResultSendDepositTxIdToTaker, this::onFault, peerAddress, messageFacade, tradeId, depositTransaction);
|
|
||||||
state = State.SendDepositTxIdToTaker;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultSendDepositTxIdToTaker()
|
|
||||||
{
|
|
||||||
log.debug("onResultSendDepositTxIdToTaker");
|
|
||||||
|
|
||||||
SetupListenerForBlockChainConfirmation.run(this::onResultSetupListenerForBlockChainConfirmation, this::onFault, trade.getDepositTransaction(), listener);
|
|
||||||
state = State.SetupListenerForBlockChainConfirmation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultSetupListenerForBlockChainConfirmation()
|
|
||||||
{
|
|
||||||
log.debug("onResultSetupListenerForBlockChainConfirmation");
|
|
||||||
|
|
||||||
state = State.onResultSetupListenerForBlockChainConfirmation;
|
|
||||||
listener.onWaitingForUserInteraction(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Triggered from UI event: Button click "Bank transfer inited"
|
|
||||||
public void onUIEventBankTransferInited()
|
|
||||||
{
|
|
||||||
log.debug("onUIEventBankTransferInited");
|
|
||||||
|
|
||||||
// validation
|
|
||||||
checkState(state == State.onResultSetupListenerForBlockChainConfirmation);
|
|
||||||
|
|
||||||
state = State.onUIEventBankTransferInited;
|
|
||||||
|
|
||||||
// next task
|
|
||||||
String depositTransactionId = trade.getDepositTransaction().getHashAsString();
|
|
||||||
String offererPayoutAddress = walletFacade.getAddressInfoByTradeID(tradeId).getAddressString();
|
|
||||||
BigInteger collateral = trade.getCollateralAmount();
|
|
||||||
BigInteger tradeAmount = trade.getTradeAmount();
|
|
||||||
SendSignedPayoutTx.run(this::onResultSendSignedPayoutTx, this::onFault, peerAddress, messageFacade, walletFacade, tradeId, takerPayoutAddress, offererPayoutAddress, depositTransactionId, collateral, tradeAmount);
|
|
||||||
state = State.SendSignedPayoutTx;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Triggered UI event
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onResultSendSignedPayoutTx()
|
|
||||||
{
|
|
||||||
log.debug("onResultSendSignedPayoutTx");
|
|
||||||
|
|
||||||
listener.onWaitingForPeerResponse(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPayoutTxPublishedMessage(PayoutTxPublishedMessage tradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("onPayoutTxPublishedMessage");
|
|
||||||
|
|
||||||
// validation
|
|
||||||
checkState(state == State.SendSignedPayoutTx);
|
|
||||||
String payoutTxAsHex = nonEmptyStringOf(tradeMessage.getPayoutTxAsHex());
|
|
||||||
|
|
||||||
state = State.onPayoutTxPublishedMessage;
|
|
||||||
|
|
||||||
// next task
|
|
||||||
listener.onPayoutTxPublished(payoutTxAsHex);
|
|
||||||
listener.onCompleted(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Incoming message from peer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public String getId()
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Getters, Setters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// generic fault handler
|
|
||||||
private void onFault(Throwable throwable)
|
|
||||||
{
|
|
||||||
listener.onFault(throwable, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Private
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public enum State
|
public enum State
|
||||||
{
|
{
|
||||||
|
@ -397,4 +68,351 @@ public class OffererAsBuyerProtocol
|
||||||
onPayoutTxPublishedMessage
|
onPayoutTxPublishedMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Trade trade;
|
||||||
|
private final PeerAddress peerAddress;
|
||||||
|
private final MessageFacade messageFacade;
|
||||||
|
private final WalletFacade walletFacade;
|
||||||
|
private final BlockChainFacade blockChainFacade;
|
||||||
|
private final CryptoFacade cryptoFacade;
|
||||||
|
private final ProtocolForOffererAsBuyerListener listener;
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
private final String tradeId;
|
||||||
|
private final Offer offer;
|
||||||
|
|
||||||
|
private State state;
|
||||||
|
|
||||||
|
// data written/read by tasks
|
||||||
|
private String preparedOffererDepositTxAsHex;
|
||||||
|
private long offererTxOutIndex;
|
||||||
|
|
||||||
|
// data written by messages, read by tasks
|
||||||
|
private String takeOfferFeeTxId;
|
||||||
|
private String takerPubKey;
|
||||||
|
private String peersPayoutAddress;
|
||||||
|
private String peersAccountId;
|
||||||
|
private BankAccount peersBankAccount;
|
||||||
|
private String peersMessagePubKey;
|
||||||
|
private String peersContractAsJson;
|
||||||
|
private String signedTakerDepositTxAsHex;
|
||||||
|
private String txConnOutAsHex;
|
||||||
|
private String txScriptSigAsHex;
|
||||||
|
private long takerTxOutIndex;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public ProtocolForOffererAsBuyer(Trade trade,
|
||||||
|
PeerAddress peerAddress,
|
||||||
|
MessageFacade messageFacade,
|
||||||
|
WalletFacade walletFacade,
|
||||||
|
BlockChainFacade blockChainFacade,
|
||||||
|
CryptoFacade cryptoFacade,
|
||||||
|
User user,
|
||||||
|
ProtocolForOffererAsBuyerListener listener)
|
||||||
|
{
|
||||||
|
this.trade = trade;
|
||||||
|
this.peerAddress = peerAddress;
|
||||||
|
this.listener = listener;
|
||||||
|
this.messageFacade = messageFacade;
|
||||||
|
this.walletFacade = walletFacade;
|
||||||
|
this.blockChainFacade = blockChainFacade;
|
||||||
|
this.cryptoFacade = cryptoFacade;
|
||||||
|
|
||||||
|
id = trade.getId();
|
||||||
|
|
||||||
|
tradeId = trade.getId();
|
||||||
|
offer = trade.getOffer();
|
||||||
|
arbitratorPubKey = offer.getArbitrator().getPubKeyAsHex();
|
||||||
|
collateral = trade.getCollateralAmount();
|
||||||
|
bankAccount = user.getBankAccount(trade.getOffer().getBankAccountId());
|
||||||
|
accountId = user.getAccountId();
|
||||||
|
tradeAmount = trade.getTradeAmount();
|
||||||
|
messagePubKey = user.getMessagePubKeyAsHex();
|
||||||
|
accountKey = walletFacade.getRegistrationAddressInfo().getKey();
|
||||||
|
payoutAddress = walletFacade.getAddressInfoByTradeID(tradeId).getAddressString();
|
||||||
|
state = State.Init;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
log.debug("start called ");
|
||||||
|
HandleTakeOfferRequest.run(this::onResultHandleTakeOfferRequest, this::onFault, peerAddress, messageFacade, trade.getState(), tradeId);
|
||||||
|
state = State.HandleTakeOfferRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultHandleTakeOfferRequest(boolean takeOfferRequestAccepted)
|
||||||
|
{
|
||||||
|
log.debug("onResultHandleTakeOfferRequest called ");
|
||||||
|
if (takeOfferRequestAccepted)
|
||||||
|
{
|
||||||
|
trade.setState(Trade.State.ACCEPTED);
|
||||||
|
messageFacade.removeOffer(offer);
|
||||||
|
listener.onOfferAccepted(offer);
|
||||||
|
listener.onWaitingForPeerResponse(state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.info("Finish here as we have already the offer accepted.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Incoming message from peer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void onTakeOfferFeePayedMessage(@NotNull TakeOfferFeePayedMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onTakeOfferFeePayedMessage called ");
|
||||||
|
|
||||||
|
// validation
|
||||||
|
checkState(state == State.HandleTakeOfferRequest);
|
||||||
|
checkArgument(tradeId.equals(message.getTradeId()));
|
||||||
|
String takeOfferFeeTxId = nonEmptyStringOf(message.getTakeOfferFeeTxId());
|
||||||
|
BigInteger tradeAmount = nonNegativeBigIntegerOf(nonZeroBigIntegerOf(message.getTradeAmount()));
|
||||||
|
String takerPubKey = nonEmptyStringOf(message.getTakerPubKey());
|
||||||
|
|
||||||
|
// apply new state
|
||||||
|
state = State.onTakeOfferFeePayedMessage;
|
||||||
|
this.takeOfferFeeTxId = takeOfferFeeTxId;
|
||||||
|
this.takerPubKey = takerPubKey;
|
||||||
|
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
|
||||||
|
trade.setTradeAmount(tradeAmount);
|
||||||
|
|
||||||
|
// next task
|
||||||
|
VerifyTakeOfferFeePayment.run(this::onResultVerifyTakeOfferFeePayment, this::onFault, walletFacade, this.takeOfferFeeTxId);
|
||||||
|
state = State.VerifyTakeOfferFeePayment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultVerifyTakeOfferFeePayment()
|
||||||
|
{
|
||||||
|
log.debug("onResultVerifyTakeOfferFeePayment called ");
|
||||||
|
|
||||||
|
CreateDepositTx.run(this::onResultCreateDepositTx, this::onFault, walletFacade, tradeId, collateral, takerPubKey, arbitratorPubKey);
|
||||||
|
|
||||||
|
state = State.CreateDepositTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultCreateDepositTx(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex)
|
||||||
|
{
|
||||||
|
log.debug("onResultCreateDepositTx called ");
|
||||||
|
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
|
||||||
|
this.offererTxOutIndex = offererTxOutIndex;
|
||||||
|
|
||||||
|
|
||||||
|
RequestTakerDepositPayment.run(this::onResultRequestTakerDepositPayment,
|
||||||
|
this::onFault,
|
||||||
|
peerAddress,
|
||||||
|
messageFacade,
|
||||||
|
tradeId,
|
||||||
|
bankAccount,
|
||||||
|
accountId,
|
||||||
|
offererPubKey,
|
||||||
|
preparedOffererDepositTxAsHex,
|
||||||
|
offererTxOutIndex);
|
||||||
|
|
||||||
|
state = State.RequestTakerDepositPayment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultRequestTakerDepositPayment()
|
||||||
|
{
|
||||||
|
log.debug("onResultRequestTakerDepositPayment called ");
|
||||||
|
listener.onWaitingForPeerResponse(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Incoming message from peer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void onRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onRequestOffererPublishDepositTxMessage called ");
|
||||||
|
|
||||||
|
// validation
|
||||||
|
checkState(state == State.RequestTakerDepositPayment);
|
||||||
|
checkArgument(tradeId.equals(message.getTradeId()));
|
||||||
|
String peersPayoutAddress = nonEmptyStringOf(message.getTakerPayoutAddress());
|
||||||
|
String peersAccountId = nonEmptyStringOf(message.getTakerAccountId());
|
||||||
|
BankAccount peersBankAccount = checkNotNull(message.getTakerBankAccount());
|
||||||
|
String peersMessagePubKey = nonEmptyStringOf(message.getTakerMessagePubKey());
|
||||||
|
String peersContractAsJson = nonEmptyStringOf(message.getTakerContractAsJson());
|
||||||
|
String signedTakerDepositTxAsHex = nonEmptyStringOf(message.getSignedTakerDepositTxAsHex());
|
||||||
|
String txConnOutAsHex = nonEmptyStringOf(message.getTxConnOutAsHex());
|
||||||
|
String txScriptSigAsHex = nonEmptyStringOf(message.getTxScriptSigAsHex());
|
||||||
|
long takerTxOutIndex = nonNegativeLongOf(message.getTakerTxOutIndex());
|
||||||
|
|
||||||
|
// apply new state
|
||||||
|
state = State.onRequestOffererPublishDepositTxMessage;
|
||||||
|
this.peersPayoutAddress = peersPayoutAddress;
|
||||||
|
this.peersAccountId = peersAccountId;
|
||||||
|
this.peersBankAccount = peersBankAccount;
|
||||||
|
this.peersMessagePubKey = peersMessagePubKey;
|
||||||
|
this.peersContractAsJson = peersContractAsJson;
|
||||||
|
this.signedTakerDepositTxAsHex = signedTakerDepositTxAsHex;
|
||||||
|
this.txConnOutAsHex = txConnOutAsHex;
|
||||||
|
this.txScriptSigAsHex = txScriptSigAsHex;
|
||||||
|
this.takerTxOutIndex = takerTxOutIndex;
|
||||||
|
|
||||||
|
// next task
|
||||||
|
VerifyTakerAccount.run(this::onResultVerifyTakerAccount, this::onFault, blockChainFacade, this.peersAccountId, this.peersBankAccount);
|
||||||
|
state = State.VerifyTakerAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultVerifyTakerAccount()
|
||||||
|
{
|
||||||
|
log.debug("onResultVerifyTakerAccount called ");
|
||||||
|
|
||||||
|
VerifyAndSignContract.run(this::onResultVerifyAndSignContract,
|
||||||
|
this::onFault,
|
||||||
|
cryptoFacade,
|
||||||
|
accountId,
|
||||||
|
tradeAmount,
|
||||||
|
takeOfferFeeTxId,
|
||||||
|
messagePubKey,
|
||||||
|
offer,
|
||||||
|
peersAccountId,
|
||||||
|
bankAccount,
|
||||||
|
peersBankAccount,
|
||||||
|
peersMessagePubKey,
|
||||||
|
peersContractAsJson,
|
||||||
|
accountKey);
|
||||||
|
|
||||||
|
state = State.VerifyAndSignContract;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultVerifyAndSignContract(Contract contract, String contractAsJson, String signature)
|
||||||
|
{
|
||||||
|
log.debug("onResultVerifyAndSignContract called ");
|
||||||
|
|
||||||
|
trade.setContract(contract);
|
||||||
|
trade.setContractAsJson(contractAsJson);
|
||||||
|
trade.setContractTakerSignature(signature);
|
||||||
|
|
||||||
|
SignAndPublishDepositTx.run(this::onResultSignAndPublishDepositTx,
|
||||||
|
this::onFault,
|
||||||
|
walletFacade,
|
||||||
|
preparedOffererDepositTxAsHex,
|
||||||
|
signedTakerDepositTxAsHex,
|
||||||
|
txConnOutAsHex,
|
||||||
|
txScriptSigAsHex,
|
||||||
|
offererTxOutIndex,
|
||||||
|
takerTxOutIndex);
|
||||||
|
state = State.SignAndPublishDepositTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultSignAndPublishDepositTx(Transaction depositTransaction)
|
||||||
|
{
|
||||||
|
log.debug("onResultSignAndPublishDepositTx called ");
|
||||||
|
|
||||||
|
trade.setDepositTransaction(depositTransaction);
|
||||||
|
listener.onDepositTxPublished(depositTransaction.getHashAsString());
|
||||||
|
|
||||||
|
SendDepositTxIdToTaker.run(this::onResultSendDepositTxIdToTaker, this::onFault, peerAddress, messageFacade, tradeId, depositTransaction);
|
||||||
|
state = State.SendDepositTxIdToTaker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultSendDepositTxIdToTaker()
|
||||||
|
{
|
||||||
|
log.debug("onResultSendDepositTxIdToTaker called ");
|
||||||
|
|
||||||
|
SetupListenerForBlockChainConfirmation.run(this::onResultSetupListenerForBlockChainConfirmation, this::onFault, trade.getDepositTransaction(), listener);
|
||||||
|
state = State.SetupListenerForBlockChainConfirmation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultSetupListenerForBlockChainConfirmation()
|
||||||
|
{
|
||||||
|
log.debug("onResultSetupListenerForBlockChainConfirmation called ");
|
||||||
|
|
||||||
|
state = State.onResultSetupListenerForBlockChainConfirmation;
|
||||||
|
listener.onWaitingForUserInteraction(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Triggered UI event
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Triggered from UI event: Button click "Bank transfer inited"
|
||||||
|
public void onUIEventBankTransferInited()
|
||||||
|
{
|
||||||
|
log.debug("onUIEventBankTransferInited called ");
|
||||||
|
|
||||||
|
// validation
|
||||||
|
checkState(state == State.onResultSetupListenerForBlockChainConfirmation);
|
||||||
|
|
||||||
|
|
||||||
|
state = State.onUIEventBankTransferInited;
|
||||||
|
|
||||||
|
// next task
|
||||||
|
String depositTransactionId = trade.getDepositTransaction().getHashAsString();
|
||||||
|
|
||||||
|
SendSignedPayoutTx.run(this::onResultSendSignedPayoutTx,
|
||||||
|
this::onFault,
|
||||||
|
peerAddress,
|
||||||
|
messageFacade,
|
||||||
|
walletFacade,
|
||||||
|
tradeId,
|
||||||
|
peersPayoutAddress,
|
||||||
|
payoutAddress,
|
||||||
|
depositTransactionId,
|
||||||
|
collateral,
|
||||||
|
tradeAmount);
|
||||||
|
state = State.SendSignedPayoutTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultSendSignedPayoutTx()
|
||||||
|
{
|
||||||
|
log.debug("onResultSendSignedPayoutTx called ");
|
||||||
|
|
||||||
|
listener.onWaitingForPeerResponse(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Incoming message from peer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void onPayoutTxPublishedMessage(PayoutTxPublishedMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onPayoutTxPublishedMessage called ");
|
||||||
|
|
||||||
|
// validation
|
||||||
|
checkState(state == State.SendSignedPayoutTx);
|
||||||
|
checkArgument(tradeId.equals(message.getTradeId()));
|
||||||
|
String payoutTxAsHex = nonEmptyStringOf(message.getPayoutTxAsHex());
|
||||||
|
|
||||||
|
state = State.onPayoutTxPublishedMessage;
|
||||||
|
|
||||||
|
// next task
|
||||||
|
listener.onPayoutTxPublished(payoutTxAsHex);
|
||||||
|
listener.onCompleted(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Getters, Setters
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// generic fault handler
|
||||||
|
private void onFault(Throwable throwable)
|
||||||
|
{
|
||||||
|
listener.onFault(throwable, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ package io.bitsquare.trade.protocol.offerer;
|
||||||
import com.google.bitcoin.core.TransactionConfidence;
|
import com.google.bitcoin.core.TransactionConfidence;
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
|
|
||||||
public interface OffererAsBuyerProtocolListener
|
public interface ProtocolForOffererAsBuyerListener
|
||||||
{
|
{
|
||||||
void onOfferAccepted(Offer offer);
|
void onOfferAccepted(Offer offer);
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@ public interface OffererAsBuyerProtocolListener
|
||||||
|
|
||||||
void onPayoutTxPublished(String payoutTxID);
|
void onPayoutTxPublished(String payoutTxID);
|
||||||
|
|
||||||
void onFault(Throwable throwable, OffererAsBuyerProtocol.State state);
|
void onFault(Throwable throwable, ProtocolForOffererAsBuyer.State state);
|
||||||
|
|
||||||
void onWaitingForPeerResponse(OffererAsBuyerProtocol.State state);
|
void onWaitingForPeerResponse(ProtocolForOffererAsBuyer.State state);
|
||||||
|
|
||||||
void onCompleted(OffererAsBuyerProtocol.State state);
|
void onCompleted(ProtocolForOffererAsBuyer.State state);
|
||||||
|
|
||||||
void onWaitingForUserInteraction(OffererAsBuyerProtocol.State state);
|
void onWaitingForUserInteraction(ProtocolForOffererAsBuyer.State state);
|
||||||
}
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.RequestTakerDepositPaymentMessage;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -25,12 +24,7 @@ public class RequestTakerDepositPayment
|
||||||
String preparedOffererDepositTxAsHex,
|
String preparedOffererDepositTxAsHex,
|
||||||
long offererTxOutIndex)
|
long offererTxOutIndex)
|
||||||
{
|
{
|
||||||
RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(tradeId,
|
RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(tradeId, bankAccount, accountId, offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex);
|
||||||
bankAccount,
|
|
||||||
accountId,
|
|
||||||
offererPubKey,
|
|
||||||
preparedOffererDepositTxAsHex,
|
|
||||||
offererTxOutIndex);
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.messages.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.msg.TradeMessage;
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
@ -9,7 +9,6 @@ public class RequestTakerDepositPaymentMessage implements Serializable, TradeMes
|
||||||
private static final long serialVersionUID = -3988720410493712913L;
|
private static final long serialVersionUID = -3988720410493712913L;
|
||||||
|
|
||||||
private final String tradeId;
|
private final String tradeId;
|
||||||
|
|
||||||
private BankAccount bankAccount;
|
private BankAccount bankAccount;
|
||||||
private String accountID;
|
private String accountID;
|
||||||
private String offererPubKey;
|
private String offererPubKey;
|
||||||
|
@ -37,7 +36,7 @@ public class RequestTakerDepositPaymentMessage implements Serializable, TradeMes
|
||||||
return bankAccount;
|
return bankAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAccountID()
|
public String getAccountId()
|
||||||
{
|
{
|
||||||
return accountID;
|
return accountID;
|
||||||
}
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class RespondToTakeOfferRequestMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 6177387534087739018L;
|
||||||
|
private final String tradeId;
|
||||||
|
private boolean takeOfferRequestAccepted;
|
||||||
|
|
||||||
|
public RespondToTakeOfferRequestMessage(String tradeId, boolean takeOfferRequestAccepted)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
this.takeOfferRequestAccepted = takeOfferRequestAccepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTakeOfferRequestAccepted()
|
||||||
|
{
|
||||||
|
return takeOfferRequestAccepted;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
import com.google.bitcoin.core.Transaction;
|
||||||
import com.google.bitcoin.core.Utils;
|
import com.google.bitcoin.core.Utils;
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.DepositTxPublishedMessage;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
|
@ -1,12 +1,11 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import com.google.bitcoin.core.ECKey;
|
import com.google.bitcoin.core.ECKey;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.BankTransferInitedMessage;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
@ -34,11 +33,7 @@ public class SendSignedPayoutTx
|
||||||
BigInteger offererPaybackAmount = tradeAmount.add(collateral);
|
BigInteger offererPaybackAmount = tradeAmount.add(collateral);
|
||||||
BigInteger takerPaybackAmount = collateral;
|
BigInteger takerPaybackAmount = collateral;
|
||||||
|
|
||||||
Pair<ECKey.ECDSASignature, String> result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransactionId,
|
Pair<ECKey.ECDSASignature, String> result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransactionId, offererPaybackAmount, takerPaybackAmount, takerPayoutAddress, tradeId);
|
||||||
offererPaybackAmount,
|
|
||||||
takerPaybackAmount,
|
|
||||||
takerPayoutAddress,
|
|
||||||
tradeId);
|
|
||||||
|
|
||||||
ECKey.ECDSASignature offererSignature = result.getKey();
|
ECKey.ECDSASignature offererSignature = result.getKey();
|
||||||
String offererSignatureR = offererSignature.r.toString();
|
String offererSignatureR = offererSignature.r.toString();
|
|
@ -0,0 +1,38 @@
|
||||||
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.bitcoin.core.TransactionConfidence;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SetupListenerForBlockChainConfirmation
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, Transaction depositTransaction, ProtocolForOffererAsBuyerListener listener)
|
||||||
|
{ //TODO
|
||||||
|
// sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
|
||||||
|
|
||||||
|
depositTransaction.getConfidence().addEventListener(new TransactionConfidence.Listener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onConfidenceChanged(Transaction tx, ChangeReason reason)
|
||||||
|
{
|
||||||
|
log.trace("onConfidenceChanged " + tx.getConfidence());
|
||||||
|
if (reason == ChangeReason.SEEN_PEERS)
|
||||||
|
{
|
||||||
|
listener.onDepositTxConfirmedUpdate(tx.getConfidence());
|
||||||
|
}
|
||||||
|
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||||
|
{
|
||||||
|
listener.onDepositTxConfirmedInBlockchain();
|
||||||
|
depositTransaction.getConfidence().removeEventListener(this);
|
||||||
|
log.trace("Tx is in blockchain");
|
||||||
|
resultHandler.onResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import io.bitsquare.btc.WalletFacade;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SignAndPublishDepositTx
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler,
|
||||||
|
FaultHandler faultHandler,
|
||||||
|
WalletFacade walletFacade,
|
||||||
|
String preparedOffererDepositTxAsHex,
|
||||||
|
String signedTakerDepositTxAsHex,
|
||||||
|
String txConnOutAsHex,
|
||||||
|
String txScriptSigAsHex,
|
||||||
|
long offererTxOutIndex,
|
||||||
|
long takerTxOutIndex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
walletFacade.offererSignAndPublishTx(preparedOffererDepositTxAsHex,
|
||||||
|
signedTakerDepositTxAsHex,
|
||||||
|
txConnOutAsHex,
|
||||||
|
txScriptSigAsHex,
|
||||||
|
offererTxOutIndex,
|
||||||
|
takerTxOutIndex,
|
||||||
|
new FutureCallback<Transaction>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction)
|
||||||
|
{
|
||||||
|
log.trace("offererSignAndPublishTx succeeded " + transaction);
|
||||||
|
resultHandler.onResult(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t)
|
||||||
|
{
|
||||||
|
log.error("offererSignAndPublishTx faultHandler.onFault:" + t);
|
||||||
|
faultHandler.onFault(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("offererSignAndPublishTx faultHandler.onFault:" + e);
|
||||||
|
faultHandler.onFault(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ResultHandler
|
||||||
|
{
|
||||||
|
void onResult(Transaction depositTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import com.google.bitcoin.core.ECKey;
|
import com.google.bitcoin.core.ECKey;
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
import io.bitsquare.trade.Contract;
|
import io.bitsquare.trade.Contract;
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.util.Utilities;
|
import io.bitsquare.util.Utilities;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -30,15 +30,7 @@ public class VerifyAndSignContract
|
||||||
String peersContractAsJson,
|
String peersContractAsJson,
|
||||||
ECKey registrationKey)
|
ECKey registrationKey)
|
||||||
{
|
{
|
||||||
Contract contract = new Contract(offer,
|
Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, accountId, peersAccountId, bankAccount, peersBankAccount, messagePubKeyAsHex, takerMessagePubKey);
|
||||||
tradeAmount,
|
|
||||||
takeOfferFeeTxId,
|
|
||||||
accountId,
|
|
||||||
peersAccountId,
|
|
||||||
bankAccount,
|
|
||||||
peersBankAccount,
|
|
||||||
messagePubKeyAsHex,
|
|
||||||
takerMessagePubKey);
|
|
||||||
|
|
||||||
String contractAsJson = Utilities.objectToJson(contract);
|
String contractAsJson = Utilities.objectToJson(contract);
|
||||||
// log.trace("Offerer contract created: " + contract);
|
// log.trace("Offerer contract created: " + contract);
|
|
@ -1,8 +1,8 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package io.bitsquare.trade.protocol.offerer;
|
||||||
|
|
||||||
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
|
import io.bitsquare.trade.protocol.shared.VerifyPeerAccount;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class VerifyTakerAccount
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount)
|
||||||
|
{
|
||||||
|
VerifyPeerAccount.run(resultHandler, faultHandler, blockChainFacade, peersAccountId, peersBankAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.mock;
|
package io.bitsquare.trade.protocol.old;
|
||||||
|
|
||||||
//TODO not used but let it for reference until all use cases are impl.
|
//TODO not used but let it for reference until all use cases are impl.
|
||||||
class BuyOffererPaymentProcess extends PaymentProcess
|
class BuyOffererPaymentProcess extends PaymentProcess
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.mock;
|
package io.bitsquare.trade.protocol.old;
|
||||||
|
|
||||||
//TODO not used but let it for reference until all use cases are impl.
|
//TODO not used but let it for reference until all use cases are impl.
|
||||||
public class BuyTakerPaymentProcess extends PaymentProcess
|
public class BuyTakerPaymentProcess extends PaymentProcess
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.mock;
|
package io.bitsquare.trade.protocol.old;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
import io.bitsquare.btc.BlockChainFacade;
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.mock;
|
package io.bitsquare.trade.protocol.old;
|
||||||
|
|
||||||
//TODO not used but let it for reference until all use cases are impl.
|
//TODO not used but let it for reference until all use cases are impl.
|
||||||
class SellOffererPaymentProcess extends PaymentProcess
|
class SellOffererPaymentProcess extends PaymentProcess
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.mock;
|
package io.bitsquare.trade.protocol.old;
|
||||||
|
|
||||||
//TODO not used but let it for reference until all use cases are impl.
|
//TODO not used but let it for reference until all use cases are impl.
|
||||||
class SellTakerPaymentProcess extends PaymentProcess
|
class SellTakerPaymentProcess extends PaymentProcess
|
|
@ -1,15 +1,15 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
package io.bitsquare.trade.protocol.shared;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class VerifyTakerAccount
|
public class VerifyPeerAccount
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class);
|
private static final Logger log = LoggerFactory.getLogger(VerifyPeerAccount.class);
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount)
|
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount)
|
||||||
{
|
{
|
|
@ -0,0 +1,51 @@
|
||||||
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.ECKey;
|
||||||
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
|
import io.bitsquare.trade.Contract;
|
||||||
|
import io.bitsquare.trade.Offer;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import io.bitsquare.util.Utilities;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class CreateAndSignContract
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler,
|
||||||
|
FaultHandler faultHandler,
|
||||||
|
CryptoFacade cryptoFacade,
|
||||||
|
Offer offer,
|
||||||
|
BigInteger tradeAmount,
|
||||||
|
String takeOfferFeeTxId,
|
||||||
|
String accountId,
|
||||||
|
BankAccount bankAccount,
|
||||||
|
String peersMessagePubKeyAsHex,
|
||||||
|
String messagePubKeyAsHex,
|
||||||
|
String peersAccountId,
|
||||||
|
BankAccount peersBankAccount,
|
||||||
|
ECKey registrationKey)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, peersAccountId, accountId, peersBankAccount, bankAccount, peersMessagePubKeyAsHex, messagePubKeyAsHex);
|
||||||
|
|
||||||
|
String contractAsJson = Utilities.objectToJson(contract);
|
||||||
|
String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
|
||||||
|
resultHandler.onResult(contract, contractAsJson, signature);
|
||||||
|
} catch (Throwable t)
|
||||||
|
{
|
||||||
|
log.error("Exception at sign contract " + t);
|
||||||
|
faultHandler.onFault(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ResultHandler
|
||||||
|
{
|
||||||
|
void onResult(Contract contract, String contractAsJson, String signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.listeners.GetPeerAddressListener;
|
import io.bitsquare.msg.listeners.GetPeerAddressListener;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
|
@ -0,0 +1,54 @@
|
||||||
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import io.bitsquare.btc.WalletFacade;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class PayDeposit
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PayDeposit.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler,
|
||||||
|
FaultHandler faultHandler,
|
||||||
|
WalletFacade walletFacade,
|
||||||
|
BigInteger collateral,
|
||||||
|
BigInteger tradeAmount,
|
||||||
|
String tradeId,
|
||||||
|
String pubKeyForThatTrade,
|
||||||
|
String arbitratorPubKey,
|
||||||
|
String offererPubKey,
|
||||||
|
String preparedOffererDepositTxAsHex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BigInteger amountToPay = tradeAmount.add(collateral);
|
||||||
|
BigInteger msOutputAmount = amountToPay.add(collateral);
|
||||||
|
|
||||||
|
Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSignTx(amountToPay,
|
||||||
|
msOutputAmount,
|
||||||
|
offererPubKey,
|
||||||
|
pubKeyForThatTrade,
|
||||||
|
arbitratorPubKey,
|
||||||
|
preparedOffererDepositTxAsHex,
|
||||||
|
tradeId);
|
||||||
|
|
||||||
|
log.trace("sharedModel.signedTakerDepositTx: " + signedTakerDepositTx);
|
||||||
|
resultHandler.onResult(signedTakerDepositTx);
|
||||||
|
} catch (InsufficientMoneyException e)
|
||||||
|
{
|
||||||
|
log.error("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e);
|
||||||
|
faultHandler.onFault(new Exception("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ResultHandler
|
||||||
|
{
|
||||||
|
void onResult(Transaction signedTakerDepositTx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
import com.google.bitcoin.core.Transaction;
|
import com.google.bitcoin.core.Transaction;
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public class PayTakeOfferFee
|
||||||
public void onSuccess(Transaction transaction)
|
public void onSuccess(Transaction transaction)
|
||||||
{
|
{
|
||||||
log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString());
|
log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString());
|
||||||
resultHandler.onResult(transaction);
|
resultHandler.onResult(transaction.getHashAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -42,7 +42,7 @@ public class PayTakeOfferFee
|
||||||
|
|
||||||
public interface ResultHandler
|
public interface ResultHandler
|
||||||
{
|
{
|
||||||
void onResult(Transaction transaction);
|
void onResult(String takeOfferFeeTxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.messages.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
import io.bitsquare.msg.TradeMessage;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
|
@ -0,0 +1,400 @@
|
||||||
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.ECKey;
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
|
import io.bitsquare.btc.WalletFacade;
|
||||||
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
|
import io.bitsquare.trade.Contract;
|
||||||
|
import io.bitsquare.trade.Offer;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.protocol.offerer.BankTransferInitedMessage;
|
||||||
|
import io.bitsquare.trade.protocol.offerer.DepositTxPublishedMessage;
|
||||||
|
import io.bitsquare.trade.protocol.offerer.RequestTakerDepositPaymentMessage;
|
||||||
|
import io.bitsquare.trade.protocol.offerer.RespondToTakeOfferRequestMessage;
|
||||||
|
import io.bitsquare.user.User;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.*;
|
||||||
|
import static io.bitsquare.util.Validator.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing from the peer.
|
||||||
|
* That class handles the role of the taker as the Bitcoin seller.
|
||||||
|
* It uses sub tasks to not pollute the main class too much with all the async result/fault handling.
|
||||||
|
* Any data from incoming messages as well data used to send to the peer need to be validated before further processing.
|
||||||
|
*/
|
||||||
|
public class ProtocolForTakerAsSeller
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ProtocolForTakerAsSeller.class);
|
||||||
|
|
||||||
|
|
||||||
|
public enum State
|
||||||
|
{
|
||||||
|
Init,
|
||||||
|
GetPeerAddress,
|
||||||
|
RequestTakeOffer,
|
||||||
|
PayTakeOfferFee,
|
||||||
|
|
||||||
|
onRequestTakerDepositPaymentMessage,
|
||||||
|
|
||||||
|
SendTakeOfferFeePayedTxId,
|
||||||
|
VerifyOffererAccount,
|
||||||
|
CreateAndSignContract,
|
||||||
|
PayDeposit,
|
||||||
|
SendSignedTakerDepositTxAsHex,
|
||||||
|
onDepositTxPublishedMessage,
|
||||||
|
onBankTransferInitedMessage,
|
||||||
|
onUIEventFiatReceived,
|
||||||
|
SignAndPublishPayoutTx,
|
||||||
|
SendPayoutTxToOfferer
|
||||||
|
}
|
||||||
|
|
||||||
|
// provided data
|
||||||
|
private final Trade trade;
|
||||||
|
private final ProtocolForTakerAsSellerListener listener;
|
||||||
|
private final MessageFacade messageFacade;
|
||||||
|
private final WalletFacade walletFacade;
|
||||||
|
private final BlockChainFacade blockChainFacade;
|
||||||
|
private final CryptoFacade cryptoFacade;
|
||||||
|
|
||||||
|
// derived
|
||||||
|
private final String id;
|
||||||
|
private final Offer offer;
|
||||||
|
private final String tradeId;
|
||||||
|
private final BankAccount bankAccount;
|
||||||
|
private final String accountId;
|
||||||
|
private final String messagePubKey;
|
||||||
|
private final BigInteger tradeAmount;
|
||||||
|
private final String pubKeyForThatTrade;
|
||||||
|
private final ECKey accountKey;
|
||||||
|
private final String peersMessagePubKey;
|
||||||
|
private final BigInteger collateral;
|
||||||
|
private final String arbitratorPubKey;
|
||||||
|
|
||||||
|
// written/read by task
|
||||||
|
private PeerAddress peerAddress;
|
||||||
|
|
||||||
|
// written by messages, read by tasks
|
||||||
|
private String peersAccountId;
|
||||||
|
private BankAccount peersBankAccount;
|
||||||
|
private String peersPubKey;
|
||||||
|
private String preparedPeersDepositTxAsHex;
|
||||||
|
private long peersTxOutIndex;
|
||||||
|
|
||||||
|
private String depositTxAsHex;
|
||||||
|
private String offererSignatureR;
|
||||||
|
private String offererSignatureS;
|
||||||
|
private BigInteger offererPaybackAmount;
|
||||||
|
private BigInteger takerPaybackAmount;
|
||||||
|
private String offererPayoutAddress;
|
||||||
|
|
||||||
|
|
||||||
|
// state
|
||||||
|
private State state;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public ProtocolForTakerAsSeller(Trade trade,
|
||||||
|
ProtocolForTakerAsSellerListener listener,
|
||||||
|
MessageFacade messageFacade,
|
||||||
|
WalletFacade walletFacade,
|
||||||
|
BlockChainFacade blockChainFacade,
|
||||||
|
CryptoFacade cryptoFacade,
|
||||||
|
User user)
|
||||||
|
{
|
||||||
|
this.trade = trade;
|
||||||
|
this.listener = listener;
|
||||||
|
this.messageFacade = messageFacade;
|
||||||
|
this.walletFacade = walletFacade;
|
||||||
|
this.blockChainFacade = blockChainFacade;
|
||||||
|
this.cryptoFacade = cryptoFacade;
|
||||||
|
|
||||||
|
offer = trade.getOffer();
|
||||||
|
tradeId = trade.getId();
|
||||||
|
tradeAmount = trade.getTradeAmount();
|
||||||
|
collateral = trade.getCollateralAmount();
|
||||||
|
arbitratorPubKey = trade.getOffer().getArbitrator().getPubKeyAsHex();
|
||||||
|
|
||||||
|
pubKeyForThatTrade = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
|
||||||
|
|
||||||
|
bankAccount = user.getBankAccount(offer.getBankAccountId());
|
||||||
|
accountId = user.getAccountId();
|
||||||
|
messagePubKey = user.getMessagePubKeyAsHex();
|
||||||
|
|
||||||
|
peersMessagePubKey = offer.getMessagePubKeyAsHex();
|
||||||
|
accountKey = walletFacade.getRegistrationAddressInfo().getKey();
|
||||||
|
|
||||||
|
id = trade.getId();
|
||||||
|
|
||||||
|
state = State.Init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
log.debug("start called");
|
||||||
|
GetPeerAddress.run(this::onResultGetPeerAddress, this::onFault, messageFacade, peersMessagePubKey);
|
||||||
|
state = State.GetPeerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultGetPeerAddress(PeerAddress peerAddress)
|
||||||
|
{
|
||||||
|
log.debug(" called");
|
||||||
|
this.peerAddress = peerAddress;
|
||||||
|
|
||||||
|
RequestTakeOffer.run(this::onResultRequestTakeOffer, this::onFault, peerAddress, messageFacade, tradeId);
|
||||||
|
state = State.RequestTakeOffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultRequestTakeOffer()
|
||||||
|
{
|
||||||
|
log.debug(" called");
|
||||||
|
listener.onWaitingForPeerResponse(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Incoming message from peer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void onRespondToTakeOfferRequestMessage(RespondToTakeOfferRequestMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onRespondToTakeOfferRequestMessage called");
|
||||||
|
checkState(state == State.RequestTakeOffer);
|
||||||
|
checkArgument(tradeId.equals(message.getTradeId()));
|
||||||
|
|
||||||
|
if (message.isTakeOfferRequestAccepted())
|
||||||
|
{
|
||||||
|
PayTakeOfferFee.run(this::onResultPayTakeOfferFee, this::onFault, walletFacade, tradeId);
|
||||||
|
state = State.PayTakeOfferFee;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listener.onTakeOfferRequestRejected(trade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultPayTakeOfferFee(String takeOfferFeeTxId)
|
||||||
|
{
|
||||||
|
log.debug("onResultPayTakeOfferFee called");
|
||||||
|
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
|
||||||
|
|
||||||
|
SendTakeOfferFeePayedTxId.run(this::onResultSendTakeOfferFeePayedTxId, this::onFault, peerAddress, messageFacade, tradeId, takeOfferFeeTxId, tradeAmount, pubKeyForThatTrade);
|
||||||
|
state = State.SendTakeOfferFeePayedTxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultSendTakeOfferFeePayedTxId()
|
||||||
|
{
|
||||||
|
log.debug("onResultSendTakeOfferFeePayedTxId called");
|
||||||
|
listener.onWaitingForPeerResponse(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Incoming message from peer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void onRequestTakerDepositPaymentMessage(RequestTakerDepositPaymentMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onRequestTakerDepositPaymentMessage called");
|
||||||
|
|
||||||
|
// validation
|
||||||
|
checkState(state == State.SendTakeOfferFeePayedTxId);
|
||||||
|
checkArgument(tradeId.equals(message.getTradeId()));
|
||||||
|
String peersAccountId = nonEmptyStringOf(message.getAccountId());
|
||||||
|
BankAccount peersBankAccount = checkNotNull(message.getBankAccount());
|
||||||
|
String offererPubKey = nonEmptyStringOf(message.getOffererPubKey());
|
||||||
|
String preparedOffererDepositTxAsHex = nonEmptyStringOf(message.getPreparedOffererDepositTxAsHex());
|
||||||
|
long offererTxOutIndex = nonNegativeLongOf(message.getOffererTxOutIndex());
|
||||||
|
|
||||||
|
// apply new state
|
||||||
|
state = State.onRequestTakerDepositPaymentMessage;
|
||||||
|
this.peersAccountId = peersAccountId;
|
||||||
|
this.peersBankAccount = peersBankAccount;
|
||||||
|
this.peersPubKey = offererPubKey;
|
||||||
|
this.preparedPeersDepositTxAsHex = preparedOffererDepositTxAsHex;
|
||||||
|
this.peersTxOutIndex = offererTxOutIndex;
|
||||||
|
|
||||||
|
// next task
|
||||||
|
VerifyOffererAccount.run(this::onResultVerifyOffererAccount, this::onFault, blockChainFacade, peersAccountId, peersBankAccount);
|
||||||
|
state = State.VerifyOffererAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultVerifyOffererAccount()
|
||||||
|
{
|
||||||
|
log.debug("onResultVerifyOffererAccount called");
|
||||||
|
String takeOfferFeeTxId = trade.getTakeOfferFeeTxId();
|
||||||
|
CreateAndSignContract.run(this::onResultCreateAndSignContract,
|
||||||
|
this::onFault,
|
||||||
|
cryptoFacade,
|
||||||
|
offer,
|
||||||
|
tradeAmount,
|
||||||
|
takeOfferFeeTxId,
|
||||||
|
accountId,
|
||||||
|
bankAccount,
|
||||||
|
peersMessagePubKey,
|
||||||
|
messagePubKey,
|
||||||
|
peersAccountId,
|
||||||
|
peersBankAccount,
|
||||||
|
accountKey);
|
||||||
|
state = State.CreateAndSignContract;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultCreateAndSignContract(Contract contract, String contractAsJson, String signature)
|
||||||
|
{
|
||||||
|
log.debug("onResultCreateAndSignContract called");
|
||||||
|
|
||||||
|
trade.setContract(contract);
|
||||||
|
trade.setContractAsJson(contractAsJson);
|
||||||
|
trade.setContractTakerSignature(signature);
|
||||||
|
|
||||||
|
PayDeposit.run(this::onResultPayDeposit, this::onFault, walletFacade, collateral, tradeAmount, tradeId, pubKeyForThatTrade, arbitratorPubKey, peersPubKey, preparedPeersDepositTxAsHex);
|
||||||
|
state = State.PayDeposit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultPayDeposit(Transaction signedTakerDepositTx)
|
||||||
|
{
|
||||||
|
log.debug("onResultPayDeposit called");
|
||||||
|
String contractAsJson = trade.getContractAsJson();
|
||||||
|
String takerSignature = trade.getTakerSignature();
|
||||||
|
|
||||||
|
SendSignedTakerDepositTxAsHex.run(this::onResultSendSignedTakerDepositTxAsHex,
|
||||||
|
this::onFault,
|
||||||
|
peerAddress,
|
||||||
|
messageFacade,
|
||||||
|
walletFacade,
|
||||||
|
bankAccount,
|
||||||
|
accountId,
|
||||||
|
messagePubKey,
|
||||||
|
tradeId,
|
||||||
|
contractAsJson,
|
||||||
|
takerSignature,
|
||||||
|
signedTakerDepositTx,
|
||||||
|
peersTxOutIndex);
|
||||||
|
state = State.SendSignedTakerDepositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultSendSignedTakerDepositTxAsHex()
|
||||||
|
{
|
||||||
|
log.debug(" called");
|
||||||
|
listener.onWaitingForPeerResponse(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Incoming message from peer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// informational, does only trigger UI feedback/update
|
||||||
|
public void onDepositTxPublishedMessage(DepositTxPublishedMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onDepositTxPublishedMessage called");
|
||||||
|
checkState(state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal());
|
||||||
|
checkArgument(tradeId.equals(message.getTradeId()));
|
||||||
|
state = State.onDepositTxPublishedMessage;
|
||||||
|
listener.onDepositTxPublished(walletFacade.takerCommitDepositTx(message.getDepositTxAsHex()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Incoming message from peer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// informational, store data for later, does only trigger UI feedback/update
|
||||||
|
public void onBankTransferInitedMessage(BankTransferInitedMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onBankTransferInitedMessage called");
|
||||||
|
|
||||||
|
// validate
|
||||||
|
checkState(state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal());
|
||||||
|
checkArgument(tradeId.equals(message.getTradeId()));
|
||||||
|
String depositTxAsHex = nonEmptyStringOf(message.getDepositTxAsHex());
|
||||||
|
String offererSignatureR = nonEmptyStringOf(message.getOffererSignatureR());
|
||||||
|
String offererSignatureS = nonEmptyStringOf(message.getOffererSignatureS());
|
||||||
|
BigInteger offererPaybackAmount = nonNegativeBigIntegerOf(nonZeroBigIntegerOf(message.getOffererPaybackAmount()));
|
||||||
|
BigInteger takerPaybackAmount = nonNegativeBigIntegerOf(nonZeroBigIntegerOf(message.getTakerPaybackAmount()));
|
||||||
|
String offererPayoutAddress = nonEmptyStringOf(message.getOffererPayoutAddress());
|
||||||
|
|
||||||
|
// apply state
|
||||||
|
state = State.onBankTransferInitedMessage;
|
||||||
|
this.depositTxAsHex = depositTxAsHex;
|
||||||
|
this.offererSignatureR = offererSignatureR;
|
||||||
|
this.offererSignatureS = offererSignatureS;
|
||||||
|
this.offererPaybackAmount = offererPaybackAmount;
|
||||||
|
this.takerPaybackAmount = takerPaybackAmount;
|
||||||
|
this.offererPayoutAddress = offererPayoutAddress;
|
||||||
|
|
||||||
|
listener.onBankTransferInited(message.getTradeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Triggered UI event
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
||||||
|
public void onUIEventFiatReceived()
|
||||||
|
{
|
||||||
|
log.debug("onUIEventFiatReceived called");
|
||||||
|
|
||||||
|
checkState(state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal());
|
||||||
|
state = State.onUIEventFiatReceived;
|
||||||
|
|
||||||
|
SignAndPublishPayoutTx.run(this::onResultSignAndPublishPayoutTx,
|
||||||
|
this::onFault,
|
||||||
|
walletFacade,
|
||||||
|
tradeId,
|
||||||
|
depositTxAsHex,
|
||||||
|
offererSignatureR,
|
||||||
|
offererSignatureS,
|
||||||
|
offererPaybackAmount,
|
||||||
|
takerPaybackAmount,
|
||||||
|
offererPayoutAddress);
|
||||||
|
state = State.SignAndPublishPayoutTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultSignAndPublishPayoutTx(String transactionId, String payoutTxAsHex)
|
||||||
|
{
|
||||||
|
log.debug("onResultSignAndPublishPayoutTx called");
|
||||||
|
listener.onPayoutTxPublished(trade, transactionId);
|
||||||
|
|
||||||
|
SendPayoutTxToOfferer.run(this::onResultSendPayoutTxToOfferer, this::onFault, peerAddress, messageFacade, tradeId, payoutTxAsHex);
|
||||||
|
state = State.SendPayoutTxToOfferer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResultSendPayoutTxToOfferer()
|
||||||
|
{
|
||||||
|
log.debug("onResultSendPayoutTxToOfferer called");
|
||||||
|
listener.onCompleted(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Getters, Setters
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// generic fault handler
|
||||||
|
private void onFault(Throwable throwable)
|
||||||
|
{
|
||||||
|
listener.onFault(throwable, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
|
|
||||||
public interface TakerAsSellerProtocolListener
|
public interface ProtocolForTakerAsSellerListener
|
||||||
{
|
{
|
||||||
void onDepositTxPublished(String depositTxId);
|
void onDepositTxPublished(String depositTxId);
|
||||||
|
|
||||||
|
@ -10,11 +10,11 @@ public interface TakerAsSellerProtocolListener
|
||||||
|
|
||||||
void onPayoutTxPublished(Trade trade, String hashAsString);
|
void onPayoutTxPublished(Trade trade, String hashAsString);
|
||||||
|
|
||||||
void onFault(Throwable throwable, TakerAsSellerProtocol.State state);
|
void onFault(Throwable throwable, ProtocolForTakerAsSeller.State state);
|
||||||
|
|
||||||
void onWaitingForPeerResponse(TakerAsSellerProtocol.State state);
|
void onWaitingForPeerResponse(ProtocolForTakerAsSeller.State state);
|
||||||
|
|
||||||
void onCompleted(TakerAsSellerProtocol.State state);
|
void onCompleted(ProtocolForTakerAsSeller.State state);
|
||||||
|
|
||||||
void onTakeOfferRequestRejected(Trade trade);
|
void onTakeOfferRequestRejected(Trade trade);
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.messages.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.msg.TradeMessage;
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
@ -62,12 +62,12 @@ public class RequestOffererPublishDepositTxMessage implements Serializable, Trad
|
||||||
return offererTxOutIndex;
|
return offererTxOutIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BankAccount getBankAccount()
|
public BankAccount getTakerBankAccount()
|
||||||
{
|
{
|
||||||
return bankAccount;
|
return bankAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAccountId()
|
public String getTakerAccountId()
|
||||||
{
|
{
|
||||||
return accountID;
|
return accountID;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ public class RequestOffererPublishDepositTxMessage implements Serializable, Trad
|
||||||
return txConnOutAsHex;
|
return txConnOutAsHex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContractAsJson()
|
public String getTakerContractAsJson()
|
||||||
{
|
{
|
||||||
return contractAsJson;
|
return contractAsJson;
|
||||||
}
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||||
import io.bitsquare.trade.protocol.messages.taker.RequestTakeOfferMessage;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.messages.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
import io.bitsquare.msg.TradeMessage;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
|
@ -1,11 +1,9 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -14,9 +12,9 @@ public class SendPayoutTxToOfferer
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
|
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade trade, String payoutTxAsHex)
|
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, String tradeId, String payoutTxAsHex)
|
||||||
{
|
{
|
||||||
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(trade.getId(), payoutTxAsHex);
|
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(tradeId, payoutTxAsHex);
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
|
@ -0,0 +1,67 @@
|
||||||
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.btc.WalletFacade;
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
|
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SendSignedTakerDepositTxAsHex
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler,
|
||||||
|
FaultHandler faultHandler,
|
||||||
|
PeerAddress peerAddress,
|
||||||
|
MessageFacade messageFacade,
|
||||||
|
WalletFacade walletFacade,
|
||||||
|
BankAccount bankAccount,
|
||||||
|
String accountId,
|
||||||
|
String messagePubKeyAsHex,
|
||||||
|
String tradeId,
|
||||||
|
String contractAsJson,
|
||||||
|
String takerSignature,
|
||||||
|
Transaction signedTakerDepositTx,
|
||||||
|
long offererTxOutIndex)
|
||||||
|
{
|
||||||
|
long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex();
|
||||||
|
|
||||||
|
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(tradeId,
|
||||||
|
bankAccount,
|
||||||
|
accountId,
|
||||||
|
messagePubKeyAsHex,
|
||||||
|
Utils.bytesToHexString(signedTakerDepositTx.bitcoinSerialize()),
|
||||||
|
Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes()),
|
||||||
|
Utils.bytesToHexString(signedTakerDepositTx.getInput(1)
|
||||||
|
.getConnectedOutput()
|
||||||
|
.getParentTransaction()
|
||||||
|
.bitcoinSerialize()),
|
||||||
|
contractAsJson,
|
||||||
|
takerSignature,
|
||||||
|
walletFacade.getAddressInfoByTradeID(tradeId).getAddressString(),
|
||||||
|
takerTxOutIndex,
|
||||||
|
offererTxOutIndex);
|
||||||
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer");
|
||||||
|
resultHandler.onResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer");
|
||||||
|
faultHandler.onFault(new Exception("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||||
import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage;
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -21,12 +20,9 @@ public class SendTakeOfferFeePayedTxId
|
||||||
String tradeId,
|
String tradeId,
|
||||||
String takeOfferFeeTxId,
|
String takeOfferFeeTxId,
|
||||||
BigInteger tradeAmount,
|
BigInteger tradeAmount,
|
||||||
String pubKeyAsHexString)
|
String pubKeyForThatTradeAsHex)
|
||||||
{
|
{
|
||||||
TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(tradeId,
|
TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(tradeId, takeOfferFeeTxId, tradeAmount, pubKeyForThatTradeAsHex);
|
||||||
takeOfferFeeTxId,
|
|
||||||
tradeAmount,
|
|
||||||
pubKeyAsHexString);
|
|
||||||
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, msg, new OutgoingTradeMessageListener()
|
messageFacade.sendTradeMessage(peerAddress, msg, new OutgoingTradeMessageListener()
|
||||||
{
|
{
|
|
@ -0,0 +1,66 @@
|
||||||
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import io.bitsquare.btc.WalletFacade;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SignAndPublishPayoutTx
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler,
|
||||||
|
FaultHandler faultHandler,
|
||||||
|
WalletFacade walletFacade,
|
||||||
|
String tradeId,
|
||||||
|
String depositTxAsHex,
|
||||||
|
String offererSignatureR,
|
||||||
|
String offererSignatureS,
|
||||||
|
BigInteger offererPaybackAmount,
|
||||||
|
BigInteger takerPaybackAmount,
|
||||||
|
String offererPayoutAddress)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
walletFacade.takerSignsAndSendsTx(depositTxAsHex,
|
||||||
|
offererSignatureR,
|
||||||
|
offererSignatureS,
|
||||||
|
offererPaybackAmount,
|
||||||
|
takerPaybackAmount,
|
||||||
|
offererPayoutAddress,
|
||||||
|
tradeId,
|
||||||
|
new FutureCallback<Transaction>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction)
|
||||||
|
{
|
||||||
|
log.debug("takerSignsAndSendsTx " + transaction);
|
||||||
|
String payoutTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize());
|
||||||
|
resultHandler.onResult(transaction.getHashAsString(), payoutTxAsHex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t)
|
||||||
|
{
|
||||||
|
log.error("Exception at takerSignsAndSendsTx " + t);
|
||||||
|
faultHandler.onFault(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Exception at takerSignsAndSendsTx " + e);
|
||||||
|
faultHandler.onFault(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ResultHandler
|
||||||
|
{
|
||||||
|
void onResult(String transactionId, String payoutTxAsHex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package io.bitsquare.trade.protocol.messages.taker;
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
import io.bitsquare.msg.TradeMessage;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -11,14 +11,14 @@ public class TakeOfferFeePayedMessage implements Serializable, TradeMessage
|
||||||
|
|
||||||
private BigInteger tradeAmount;
|
private BigInteger tradeAmount;
|
||||||
private String takeOfferFeeTxID;
|
private String takeOfferFeeTxID;
|
||||||
private String takerMultiSigPubKey;
|
private String takerPubKey;
|
||||||
|
|
||||||
public TakeOfferFeePayedMessage(String tradeId, String takeOfferFeeTxID, BigInteger tradeAmount, String takerMultiSigPubKey)
|
public TakeOfferFeePayedMessage(String tradeId, String takeOfferFeeTxID, BigInteger tradeAmount, String takerPubKey)
|
||||||
{
|
{
|
||||||
this.tradeId = tradeId;
|
this.tradeId = tradeId;
|
||||||
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
||||||
this.tradeAmount = tradeAmount;
|
this.tradeAmount = tradeAmount;
|
||||||
this.takerMultiSigPubKey = takerMultiSigPubKey;
|
this.takerPubKey = takerPubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,9 +37,9 @@ public class TakeOfferFeePayedMessage implements Serializable, TradeMessage
|
||||||
return takeOfferFeeTxID;
|
return takeOfferFeeTxID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTakerMultiSigPubKey()
|
public String getTakerPubKey()
|
||||||
{
|
{
|
||||||
return takerMultiSigPubKey;
|
return takerPubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,882 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.taker;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
|
||||||
import io.bitsquare.btc.WalletFacade;
|
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
|
||||||
import io.bitsquare.trade.Offer;
|
|
||||||
import io.bitsquare.trade.Trade;
|
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.BankTransferInitedMessage;
|
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.DepositTxPublishedMessage;
|
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.RequestTakerDepositPaymentMessage;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.taker.*;
|
|
||||||
import io.bitsquare.user.User;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
import static io.bitsquare.util.Validator.nonEmptyStringOf;
|
|
||||||
import static io.bitsquare.util.Validator.nonNegativeLongOf;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing from the peer.
|
|
||||||
* That class handles the role of the taker as the Bitcoin seller.
|
|
||||||
* It uses sub tasks to not pollute the main class too much with all the async result/fault handling.
|
|
||||||
* Any data from incoming messages as well data used to send to the peer need to be validated before further processing.
|
|
||||||
*/
|
|
||||||
public class TakerAsSellerProtocol
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(TakerAsSellerProtocol.class);
|
|
||||||
// provided data
|
|
||||||
private final Trade trade;
|
|
||||||
private final TakerAsSellerProtocolListener listener;
|
|
||||||
private final MessageFacade messageFacade;
|
|
||||||
private final WalletFacade walletFacade;
|
|
||||||
private final BlockChainFacade blockChainFacade;
|
|
||||||
private final CryptoFacade cryptoFacade;
|
|
||||||
private final User user;
|
|
||||||
private final String id;
|
|
||||||
private final Offer offer;
|
|
||||||
private final String tradeId;
|
|
||||||
// written/read by task
|
|
||||||
private String payoutTxAsHex;
|
|
||||||
private PeerAddress peerAddress;
|
|
||||||
private Transaction signedTakerDepositTx;
|
|
||||||
private long takerTxOutIndex;
|
|
||||||
// written by message, read by tasks
|
|
||||||
private String peersAccountId;
|
|
||||||
private BankAccount peersBankAccount;
|
|
||||||
private String offererPubKey;
|
|
||||||
private String preparedOffererDepositTxAsHex;
|
|
||||||
private long offererTxOutIndex;
|
|
||||||
private String depositTxAsHex;
|
|
||||||
private String offererSignatureR;
|
|
||||||
private String offererSignatureS;
|
|
||||||
private BigInteger offererPaybackAmount;
|
|
||||||
private BigInteger takerPaybackAmount;
|
|
||||||
private String offererPayoutAddress;
|
|
||||||
//private
|
|
||||||
private State state;
|
|
||||||
|
|
||||||
public TakerAsSellerProtocol(Trade trade,
|
|
||||||
TakerAsSellerProtocolListener listener,
|
|
||||||
MessageFacade messageFacade,
|
|
||||||
WalletFacade walletFacade,
|
|
||||||
BlockChainFacade blockChainFacade,
|
|
||||||
CryptoFacade cryptoFacade,
|
|
||||||
User user)
|
|
||||||
{
|
|
||||||
this.trade = trade;
|
|
||||||
this.listener = listener;
|
|
||||||
this.messageFacade = messageFacade;
|
|
||||||
this.walletFacade = walletFacade;
|
|
||||||
this.blockChainFacade = blockChainFacade;
|
|
||||||
this.cryptoFacade = cryptoFacade;
|
|
||||||
this.user = user;
|
|
||||||
|
|
||||||
offer = trade.getOffer();
|
|
||||||
tradeId = trade.getId();
|
|
||||||
|
|
||||||
id = trade.getId();
|
|
||||||
state = State.Init;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// generic fault handler
|
|
||||||
public void onFault(Throwable throwable)
|
|
||||||
{
|
|
||||||
listener.onFault(throwable, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start()
|
|
||||||
{
|
|
||||||
String messagePubKeyAsHex = nonEmptyStringOf(offer.getMessagePubKeyAsHex());
|
|
||||||
|
|
||||||
GetPeerAddress.run(this::onResultGetPeerAddress, this::onFault, messageFacade, messagePubKeyAsHex);
|
|
||||||
state = State.GetPeerAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Tasks
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onResultGetPeerAddress(PeerAddress peerAddress)
|
|
||||||
{
|
|
||||||
this.peerAddress = checkNotNull(peerAddress);
|
|
||||||
|
|
||||||
RequestTakeOffer.run(this::onResultRequestTakeOffer, this::onFault, this.peerAddress, messageFacade, tradeId);
|
|
||||||
state = State.RequestTakeOffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultRequestTakeOffer()
|
|
||||||
{
|
|
||||||
listener.onWaitingForPeerResponse(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onAcceptTakeOfferRequestMessage()
|
|
||||||
{
|
|
||||||
log.debug("onAcceptTakeOfferRequestMessage");
|
|
||||||
checkState(state == State.RequestTakeOffer);
|
|
||||||
|
|
||||||
PayTakeOfferFee.run(this::onResultPayTakeOfferFee, this::onFault, walletFacade, tradeId);
|
|
||||||
state = State.PayTakeOfferFee;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Incoming message from peer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// OR
|
|
||||||
public void onRejectTakeOfferRequestMessage()
|
|
||||||
{
|
|
||||||
log.debug("onRejectTakeOfferRequestMessage");
|
|
||||||
checkState(state == State.RequestTakeOffer);
|
|
||||||
|
|
||||||
state = State.onRejectTakeOfferRequestMessage;
|
|
||||||
listener.onTakeOfferRequestRejected(trade);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultPayTakeOfferFee(Transaction transaction)
|
|
||||||
{
|
|
||||||
checkNotNull(transaction);
|
|
||||||
String transactionId = nonEmptyStringOf(transaction.getHashAsString());
|
|
||||||
|
|
||||||
trade.setTakeOfferFeeTxID(transactionId);
|
|
||||||
|
|
||||||
String takeOfferFeeTxId = trade.getTakeOfferFeeTxId();
|
|
||||||
BigInteger tradeAmount = trade.getTradeAmount();
|
|
||||||
String pubKeyAsHexString = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
|
|
||||||
|
|
||||||
SendTakeOfferFeePayedTxId.run(this::onResultSendTakeOfferFeePayedTxId,
|
|
||||||
this::onFault,
|
|
||||||
peerAddress,
|
|
||||||
messageFacade,
|
|
||||||
tradeId,
|
|
||||||
takeOfferFeeTxId,
|
|
||||||
tradeAmount,
|
|
||||||
pubKeyAsHexString);
|
|
||||||
state = State.SendTakeOfferFeePayedTxId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Tasks
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onResultSendTakeOfferFeePayedTxId()
|
|
||||||
{
|
|
||||||
listener.onWaitingForPeerResponse(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onRequestTakerDepositPaymentMessage(RequestTakerDepositPaymentMessage message)
|
|
||||||
{
|
|
||||||
log.debug("onRequestTakerDepositPaymentMessage");
|
|
||||||
|
|
||||||
checkState(state == State.SendTakeOfferFeePayedTxId);
|
|
||||||
|
|
||||||
peersAccountId = nonEmptyStringOf(message.getAccountID());
|
|
||||||
peersBankAccount = checkNotNull(message.getBankAccount());
|
|
||||||
offererPubKey = nonEmptyStringOf(message.getOffererPubKey());
|
|
||||||
preparedOffererDepositTxAsHex = nonEmptyStringOf(message.getPreparedOffererDepositTxAsHex());
|
|
||||||
offererTxOutIndex = nonNegativeLongOf(message.getOffererTxOutIndex());
|
|
||||||
|
|
||||||
VerifyOffererAccount.run(this::onResultVerifyOffererAccount,
|
|
||||||
this::onFault,
|
|
||||||
blockChainFacade,
|
|
||||||
peersAccountId,
|
|
||||||
peersBankAccount);
|
|
||||||
state = State.VerifyOffererAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Incoming message from peer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onResultVerifyOffererAccount()
|
|
||||||
{
|
|
||||||
CreateAndSignContract.run(this::onResultCreateAndSignContract,
|
|
||||||
this::onFault,
|
|
||||||
cryptoFacade,
|
|
||||||
trade,
|
|
||||||
user,
|
|
||||||
peersAccountId,
|
|
||||||
peersBankAccount,
|
|
||||||
walletFacade.getRegistrationAddressInfo().getKey());
|
|
||||||
state = State.CreateAndSignContract;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Tasks
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onResultCreateAndSignContract()
|
|
||||||
{
|
|
||||||
PayDeposit.run(this::onResultPayDeposit, this::onFault, walletFacade, trade, offererPubKey, preparedOffererDepositTxAsHex);
|
|
||||||
state = State.PayDeposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultPayDeposit(Transaction signedTakerDepositTx, long takerTxOutIndex)
|
|
||||||
{
|
|
||||||
SendSignedTakerDepositTxAsHex.run(this::onResultSendSignedTakerDepositTxAsHex,
|
|
||||||
this::onFault,
|
|
||||||
peerAddress,
|
|
||||||
messageFacade,
|
|
||||||
walletFacade,
|
|
||||||
trade,
|
|
||||||
user,
|
|
||||||
signedTakerDepositTx,
|
|
||||||
takerTxOutIndex,
|
|
||||||
offererTxOutIndex);
|
|
||||||
state = State.SendSignedTakerDepositTxAsHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultSendSignedTakerDepositTxAsHex()
|
|
||||||
{
|
|
||||||
listener.onWaitingForPeerResponse(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// informational, does only trigger UI feedback/update
|
|
||||||
public void onDepositTxPublishedMessage(DepositTxPublishedMessage message)
|
|
||||||
{
|
|
||||||
log.debug("onDepositTxPublishedMessage");
|
|
||||||
if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal())
|
|
||||||
{
|
|
||||||
state = State.onDepositTxPublishedMessage;
|
|
||||||
|
|
||||||
listener.onDepositTxPublished(walletFacade.takerCommitDepositTx(message.getDepositTxAsHex()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log.error("Invalid state. Actual state is: " + state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Incoming message from peer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// informational, store data for later, does only trigger UI feedback/update
|
|
||||||
public void onBankTransferInitedMessage(BankTransferInitedMessage tradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("onBankTransferInitedMessage");
|
|
||||||
|
|
||||||
if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal())
|
|
||||||
{
|
|
||||||
state = State.onBankTransferInitedMessage;
|
|
||||||
|
|
||||||
depositTxAsHex = tradeMessage.getDepositTxAsHex();
|
|
||||||
offererSignatureR = tradeMessage.getOffererSignatureR();
|
|
||||||
offererSignatureS = tradeMessage.getOffererSignatureS();
|
|
||||||
offererPaybackAmount = tradeMessage.getOffererPaybackAmount();
|
|
||||||
takerPaybackAmount = tradeMessage.getTakerPaybackAmount();
|
|
||||||
offererPayoutAddress = tradeMessage.getOffererPayoutAddress();
|
|
||||||
|
|
||||||
listener.onBankTransferInited(tradeMessage.getTradeId());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log.error("Invalid state. Actual state is: " + state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
|
||||||
public void onUIEventFiatReceived()
|
|
||||||
{
|
|
||||||
log.debug("onUIEventFiatReceived");
|
|
||||||
|
|
||||||
if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal())
|
|
||||||
{
|
|
||||||
state = State.onUIEventFiatReceived;
|
|
||||||
|
|
||||||
SignAndPublishPayoutTx.run(this::onResultSignAndPublishPayoutTx,
|
|
||||||
this::onFault,
|
|
||||||
walletFacade,
|
|
||||||
trade,
|
|
||||||
depositTxAsHex,
|
|
||||||
offererSignatureR,
|
|
||||||
offererSignatureS,
|
|
||||||
offererPaybackAmount,
|
|
||||||
takerPaybackAmount,
|
|
||||||
offererPayoutAddress);
|
|
||||||
state = State.SignAndPublishPayoutTx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log.error("Invalid state. Actual state is: " + state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResultSignAndPublishPayoutTx(Transaction transaction, String payoutTxAsHex)
|
|
||||||
{
|
|
||||||
listener.onPayoutTxPublished(trade, transaction.getHashAsString());
|
|
||||||
|
|
||||||
SendPayoutTxToOfferer.run(this::onResultSendPayoutTxToOfferer, this::onFault, peerAddress, messageFacade, trade, payoutTxAsHex);
|
|
||||||
state = State.SendPayoutTxToOfferer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Tasks
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onResultSendPayoutTxToOfferer()
|
|
||||||
{
|
|
||||||
checkState(state == State.SendPayoutTxToOfferer);
|
|
||||||
listener.onCompleted(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId()
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Getters, Setters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public enum State
|
|
||||||
{
|
|
||||||
Init,
|
|
||||||
GetPeerAddress,
|
|
||||||
RequestTakeOffer,
|
|
||||||
PayTakeOfferFee,
|
|
||||||
onRejectTakeOfferRequestMessage,
|
|
||||||
SendTakeOfferFeePayedTxId,
|
|
||||||
VerifyOffererAccount,
|
|
||||||
CreateAndSignContract,
|
|
||||||
PayDeposit,
|
|
||||||
SendSignedTakerDepositTxAsHex,
|
|
||||||
onDepositTxPublishedMessage,
|
|
||||||
onBankTransferInitedMessage,
|
|
||||||
onUIEventFiatReceived,
|
|
||||||
SignAndPublishPayoutTx,
|
|
||||||
SendPayoutTxToOfferer
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 1.1
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
/* private void findPeerAddress()
|
|
||||||
{
|
|
||||||
log.debug("1.1 findPeerAddress");
|
|
||||||
AddressLookupListener addressLookupListener = new AddressLookupListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onResult(PeerAddress address)
|
|
||||||
{
|
|
||||||
log.debug("1.1 findPeerAddress onResult");
|
|
||||||
// We got the peer address
|
|
||||||
peerAddress = address;
|
|
||||||
|
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
|
||||||
|
|
||||||
// next
|
|
||||||
requestTakeOffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed()
|
|
||||||
{
|
|
||||||
log.debug("1.1 findPeerAddress onFailed");
|
|
||||||
takerPaymentProtocolListener.onFailure("onGetPeerAddressFailed");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
|
||||||
|
|
||||||
// Request the peers address from the DHT
|
|
||||||
messageFacade.getPeerAddress(offer.getMessagePubKeyAsHex(), addressLookupListener);
|
|
||||||
} */
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 1.2
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/* private void requestTakeOffer()
|
|
||||||
{
|
|
||||||
log.debug("1.2 requestTakeOffer");
|
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onResult()
|
|
||||||
{
|
|
||||||
log.debug("1.2 requestTakeOffer onResult");
|
|
||||||
// Our message has arrived
|
|
||||||
// We don't know yet if the offerer has accepted
|
|
||||||
// the take request (if offer is not already reserved for another user)
|
|
||||||
// We await for an incoming message from the offerer with the accept msg
|
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
|
||||||
|
|
||||||
// Wait for message from offerer...
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed()
|
|
||||||
{
|
|
||||||
log.debug("1.2 requestTakeOffer onFailed");
|
|
||||||
takerPaymentProtocolListener.onFailure("sendTakeOfferRequest onSendTradingMessageFailed");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
|
||||||
|
|
||||||
// Send the take offer request
|
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKE_OFFER, trade.getId());
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
//************************************************************************************************
|
|
||||||
// 1.3. Offerers tasks, we are in waiting mode
|
|
||||||
//************************************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 1.4
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
// 1.4a offerer has accepted the take offer request. Move on to step 2.
|
|
||||||
/* public void onAcceptTakeOfferRequestMessage()
|
|
||||||
{
|
|
||||||
log.debug("1.4a onAcceptTakeOfferRequestMessage");
|
|
||||||
// listener.onProgress(getProgress());
|
|
||||||
|
|
||||||
payOfferFee(trade);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1.4b Offerer has rejected the take offer request. The UI controller will onResult the case.
|
|
||||||
public void onRejectTakeOfferRequestMessage()
|
|
||||||
{
|
|
||||||
log.debug("1.4b onRejectTakeOfferRequestMessage");
|
|
||||||
// listener.onProgress(getProgress());
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 2.1
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/* private void payOfferFee(Trade trade)
|
|
||||||
{
|
|
||||||
log.debug("2.1 payTakeOfferFee");
|
|
||||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
|
||||||
{
|
|
||||||
log.debug("2.1 payTakeOfferFee onSuccess");
|
|
||||||
log.info("sendResult onSuccess txid:" + transaction.getHashAsString());
|
|
||||||
|
|
||||||
// Offer fee payed successfully.
|
|
||||||
trade.setTakeOfferFeeTxID(transaction.getHashAsString());
|
|
||||||
|
|
||||||
// listener.onProgress(getProgress());
|
|
||||||
|
|
||||||
// move on
|
|
||||||
sendTakerOfferFeeTxID(transaction.getHashAsString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable t)
|
|
||||||
{
|
|
||||||
log.debug("2.1 payTakeOfferFee onFailure");
|
|
||||||
// listener.onFailure("payTakeOfferFee onFailure " + t.getMessage());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Pay the offer fee
|
|
||||||
// listener.onProgress(getProgress());
|
|
||||||
walletFacade.payTakeOfferFee(trade.getId(), callback);
|
|
||||||
} catch (InsufficientMoneyException e)
|
|
||||||
{
|
|
||||||
// listener.onProgress(getProgress());
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 2.2
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Request peers account details. At that moment private data (bank account nr.) of the offerer get visible to the taker.
|
|
||||||
// We send also the tx id of the fee payment, so the offerer can confirm that the payment is seen in the network
|
|
||||||
// 0 block confirmation is acceptable for the fee to not block the process
|
|
||||||
// The offerer will wait until a minimum of peers seen the tx before sending his data.
|
|
||||||
// We also get the multisig tx delivered
|
|
||||||
/* private void sendTakerOfferFeeTxID(String takeOfferFeeTxID)
|
|
||||||
{
|
|
||||||
log.debug("2.2 sendTakerOfferFeeTxID");
|
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onResult()
|
|
||||||
{
|
|
||||||
log.debug("2.2 sendTakerOfferFeeTxID onResult");
|
|
||||||
// Message has arrived
|
|
||||||
//listener.onProgress(getProgress());
|
|
||||||
|
|
||||||
// We wait until the offerer send us the data
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed()
|
|
||||||
{
|
|
||||||
log.debug("2.2 sendTakerOfferFeeTxID onFailed");
|
|
||||||
// //TakerAsSellerProtocol.this. listener.onFailure("requestAccountDetails onSendTradingMessageFailed");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// this.listener.onProgress(getProgress());
|
|
||||||
|
|
||||||
// 2.3. send request for the account details and send fee tx id so offerer can verify that the fee has been paid.
|
|
||||||
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.TAKE_OFFER_FEE_PAYED,
|
|
||||||
trade.getId(),
|
|
||||||
trade.getTradeAmount(),
|
|
||||||
takeOfferFeeTxID,
|
|
||||||
walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString());
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//************************************************************************************************
|
|
||||||
// 2.3 - 2.6 Offerers tasks, we are in waiting mode
|
|
||||||
//************************************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 2.7 Incoming msg from offerer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/*public void onRequestTakerDepositPaymentMessage(TradeMessageOld requestTradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("2.7 onRequestTakerDepositPaymentMessage");
|
|
||||||
verifyOfferer(requestTradeMessage);
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 2.8 Verify offerers account registration and against the blacklist
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/*private void verifyOfferer(TradeMessageOld requestTradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("2.8 verifyOfferer");
|
|
||||||
log.debug("2.8.1 verifyAccountRegistration");
|
|
||||||
if (blockChainFacade.verifyAccountRegistration())
|
|
||||||
{
|
|
||||||
log.debug("2.8.2 isAccountBlackListed");
|
|
||||||
if (blockChainFacade.isAccountBlackListed(requestTradeMessage.getAccountId(), requestTradeMessage.getBankAccount()))
|
|
||||||
{
|
|
||||||
// listener.onFailure("Offerer is blacklisted.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
createAndSignContract(requestTradeMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// listener.onFailure("Offerers account registration is invalid.");
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 2.9 Create and sign the contract
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/* private void createAndSignContract(TradeMessageOld requestTradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("2.9 createAndSignContract");
|
|
||||||
checkNotNull(trade.getOffer());
|
|
||||||
checkNotNull(trade.getTradeAmount());
|
|
||||||
checkNotNull(trade.getTakeOfferFeeTxId());
|
|
||||||
checkNotNull(requestTradeMessage.getAccountId());
|
|
||||||
checkNotNull(user.getAccountId());
|
|
||||||
checkNotNull(requestTradeMessage.getBankAccount());
|
|
||||||
checkNotNull(user.getCurrentBankAccount());
|
|
||||||
checkNotNull(user.getMessagePubKeyAsHex());
|
|
||||||
|
|
||||||
Contract contract = new Contract(trade.getOffer(),
|
|
||||||
trade.getTradeAmount(),
|
|
||||||
trade.getTakeOfferFeeTxId(),
|
|
||||||
requestTradeMessage.getAccountId(),
|
|
||||||
user.getAccountId(),
|
|
||||||
requestTradeMessage.getBankAccount(),
|
|
||||||
user.getCurrentBankAccount(),
|
|
||||||
trade.getOffer().getMessagePubKeyAsHex(),
|
|
||||||
user.getMessagePubKeyAsHex()
|
|
||||||
);
|
|
||||||
|
|
||||||
log.debug("2.9 contract created: " + contract);
|
|
||||||
String contractAsJson = Utilities.objectToJson(contract);
|
|
||||||
String signature = cryptoFacade.signContract(walletFacade.getRegistrationAddressInfo().getKey(), contractAsJson);
|
|
||||||
|
|
||||||
//log.debug("2.9 contractAsJson: " + contractAsJson);
|
|
||||||
log.debug("2.9 contract signature: " + signature);
|
|
||||||
|
|
||||||
trade.setContract(contract);
|
|
||||||
trade.setContractAsJson(contractAsJson);
|
|
||||||
trade.setContractTakerSignature(signature);
|
|
||||||
|
|
||||||
payDeposit(requestTradeMessage);
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 2.10 Pay in the funds to the deposit tx and sign it
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/*private void payDeposit(TradeMessageOld requestTradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("2.10 payDeposit");
|
|
||||||
|
|
||||||
BigInteger collateralAmount = trade.getCollateralAmount();
|
|
||||||
BigInteger takerInputAmount = trade.getTradeAmount().add(collateralAmount);
|
|
||||||
BigInteger msOutputAmount = trade.getTradeAmount().add(collateralAmount).add(collateralAmount);
|
|
||||||
|
|
||||||
String offererPubKey = requestTradeMessage.getOffererPubKey();
|
|
||||||
String takerPubKey = walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString();
|
|
||||||
String arbitratorPubKey = trade.getOffer().getArbitrator().getPubKeyAsHex();
|
|
||||||
String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex();
|
|
||||||
|
|
||||||
checkNotNull(takerInputAmount);
|
|
||||||
checkNotNull(msOutputAmount);
|
|
||||||
checkNotNull(offererPubKey);
|
|
||||||
checkNotNull(takerPubKey);
|
|
||||||
checkNotNull(arbitratorPubKey);
|
|
||||||
checkNotNull(preparedOffererDepositTxAsHex);
|
|
||||||
|
|
||||||
log.debug("2.10 offererCreatesMSTxAndAddPayment");
|
|
||||||
log.debug("takerAmount " + BtcFormatter.formatSatoshis(takerInputAmount));
|
|
||||||
log.debug("msOutputAmount " + BtcFormatter.formatSatoshis(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, trade.getId());
|
|
||||||
log.debug("2.10 deposit tx created: " + signedTakerDepositTx);
|
|
||||||
long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex();
|
|
||||||
sendSignedTakerDepositTxAsHex(signedTakerDepositTx, takerTxOutIndex, requestTradeMessage.getOffererTxOutIndex());
|
|
||||||
} catch (InsufficientMoneyException e)
|
|
||||||
{
|
|
||||||
log.error("2.10 error at walletFacade.takerAddPaymentAndSign: " + e.getMessage());
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 2.11 Send the tx to the offerer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/* private void sendSignedTakerDepositTxAsHex(Transaction signedTakerDepositTx, long takerTxOutIndex, long offererTxOutIndex)
|
|
||||||
{
|
|
||||||
log.debug("2.11 sendSignedTakerDepositTxAsHex");
|
|
||||||
|
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onResult()
|
|
||||||
{
|
|
||||||
log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onResult");
|
|
||||||
// Message arrived at taker
|
|
||||||
// //TakerAsSellerProtocol.this. listener.onFailure(getProgress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed()
|
|
||||||
{
|
|
||||||
log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onFailed");
|
|
||||||
////TakerAsSellerProtocol.this. listener.onFailure("sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onFailed");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// this.listener.onProgress(getProgress());
|
|
||||||
|
|
||||||
BankAccount bankAccount = user.getCurrentBankAccount();
|
|
||||||
String accountID = user.getAccountId();
|
|
||||||
String messagePubKey = user.getMessagePubKeyAsHex();
|
|
||||||
String contractAsJson = trade.getContractAsJson();
|
|
||||||
String signature = trade.getTakerSignature();
|
|
||||||
|
|
||||||
String signedTakerDepositTxAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.bitcoinSerialize());
|
|
||||||
String txScriptSigAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes());
|
|
||||||
String txConnOutAsHex = com.google.bitcoin.core.Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize());
|
|
||||||
//TODO just 1 address supported yet
|
|
||||||
String payoutAddress = walletFacade.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);
|
|
||||||
|
|
||||||
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.REQUEST_OFFERER_DEPOSIT_PUBLICATION,
|
|
||||||
trade.getId(),
|
|
||||||
bankAccount,
|
|
||||||
accountID,
|
|
||||||
messagePubKey,
|
|
||||||
signedTakerDepositTxAsHex,
|
|
||||||
txScriptSigAsHex,
|
|
||||||
txConnOutAsHex,
|
|
||||||
contractAsJson,
|
|
||||||
signature,
|
|
||||||
payoutAddress,
|
|
||||||
takerTxOutIndex,
|
|
||||||
offererTxOutIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
log.debug("2.11 sendTradingMessage");
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
//************************************************************************************************
|
|
||||||
// 3.1 - 3.5 Offerers tasks, we are in waiting mode
|
|
||||||
//************************************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 3.6 Incoming msg from offerer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/* public void onDepositTxPublishedMessage(TradeMessageOld tradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("3.6 DepositTxID received: " + tradeMessage.getDepositTxAsHex());
|
|
||||||
|
|
||||||
String txID = walletFacade.takerCommitDepositTx(tradeMessage.getDepositTxAsHex());
|
|
||||||
// listener.onProgress(getProgress());
|
|
||||||
listener.onDepositTxPublishedMessage(txID);
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
//************************************************************************************************
|
|
||||||
// 3.7-3.10 Offerers tasks, we are in waiting mode
|
|
||||||
//************************************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 3.11 Incoming msg from offerer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/* public void onBankTransferInitedMessage(BankTransferInitedMessage tradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("3.11 Bank transfer inited msg received");
|
|
||||||
listener.onBankTransferInitedMessage(tradeMessage);
|
|
||||||
} */
|
|
||||||
|
|
||||||
//************************************************************************************************
|
|
||||||
// Taker will check periodically his bank account until he received the money. That might take a while...
|
|
||||||
//************************************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 3.12 User clicked the "bank transfer received" button, so we release the funds for pay out
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/* public void onUIEventFiatReceived(TradeMessageOld tradeMessage)
|
|
||||||
{
|
|
||||||
log.debug("3.12 onUIEventFiatReceived");
|
|
||||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
|
||||||
{
|
|
||||||
System.out.println("######### 3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction);
|
|
||||||
log.debug("3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction);
|
|
||||||
listener.onPayoutTxPublished(transaction.getHashAsString());
|
|
||||||
|
|
||||||
sendPayoutTxToOfferer(Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable t)
|
|
||||||
{
|
|
||||||
log.error("######### 3.12 onFailure walletFacade.takerSignsAndSendsTx");
|
|
||||||
System.err.println("3.12 onFailure walletFacade.takerSignsAndSendsTx");
|
|
||||||
// listener.onFailure("takerSignsAndSendsTx failed " + t.getMessage());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String depositTxAsHex = tradeMessage.getDepositTxAsHex();
|
|
||||||
String offererSignatureR = tradeMessage.getOffererSignatureR();
|
|
||||||
String offererSignatureS = tradeMessage.getOffererSignatureS();
|
|
||||||
BigInteger offererPaybackAmount = tradeMessage.getOffererPaybackAmount();
|
|
||||||
BigInteger takerPaybackAmount = tradeMessage.getTakerPaybackAmount();
|
|
||||||
String offererPayoutAddress = tradeMessage.getOffererPayoutAddress();
|
|
||||||
|
|
||||||
log.debug("3.12 walletFacade.takerSignsAndSendsTx");
|
|
||||||
walletFacade.takerSignsAndSendsTx(depositTxAsHex,
|
|
||||||
offererSignatureR,
|
|
||||||
offererSignatureS,
|
|
||||||
offererPaybackAmount,
|
|
||||||
takerPaybackAmount,
|
|
||||||
offererPayoutAddress,
|
|
||||||
trade.getId(),
|
|
||||||
callback);
|
|
||||||
} catch (AddressFormatException e)
|
|
||||||
{
|
|
||||||
log.error("3.12 offererCreatesAndSignsPayoutTx onFailed AddressFormatException " + e.getMessage());
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Step 3.13 Send payout txID to offerer
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/*void sendPayoutTxToOfferer(String payoutTxAsHex)
|
|
||||||
{
|
|
||||||
log.debug("3.13 sendPayoutTxToOfferer ");
|
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onResult()
|
|
||||||
{
|
|
||||||
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onResult");
|
|
||||||
log.debug("3.13 TRADE COMPLETE!!!!!!!!!!!");
|
|
||||||
//TakerAsSellerProtocol.this. listener.onFailure(getProgress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed()
|
|
||||||
{
|
|
||||||
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed");
|
|
||||||
//TakerAsSellerProtocol.this. listener.onFailure("sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.PAYOUT_TX_PUBLISHED, trade.getId());
|
|
||||||
tradeMessage.setPayoutTxAsHex(payoutTxAsHex);
|
|
||||||
log.debug("3.13 sendTradeMessage PAYOUT_TX_PUBLISHED");
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* private double getProgress()
|
|
||||||
{
|
|
||||||
currentStep++;
|
|
||||||
int numberOfSteps = 10;
|
|
||||||
return (double) currentStep / (double) numberOfSteps;
|
|
||||||
} */
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package io.bitsquare.trade.protocol.taker;
|
||||||
|
|
||||||
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
|
import io.bitsquare.trade.protocol.FaultHandler;
|
||||||
|
import io.bitsquare.trade.protocol.ResultHandler;
|
||||||
|
import io.bitsquare.trade.protocol.shared.VerifyPeerAccount;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class VerifyOffererAccount
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
|
||||||
|
|
||||||
|
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount)
|
||||||
|
{
|
||||||
|
VerifyPeerAccount.run(resultHandler, faultHandler, blockChainFacade, peersAccountId, peersBankAccount);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,65 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
|
||||||
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
|
||||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
|
||||||
import io.bitsquare.trade.Trade;
|
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.AcceptTakeOfferRequestMessage;
|
|
||||||
import io.bitsquare.trade.protocol.messages.offerer.RejectTakeOfferRequestMessage;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class HandleTakeOfferRequest
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(HandleTakeOfferRequest.class);
|
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade.State tradeState, String tradeId)
|
|
||||||
{
|
|
||||||
if (tradeState == Trade.State.OPEN)
|
|
||||||
{
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, new AcceptTakeOfferRequestMessage(tradeId), new OutgoingTradeMessageListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onResult()
|
|
||||||
{
|
|
||||||
log.trace("AcceptTakeOfferRequestMessage successfully arrived at peer");
|
|
||||||
resultHandler.onResult(Trade.State.ACCEPTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed()
|
|
||||||
{
|
|
||||||
log.error("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer");
|
|
||||||
faultHandler.onFault(new Exception("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RejectTakeOfferRequestMessage msg = new RejectTakeOfferRequestMessage(tradeId);
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, msg, new OutgoingTradeMessageListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onResult()
|
|
||||||
{
|
|
||||||
log.trace("RejectTakeOfferRequestMessage successfully arrived at peer");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed()
|
|
||||||
{
|
|
||||||
log.error("RejectTakeOfferRequestMessage faultHandler.onFault to arrive at peer");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
log.error("Offer not marked as open.");
|
|
||||||
faultHandler.onFault(new Exception("Offer not marked as open."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ResultHandler
|
|
||||||
{
|
|
||||||
void onResult(Trade.State tradeState);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
import com.google.bitcoin.core.TransactionConfidence;
|
|
||||||
import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocolListener;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class SetupListenerForBlockChainConfirmation
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
|
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, Transaction depositTransaction, OffererAsBuyerProtocolListener listener)
|
|
||||||
{ //TODO
|
|
||||||
// sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
|
|
||||||
|
|
||||||
depositTransaction.getConfidence().addEventListener(new TransactionConfidence.Listener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onConfidenceChanged(Transaction tx, ChangeReason reason)
|
|
||||||
{
|
|
||||||
log.trace("onConfidenceChanged " + tx.getConfidence());
|
|
||||||
if (reason == ChangeReason.SEEN_PEERS)
|
|
||||||
{
|
|
||||||
listener.onDepositTxConfirmedUpdate(tx.getConfidence());
|
|
||||||
}
|
|
||||||
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
|
||||||
{
|
|
||||||
listener.onDepositTxConfirmedInBlockchain();
|
|
||||||
depositTransaction.getConfidence().removeEventListener(this);
|
|
||||||
log.trace("Tx is in blockchain");
|
|
||||||
resultHandler.onResult();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import io.bitsquare.btc.WalletFacade;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class SignAndPublishDepositTx
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class);
|
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler,
|
|
||||||
FaultHandler faultHandler,
|
|
||||||
WalletFacade walletFacade,
|
|
||||||
String preparedOffererDepositTxAsHex,
|
|
||||||
String signedTakerDepositTxAsHex,
|
|
||||||
String txConnOutAsHex,
|
|
||||||
String txScriptSigAsHex,
|
|
||||||
long offererTxOutIndex,
|
|
||||||
long takerTxOutIndex)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
walletFacade.offererSignAndPublishTx(preparedOffererDepositTxAsHex,
|
|
||||||
signedTakerDepositTxAsHex,
|
|
||||||
txConnOutAsHex,
|
|
||||||
txScriptSigAsHex,
|
|
||||||
offererTxOutIndex,
|
|
||||||
takerTxOutIndex,
|
|
||||||
new FutureCallback<Transaction>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onSuccess(Transaction transaction)
|
|
||||||
{
|
|
||||||
log.trace("offererSignAndPublishTx succeeded " + transaction);
|
|
||||||
resultHandler.onResult(transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable t)
|
|
||||||
{
|
|
||||||
log.error("offererSignAndPublishTx faultHandler.onFault:" + t);
|
|
||||||
faultHandler.onFault(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e)
|
|
||||||
{
|
|
||||||
log.error("offererSignAndPublishTx faultHandler.onFault:" + e);
|
|
||||||
faultHandler.onFault(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ResultHandler
|
|
||||||
{
|
|
||||||
void onResult(Transaction transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.ECKey;
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
|
||||||
import io.bitsquare.trade.Contract;
|
|
||||||
import io.bitsquare.trade.Trade;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import io.bitsquare.user.User;
|
|
||||||
import io.bitsquare.util.Utilities;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class CreateAndSignContract
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
|
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler,
|
|
||||||
FaultHandler faultHandler,
|
|
||||||
CryptoFacade cryptoFacade,
|
|
||||||
Trade trade,
|
|
||||||
User user,
|
|
||||||
String peersAccountId,
|
|
||||||
BankAccount peersBankAccount,
|
|
||||||
ECKey registrationKey)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Contract contract = new Contract(trade.getOffer(),
|
|
||||||
trade.getTradeAmount(),
|
|
||||||
trade.getTakeOfferFeeTxId(),
|
|
||||||
peersAccountId,
|
|
||||||
user.getAccountId(),
|
|
||||||
peersBankAccount,
|
|
||||||
user.getCurrentBankAccount(),
|
|
||||||
trade.getOffer().getMessagePubKeyAsHex(),
|
|
||||||
user.getMessagePubKeyAsHex()
|
|
||||||
);
|
|
||||||
|
|
||||||
String contractAsJson = Utilities.objectToJson(contract);
|
|
||||||
String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
|
|
||||||
//log.trace("contract: " + contract);
|
|
||||||
//log.debug("contractAsJson: " + contractAsJson);
|
|
||||||
//log.trace("contract signature: " + signature);
|
|
||||||
|
|
||||||
trade.setContract(contract);
|
|
||||||
trade.setContractAsJson(contractAsJson);
|
|
||||||
trade.setContractTakerSignature(signature);
|
|
||||||
|
|
||||||
resultHandler.onResult();
|
|
||||||
} catch (Throwable t)
|
|
||||||
{
|
|
||||||
log.error("Exception at sign contract " + t);
|
|
||||||
faultHandler.onFault(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
import io.bitsquare.btc.WalletFacade;
|
|
||||||
import io.bitsquare.trade.Trade;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class PayDeposit
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(PayDeposit.class);
|
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, WalletFacade walletFacade, Trade trade, String offererPubKey, String preparedOffererDepositTxAsHex)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
BigInteger collateralAmount = trade.getCollateralAmount();
|
|
||||||
Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSignTx(trade.getTradeAmount().add(collateralAmount),
|
|
||||||
trade.getTradeAmount().add(collateralAmount).add(collateralAmount),
|
|
||||||
offererPubKey,
|
|
||||||
walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString(),
|
|
||||||
trade.getOffer().getArbitrator().getPubKeyAsHex(),
|
|
||||||
preparedOffererDepositTxAsHex,
|
|
||||||
trade.getId());
|
|
||||||
|
|
||||||
log.trace("sharedModel.signedTakerDepositTx: " + signedTakerDepositTx);
|
|
||||||
long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex();
|
|
||||||
|
|
||||||
resultHandler.onResult(signedTakerDepositTx, takerTxOutIndex);
|
|
||||||
} catch (InsufficientMoneyException e)
|
|
||||||
{
|
|
||||||
log.error("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e);
|
|
||||||
faultHandler.onFault(new Exception("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ResultHandler
|
|
||||||
{
|
|
||||||
void onResult(Transaction signedTakerDepositTx, long takerTxOutIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
import com.google.bitcoin.core.Utils;
|
|
||||||
import io.bitsquare.btc.WalletFacade;
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
|
||||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
|
||||||
import io.bitsquare.trade.Trade;
|
|
||||||
import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import io.bitsquare.user.User;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class SendSignedTakerDepositTxAsHex
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
|
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler,
|
|
||||||
FaultHandler faultHandler,
|
|
||||||
PeerAddress peerAddress,
|
|
||||||
MessageFacade messageFacade,
|
|
||||||
WalletFacade walletFacade,
|
|
||||||
Trade trade,
|
|
||||||
User user,
|
|
||||||
Transaction signedTakerDepositTx,
|
|
||||||
long takerTxOutIndex,
|
|
||||||
long offererTxOutIndex)
|
|
||||||
{
|
|
||||||
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(trade.getId(),
|
|
||||||
user.getCurrentBankAccount(),
|
|
||||||
user.getAccountId(),
|
|
||||||
user.getMessagePubKeyAsHex(),
|
|
||||||
Utils.bytesToHexString(signedTakerDepositTx.bitcoinSerialize()),
|
|
||||||
Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes()),
|
|
||||||
Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()),
|
|
||||||
trade.getContractAsJson(),
|
|
||||||
trade.getTakerSignature(),
|
|
||||||
walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString(),
|
|
||||||
takerTxOutIndex,
|
|
||||||
offererTxOutIndex);
|
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onResult()
|
|
||||||
{
|
|
||||||
log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer");
|
|
||||||
resultHandler.onResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed()
|
|
||||||
{
|
|
||||||
log.error("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer");
|
|
||||||
faultHandler.onFault(new Exception("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
import com.google.bitcoin.core.Utils;
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import io.bitsquare.btc.WalletFacade;
|
|
||||||
import io.bitsquare.trade.Trade;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class SignAndPublishPayoutTx
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
|
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler,
|
|
||||||
FaultHandler faultHandler,
|
|
||||||
WalletFacade walletFacade,
|
|
||||||
Trade trade,
|
|
||||||
String depositTxAsHex,
|
|
||||||
String offererSignatureR,
|
|
||||||
String offererSignatureS,
|
|
||||||
BigInteger offererPaybackAmount,
|
|
||||||
BigInteger takerPaybackAmount,
|
|
||||||
String offererPayoutAddress
|
|
||||||
)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
walletFacade.takerSignsAndSendsTx(depositTxAsHex,
|
|
||||||
offererSignatureR,
|
|
||||||
offererSignatureS,
|
|
||||||
offererPaybackAmount,
|
|
||||||
takerPaybackAmount,
|
|
||||||
offererPayoutAddress,
|
|
||||||
trade.getId(),
|
|
||||||
new FutureCallback<Transaction>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onSuccess(Transaction transaction)
|
|
||||||
{
|
|
||||||
log.debug("takerSignsAndSendsTx " + transaction);
|
|
||||||
String payoutTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize());
|
|
||||||
resultHandler.onResult(transaction, payoutTxAsHex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable t)
|
|
||||||
{
|
|
||||||
log.error("Exception at takerSignsAndSendsTx " + t);
|
|
||||||
faultHandler.onFault(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e)
|
|
||||||
{
|
|
||||||
log.error("Exception at takerSignsAndSendsTx " + e);
|
|
||||||
faultHandler.onFault(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ResultHandler
|
|
||||||
{
|
|
||||||
void onResult(Transaction transaction, String payoutTxAsHex);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
package io.bitsquare.trade.protocol.tasks.taker;
|
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
|
||||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class VerifyOffererAccount
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
|
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount)
|
|
||||||
{
|
|
||||||
//TODO mocked yet
|
|
||||||
if (blockChainFacade.verifyAccountRegistration())
|
|
||||||
{
|
|
||||||
if (blockChainFacade.isAccountBlackListed(peersAccountId, peersBankAccount))
|
|
||||||
{
|
|
||||||
log.error("Offerer is blacklisted");
|
|
||||||
faultHandler.onFault(new Exception("Offerer is blacklisted"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resultHandler.onResult();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log.error("Account Registration for peer faultHandler.onFault.");
|
|
||||||
faultHandler.onFault(new Exception("Account Registration for peer faultHandler.onFault."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -94,18 +94,26 @@ public class Arbitrator implements Serializable
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
if (id != null)
|
if (id != null)
|
||||||
|
{
|
||||||
return Objects.hashCode(id);
|
return Objects.hashCode(id);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("NonFinalFieldReferenceInEquals")
|
@SuppressWarnings("NonFinalFieldReferenceInEquals")
|
||||||
public boolean equals(Object obj)
|
public boolean equals(Object obj)
|
||||||
{
|
{
|
||||||
if (!(obj instanceof Arbitrator))
|
if (!(obj instanceof Arbitrator))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (obj == this)
|
if (obj == this)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Arbitrator other = (Arbitrator) obj;
|
Arbitrator other = (Arbitrator) obj;
|
||||||
return id != null && id.equals(other.getId());
|
return id != null && id.equals(other.getId());
|
||||||
|
|
|
@ -46,17 +46,28 @@ public class User implements Serializable
|
||||||
public void addBankAccount(BankAccount bankAccount)
|
public void addBankAccount(BankAccount bankAccount)
|
||||||
{
|
{
|
||||||
if (!bankAccounts.contains(bankAccount))
|
if (!bankAccounts.contains(bankAccount))
|
||||||
|
{
|
||||||
bankAccounts.add(bankAccount);
|
bankAccounts.add(bankAccount);
|
||||||
|
}
|
||||||
|
|
||||||
currentBankAccount = bankAccount;
|
currentBankAccount = bankAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeCurrentBankAccount()
|
public void removeCurrentBankAccount()
|
||||||
{
|
{
|
||||||
if (currentBankAccount != null) bankAccounts.remove(currentBankAccount);
|
if (currentBankAccount != null)
|
||||||
|
{
|
||||||
|
bankAccounts.remove(currentBankAccount);
|
||||||
|
}
|
||||||
|
|
||||||
if (bankAccounts.isEmpty()) currentBankAccount = null;
|
if (bankAccounts.isEmpty())
|
||||||
else currentBankAccount = bankAccounts.get(0);
|
{
|
||||||
|
currentBankAccount = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentBankAccount = bankAccounts.get(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +85,9 @@ public class User implements Serializable
|
||||||
bankAccountUIDs += bankAccount.toString();
|
bankAccountUIDs += bankAccount.toString();
|
||||||
|
|
||||||
if (i < bankAccounts.size() - 1)
|
if (i < bankAccounts.size() - 1)
|
||||||
|
{
|
||||||
bankAccountUIDs += ", ";
|
bankAccountUIDs += ", ";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return bankAccountUIDs;
|
return bankAccountUIDs;
|
||||||
|
@ -136,8 +149,10 @@ public class User implements Serializable
|
||||||
for (final BankAccount bankAccount : bankAccounts)
|
for (final BankAccount bankAccount : bankAccounts)
|
||||||
{
|
{
|
||||||
if (bankAccount.getUid().equals(bankAccountId))
|
if (bankAccount.getUid().equals(bankAccountId))
|
||||||
|
{
|
||||||
return bankAccount;
|
return bankAccount;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,9 +60,13 @@ public class DSAKeyUtil
|
||||||
} catch (Throwable throwable)
|
} catch (Throwable throwable)
|
||||||
{
|
{
|
||||||
if (throwable instanceof FileNotFoundException)
|
if (throwable instanceof FileNotFoundException)
|
||||||
|
{
|
||||||
log.debug("Files not found. That is ok for the first execute.");
|
log.debug("Files not found. That is ok for the first execute.");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
log.error("Could not read key files. " + throwable);
|
log.error("Could not read key files. " + throwable);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -114,16 +118,24 @@ public class DSAKeyUtil
|
||||||
// Work around an issue on Windows whereby you can't rename over existing files.
|
// Work around an issue on Windows whereby you can't rename over existing files.
|
||||||
final File pubKeyCanonicalFile = pubKeyFile.getCanonicalFile();
|
final File pubKeyCanonicalFile = pubKeyFile.getCanonicalFile();
|
||||||
if (pubKeyCanonicalFile.exists() && !pubKeyCanonicalFile.delete())
|
if (pubKeyCanonicalFile.exists() && !pubKeyCanonicalFile.delete())
|
||||||
|
{
|
||||||
throw new IOException("Failed to delete pubKeyCanonicalFile for replacement with save");
|
throw new IOException("Failed to delete pubKeyCanonicalFile for replacement with save");
|
||||||
|
}
|
||||||
if (!pubKeyTempFile.renameTo(pubKeyCanonicalFile))
|
if (!pubKeyTempFile.renameTo(pubKeyCanonicalFile))
|
||||||
|
{
|
||||||
throw new IOException("Failed to rename " + pubKeyTempFile + " to " + pubKeyCanonicalFile);
|
throw new IOException("Failed to rename " + pubKeyTempFile + " to " + pubKeyCanonicalFile);
|
||||||
|
}
|
||||||
|
|
||||||
final File privKeyCanonicalFile = privKeyFile.getCanonicalFile();
|
final File privKeyCanonicalFile = privKeyFile.getCanonicalFile();
|
||||||
if (privKeyCanonicalFile.exists() && !privKeyCanonicalFile.delete())
|
if (privKeyCanonicalFile.exists() && !privKeyCanonicalFile.delete())
|
||||||
|
{
|
||||||
throw new IOException("Failed to delete privKeyCanonicalFile for replacement with save");
|
throw new IOException("Failed to delete privKeyCanonicalFile for replacement with save");
|
||||||
|
}
|
||||||
if (!privKeyTempFile.renameTo(privKeyCanonicalFile))
|
if (!privKeyTempFile.renameTo(privKeyCanonicalFile))
|
||||||
|
{
|
||||||
throw new IOException("Failed to rename " + privKeyTempFile + " to " + privKeyCanonicalFile);
|
throw new IOException("Failed to rename " + privKeyTempFile + " to " + privKeyCanonicalFile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!pubKeyTempFile.renameTo(pubKeyFile))
|
if (!pubKeyTempFile.renameTo(pubKeyFile))
|
||||||
|
@ -141,14 +153,18 @@ public class DSAKeyUtil
|
||||||
{
|
{
|
||||||
log.warn("PubKeyTempFile still exists after failed save.");
|
log.warn("PubKeyTempFile still exists after failed save.");
|
||||||
if (!pubKeyTempFile.delete())
|
if (!pubKeyTempFile.delete())
|
||||||
|
{
|
||||||
log.warn("Cannot delete pubKeyTempFile.");
|
log.warn("Cannot delete pubKeyTempFile.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (privKeyTempFile.exists())
|
if (privKeyTempFile.exists())
|
||||||
{
|
{
|
||||||
log.warn("PrivKeyTempFile still exists after failed save.");
|
log.warn("PrivKeyTempFile still exists after failed save.");
|
||||||
if (!privKeyTempFile.delete())
|
if (!privKeyTempFile.delete())
|
||||||
|
{
|
||||||
log.warn("Cannot delete privKeyTempFile.");
|
log.warn("Cannot delete privKeyTempFile.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,10 @@ public class FileUtil
|
||||||
if (!dir.exists())
|
if (!dir.exists())
|
||||||
{
|
{
|
||||||
if (!dir.mkdir())
|
if (!dir.mkdir())
|
||||||
|
{
|
||||||
log.error("Could not create directory. " + dir.getAbsolutePath());
|
log.error("Could not create directory. " + dir.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,9 @@ public class Utilities
|
||||||
private static void printElapsedTime(String msg)
|
private static void printElapsedTime(String msg)
|
||||||
{
|
{
|
||||||
if (!msg.isEmpty())
|
if (!msg.isEmpty())
|
||||||
|
{
|
||||||
msg += " / ";
|
msg += " / ";
|
||||||
|
}
|
||||||
long timeStamp = System.currentTimeMillis();
|
long timeStamp = System.currentTimeMillis();
|
||||||
log.debug(msg + "Elapsed: " + String.valueOf(timeStamp - lastTimeStamp));
|
log.debug(msg + "Elapsed: " + String.valueOf(timeStamp - lastTimeStamp));
|
||||||
lastTimeStamp = timeStamp;
|
lastTimeStamp = timeStamp;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue