mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-07 06:32:47 -04:00
v0.3.4
This commit is contained in:
parent
96090b71ad
commit
86284fe644
30 changed files with 135 additions and 115 deletions
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,4 @@ public class Tuple3<A, B, C> implements Serializable {
|
||||||
result = 31 * result + (third != null ? third.hashCode() : 0);
|
result = 31 * result + (third != null ? third.hashCode() : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
|
@ -52,6 +52,5 @@
|
||||||
<version>4.8</version>
|
<version>4.8</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class FeePolicy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some wallets (Mycelium) don't support higher fees
|
// Some wallets (Mycelium) don't support higher fees
|
||||||
public static Coin getMinFundingFee() {
|
public static Coin getMinRequiredFeeForFundingTx() {
|
||||||
return Coin.valueOf(20_000);
|
return Coin.valueOf(20_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,14 @@ import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.app.Log;
|
||||||
|
import io.bitsquare.btc.BitcoinNetwork;
|
||||||
|
import io.bitsquare.btc.FeePolicy;
|
||||||
import io.bitsquare.btc.blockchain.providers.BlockTrailProvider;
|
import io.bitsquare.btc.blockchain.providers.BlockTrailProvider;
|
||||||
import io.bitsquare.btc.blockchain.providers.BlockchainApiProvider;
|
import io.bitsquare.btc.blockchain.providers.BlockchainApiProvider;
|
||||||
import io.bitsquare.btc.blockchain.providers.BlockrIOProvider;
|
import io.bitsquare.btc.blockchain.providers.BlockrIOProvider;
|
||||||
import io.bitsquare.btc.blockchain.providers.TradeBlockProvider;
|
import io.bitsquare.btc.blockchain.providers.TradeBlockProvider;
|
||||||
|
import io.bitsquare.user.Preferences;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -20,34 +24,47 @@ public class BlockchainService {
|
||||||
private static final Logger log = LoggerFactory.getLogger(BlockchainService.class);
|
private static final Logger log = LoggerFactory.getLogger(BlockchainService.class);
|
||||||
|
|
||||||
private final ArrayList<BlockchainApiProvider> providers;
|
private final ArrayList<BlockchainApiProvider> providers;
|
||||||
|
private final boolean isMainNet;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
public BlockchainService(Preferences preferences) {
|
||||||
|
isMainNet = preferences.getBitcoinNetwork() == BitcoinNetwork.MAINNET;
|
||||||
|
providers = new ArrayList<>(Arrays.asList(new BlockrIOProvider(), new BlockTrailProvider(), new TradeBlockProvider()));
|
||||||
|
}
|
||||||
|
|
||||||
public BlockchainService() {
|
public BlockchainService() {
|
||||||
|
isMainNet = false;
|
||||||
providers = new ArrayList<>(Arrays.asList(new BlockrIOProvider(), new BlockTrailProvider(), new TradeBlockProvider()));
|
providers = new ArrayList<>(Arrays.asList(new BlockrIOProvider(), new BlockTrailProvider(), new TradeBlockProvider()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettableFuture<Coin> requestFeeFromBlockchain(String transactionId) {
|
public SettableFuture<Coin> requestFeeFromBlockchain(String transactionId) {
|
||||||
log.debug("Request fee from providers");
|
Log.traceCall(transactionId);
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
final SettableFuture<Coin> resultFuture = SettableFuture.create();
|
final SettableFuture<Coin> resultFuture = SettableFuture.create();
|
||||||
for (BlockchainApiProvider provider : providers) {
|
|
||||||
GetFeeRequest getFeeRequest = new GetFeeRequest();
|
|
||||||
SettableFuture<Coin> future = getFeeRequest.requestFee(transactionId, provider);
|
|
||||||
Futures.addCallback(future, new FutureCallback<Coin>() {
|
|
||||||
public void onSuccess(Coin fee) {
|
|
||||||
if (!resultFuture.isDone()) {
|
|
||||||
log.info("Request fee from providers done after {} ms.", (System.currentTimeMillis() - startTime));
|
|
||||||
resultFuture.set(fee);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onFailure(@NotNull Throwable throwable) {
|
if (isMainNet) {
|
||||||
if (!resultFuture.isDone()) {
|
for (BlockchainApiProvider provider : providers) {
|
||||||
log.warn("Could not get the fee from any provider after repeated requests.");
|
GetFeeRequest getFeeRequest = new GetFeeRequest();
|
||||||
resultFuture.setException(throwable);
|
SettableFuture<Coin> future = getFeeRequest.requestFee(transactionId, provider);
|
||||||
|
Futures.addCallback(future, new FutureCallback<Coin>() {
|
||||||
|
public void onSuccess(Coin fee) {
|
||||||
|
if (!resultFuture.isDone()) {
|
||||||
|
log.info("Request fee from providers done after {} ms.", (System.currentTimeMillis() - startTime));
|
||||||
|
resultFuture.set(fee);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
public void onFailure(@NotNull Throwable throwable) {
|
||||||
|
if (!resultFuture.isDone()) {
|
||||||
|
log.warn("Could not get the fee from any provider after repeated requests.");
|
||||||
|
resultFuture.setException(throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For regtest/testnet we dont care of the check and set the expected value
|
||||||
|
resultFuture.set(FeePolicy.getMinRequiredFeeForFundingTx());
|
||||||
}
|
}
|
||||||
return resultFuture;
|
return resultFuture;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,18 +31,18 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb
|
||||||
|
|
||||||
public final byte[] sellerSignature;
|
public final byte[] sellerSignature;
|
||||||
public final String sellerPayoutAddress;
|
public final String sellerPayoutAddress;
|
||||||
public final long lockTime;
|
public final long lockTimeAsBlockHeight;
|
||||||
private final NodeAddress senderNodeAddress;
|
private final NodeAddress senderNodeAddress;
|
||||||
|
|
||||||
public FinalizePayoutTxRequest(String tradeId,
|
public FinalizePayoutTxRequest(String tradeId,
|
||||||
byte[] sellerSignature,
|
byte[] sellerSignature,
|
||||||
String sellerPayoutAddress,
|
String sellerPayoutAddress,
|
||||||
long lockTime,
|
long lockTimeAsBlockHeight,
|
||||||
NodeAddress senderNodeAddress) {
|
NodeAddress senderNodeAddress) {
|
||||||
super(tradeId);
|
super(tradeId);
|
||||||
this.sellerSignature = sellerSignature;
|
this.sellerSignature = sellerSignature;
|
||||||
this.sellerPayoutAddress = sellerPayoutAddress;
|
this.sellerPayoutAddress = sellerPayoutAddress;
|
||||||
this.lockTime = lockTime;
|
this.lockTimeAsBlockHeight = lockTimeAsBlockHeight;
|
||||||
this.senderNodeAddress = senderNodeAddress;
|
this.senderNodeAddress = senderNodeAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb
|
||||||
|
|
||||||
FinalizePayoutTxRequest that = (FinalizePayoutTxRequest) o;
|
FinalizePayoutTxRequest that = (FinalizePayoutTxRequest) o;
|
||||||
|
|
||||||
if (lockTime != that.lockTime) return false;
|
if (lockTimeAsBlockHeight != that.lockTimeAsBlockHeight) return false;
|
||||||
if (!Arrays.equals(sellerSignature, that.sellerSignature)) return false;
|
if (!Arrays.equals(sellerSignature, that.sellerSignature)) return false;
|
||||||
if (sellerPayoutAddress != null ? !sellerPayoutAddress.equals(that.sellerPayoutAddress) : that.sellerPayoutAddress != null)
|
if (sellerPayoutAddress != null ? !sellerPayoutAddress.equals(that.sellerPayoutAddress) : that.sellerPayoutAddress != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -72,7 +72,7 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb
|
||||||
int result = super.hashCode();
|
int result = super.hashCode();
|
||||||
result = 31 * result + (sellerSignature != null ? Arrays.hashCode(sellerSignature) : 0);
|
result = 31 * result + (sellerSignature != null ? Arrays.hashCode(sellerSignature) : 0);
|
||||||
result = 31 * result + (sellerPayoutAddress != null ? sellerPayoutAddress.hashCode() : 0);
|
result = 31 * result + (sellerPayoutAddress != null ? sellerPayoutAddress.hashCode() : 0);
|
||||||
result = 31 * result + (int) (lockTime ^ (lockTime >>> 32));
|
result = 31 * result + (int) (lockTimeAsBlockHeight ^ (lockTimeAsBlockHeight >>> 32));
|
||||||
result = 31 * result + (senderNodeAddress != null ? senderNodeAddress.hashCode() : 0);
|
result = 31 * result + (senderNodeAddress != null ? senderNodeAddress.hashCode() : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class ProcessFinalizePayoutTxRequest extends TradeTask {
|
||||||
|
|
||||||
processModel.tradingPeer.setSignature(checkNotNull(message.sellerSignature));
|
processModel.tradingPeer.setSignature(checkNotNull(message.sellerSignature));
|
||||||
processModel.tradingPeer.setPayoutAddressString(nonEmptyStringOf(message.sellerPayoutAddress));
|
processModel.tradingPeer.setPayoutAddressString(nonEmptyStringOf(message.sellerPayoutAddress));
|
||||||
trade.setLockTimeAsBlockHeight(nonNegativeLongOf(message.lockTime));
|
trade.setLockTimeAsBlockHeight(nonNegativeLongOf(message.lockTimeAsBlockHeight));
|
||||||
|
|
||||||
trade.setState(Trade.State.FIAT_PAYMENT_RECEIPT_MSG_RECEIVED);
|
trade.setState(Trade.State.FIAT_PAYMENT_RECEIPT_MSG_RECEIVED);
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class Preferences implements Serializable {
|
||||||
|
|
||||||
private static Locale defaultLocale = Locale.getDefault();
|
private static Locale defaultLocale = Locale.getDefault();
|
||||||
//TODO test with other locales
|
//TODO test with other locales
|
||||||
//private static Locale defaultLocale = Locale.US;
|
// private static Locale defaultLocale = Locale.US;
|
||||||
|
|
||||||
public static Locale getDefaultLocale() {
|
public static Locale getDefaultLocale() {
|
||||||
return defaultLocale;
|
return defaultLocale;
|
||||||
|
@ -416,5 +416,4 @@ public class Preferences implements Serializable {
|
||||||
public boolean getUseTorForBitcoinJ() {
|
public boolean getUseTorForBitcoinJ() {
|
||||||
return useTorForBitcoinJ;
|
return useTorForBitcoinJ;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ import javafx.scene.layout.StackPane;
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.stage.StageStyle;
|
import javafx.stage.StageStyle;
|
||||||
|
import org.bitcoinj.store.BlockStoreException;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.controlsfx.dialog.Dialogs;
|
import org.controlsfx.dialog.Dialogs;
|
||||||
import org.reactfx.EventStreams;
|
import org.reactfx.EventStreams;
|
||||||
|
@ -108,10 +109,15 @@ public class BitsquareApp extends Application {
|
||||||
// setup UncaughtExceptionHandler
|
// setup UncaughtExceptionHandler
|
||||||
Thread.UncaughtExceptionHandler handler = (thread, throwable) -> {
|
Thread.UncaughtExceptionHandler handler = (thread, throwable) -> {
|
||||||
// Might come from another thread
|
// Might come from another thread
|
||||||
log.error("Uncaught Exception from thread " + Thread.currentThread().getName());
|
if (throwable.getCause() != null && throwable.getCause().getCause() != null &&
|
||||||
log.error("Uncaught Exception throwableMessage= " + throwable.getMessage());
|
throwable.getCause().getCause() instanceof BlockStoreException) {
|
||||||
throwable.printStackTrace();
|
log.error(throwable.getMessage());
|
||||||
UserThread.execute(() -> showErrorPopup(throwable, false));
|
} else {
|
||||||
|
log.error("Uncaught Exception from thread " + Thread.currentThread().getName());
|
||||||
|
log.error("Uncaught Exception throwableMessage= " + throwable.getMessage());
|
||||||
|
throwable.printStackTrace();
|
||||||
|
UserThread.execute(() -> showErrorPopup(throwable, false));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Thread.setDefaultUncaughtExceptionHandler(handler);
|
Thread.setDefaultUncaughtExceptionHandler(handler);
|
||||||
Thread.currentThread().setUncaughtExceptionHandler(handler);
|
Thread.currentThread().setUncaughtExceptionHandler(handler);
|
||||||
|
@ -135,7 +141,7 @@ public class BitsquareApp extends Application {
|
||||||
if (mainView != null)
|
if (mainView != null)
|
||||||
mainView.setPersistedFilesCorrupted(corruptedDatabaseFiles);
|
mainView.setPersistedFilesCorrupted(corruptedDatabaseFiles);
|
||||||
});
|
});
|
||||||
|
|
||||||
// load the main view and create the main scene
|
// load the main view and create the main scene
|
||||||
CachingViewLoader viewLoader = injector.getInstance(CachingViewLoader.class);
|
CachingViewLoader viewLoader = injector.getInstance(CachingViewLoader.class);
|
||||||
mainView = (MainView) viewLoader.load(MainView.class);
|
mainView = (MainView) viewLoader.load(MainView.class);
|
||||||
|
|
|
@ -26,7 +26,6 @@ import javafx.scene.layout.Pane;
|
||||||
|
|
||||||
public class TitledGroupBg extends Pane {
|
public class TitledGroupBg extends Pane {
|
||||||
|
|
||||||
|
|
||||||
private final Label label;
|
private final Label label;
|
||||||
private final StringProperty text = new SimpleStringProperty();
|
private final StringProperty text = new SimpleStringProperty();
|
||||||
|
|
||||||
|
|
|
@ -637,7 +637,10 @@ public class MainViewModel implements ViewModel {
|
||||||
if (error instanceof TimeoutException) {
|
if (error instanceof TimeoutException) {
|
||||||
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
||||||
} else if (error.getCause() instanceof BlockStoreException) {
|
} else if (error.getCause() instanceof BlockStoreException) {
|
||||||
walletServiceErrorMsg.set("Bitsquare is already running. You cannot run 2 instances of Bitsquare.");
|
new Popup().warning("Bitsquare is already running. You cannot run 2 instances of Bitsquare.")
|
||||||
|
.closeButtonText("Shut down")
|
||||||
|
.onClose(BitsquareApp.shutDownHandler::run)
|
||||||
|
.show();
|
||||||
} else if (error.getMessage() != null) {
|
} else if (error.getMessage() != null) {
|
||||||
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + error.getMessage());
|
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + error.getMessage());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
<TableView fx:id="table" VBox.vgrow="ALWAYS">
|
<TableView fx:id="table" VBox.vgrow="ALWAYS">
|
||||||
<columns>
|
<columns>
|
||||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="170" maxWidth="170"/>
|
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="180" maxWidth="180"/>
|
||||||
<TableColumn text="Details" fx:id="detailsColumn" minWidth="260"/>
|
<TableColumn text="Details" fx:id="detailsColumn" minWidth="260"/>
|
||||||
<TableColumn text="Address" fx:id="addressColumn" minWidth="320" maxWidth="320">
|
<TableColumn text="Address" fx:id="addressColumn" minWidth="320" maxWidth="320">
|
||||||
<cellValueFactory>
|
<cellValueFactory>
|
||||||
|
|
|
@ -28,12 +28,12 @@
|
||||||
</padding>
|
</padding>
|
||||||
<TableView fx:id="table" VBox.vgrow="ALWAYS">
|
<TableView fx:id="table" VBox.vgrow="ALWAYS">
|
||||||
<columns>
|
<columns>
|
||||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="160" maxWidth="160">
|
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="180" maxWidth="180">
|
||||||
<cellValueFactory>
|
<cellValueFactory>
|
||||||
<PropertyValueFactory property="date"/>
|
<PropertyValueFactory property="date"/>
|
||||||
</cellValueFactory>
|
</cellValueFactory>
|
||||||
</TableColumn>
|
</TableColumn>
|
||||||
<TableColumn text="Details" fx:id="detailsColumn" minWidth="210" maxWidth="210"/>
|
<TableColumn text="Details" fx:id="detailsColumn" minWidth="220" maxWidth="220"/>
|
||||||
<TableColumn text="Address" fx:id="addressColumn" minWidth="180"/>
|
<TableColumn text="Address" fx:id="addressColumn" minWidth="180"/>
|
||||||
<TableColumn text="Transaction" fx:id="transactionColumn" minWidth="100"/>
|
<TableColumn text="Transaction" fx:id="transactionColumn" minWidth="100"/>
|
||||||
<TableColumn text="Amount (BTC)" fx:id="amountColumn" minWidth="110" maxWidth="110">
|
<TableColumn text="Amount (BTC)" fx:id="amountColumn" minWidth="110" maxWidth="110">
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<TableView fx:id="table" VBox.vgrow="ALWAYS">
|
<TableView fx:id="table" VBox.vgrow="ALWAYS">
|
||||||
<columns>
|
<columns>
|
||||||
<TableColumn text="Select" fx:id="selectColumn" minWidth="60" maxWidth="60" sortable="false"/>
|
<TableColumn text="Select" fx:id="selectColumn" minWidth="60" maxWidth="60" sortable="false"/>
|
||||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="170" maxWidth="170"/>
|
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="180" maxWidth="180"/>
|
||||||
<TableColumn text="Details" fx:id="detailsColumn" minWidth="160" maxWidth="160"/>
|
<TableColumn text="Details" fx:id="detailsColumn" minWidth="160" maxWidth="160"/>
|
||||||
<TableColumn text="Address" fx:id="addressColumn" minWidth="320" maxWidth="320">
|
<TableColumn text="Address" fx:id="addressColumn" minWidth="320" maxWidth="320">
|
||||||
<cellValueFactory>
|
<cellValueFactory>
|
||||||
|
|
|
@ -191,9 +191,9 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
|
||||||
new Popup().headLine("Confirm your withdrawal request")
|
new Popup().headLine("Confirm your withdrawal request")
|
||||||
.message("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" +
|
.message("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" +
|
||||||
"From address: " + withdrawFromTextField.getText() + "\n" +
|
"From address: " + withdrawFromTextField.getText() + "\n" +
|
||||||
"To receiving address: " + withdrawToTextField.getText() + ".\n\n" +
|
"To receiving address: " + withdrawToTextField.getText() + ".\n" +
|
||||||
"Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n" +
|
"Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n\n" +
|
||||||
"Recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" +
|
"The recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" +
|
||||||
"Are you sure you want to withdraw that amount?")
|
"Are you sure you want to withdraw that amount?")
|
||||||
.onAction(() -> doWithdraw(receiverAmount, callback))
|
.onAction(() -> doWithdraw(receiverAmount, callback))
|
||||||
.show();
|
.show();
|
||||||
|
|
|
@ -103,6 +103,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList();
|
final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList();
|
||||||
|
|
||||||
private PaymentAccount paymentAccount;
|
private PaymentAccount paymentAccount;
|
||||||
|
private WalletEventListener walletEventListener;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -138,42 +139,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
};
|
};
|
||||||
|
|
||||||
paymentAccountsChangeListener = change -> paymentAccounts.setAll(user.getPaymentAccounts());
|
paymentAccountsChangeListener = change -> paymentAccounts.setAll(user.getPaymentAccounts());
|
||||||
}
|
walletEventListener = new WalletEventListener() {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void activate() {
|
|
||||||
addBindings();
|
|
||||||
addListeners();
|
|
||||||
|
|
||||||
paymentAccounts.setAll(user.getPaymentAccounts());
|
|
||||||
updateBalance(walletService.getBalanceForAddress(getAddressEntry().getAddress()));
|
|
||||||
|
|
||||||
if (direction == Offer.Direction.BUY)
|
|
||||||
calculateTotalToPay();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void deactivate() {
|
|
||||||
removeBindings();
|
|
||||||
removeListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addBindings() {
|
|
||||||
btcCode.bind(preferences.btcDenominationProperty());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeBindings() {
|
|
||||||
btcCode.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isFeeFromFundingTxSufficient() {
|
|
||||||
return feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinFundingFee()) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addListeners() {
|
|
||||||
walletService.addBalanceListener(balanceListener);
|
|
||||||
walletService.getWallet().addEventListener(new WalletEventListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
||||||
requestFeeFromBlockchain(tx.getHashAsString());
|
requestFeeFromBlockchain(tx.getHashAsString());
|
||||||
|
@ -202,28 +168,45 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
@Override
|
@Override
|
||||||
public void onKeysAdded(List<ECKey> keys) {
|
public void onKeysAdded(List<ECKey> keys) {
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestFeeFromBlockchain(String transactionId) {
|
@Override
|
||||||
SettableFuture<Coin> future = blockchainService.requestFeeFromBlockchain(transactionId);
|
protected void activate() {
|
||||||
Futures.addCallback(future, new FutureCallback<Coin>() {
|
addBindings();
|
||||||
public void onSuccess(Coin fee) {
|
addListeners();
|
||||||
UserThread.execute(() -> feeFromFundingTxProperty.set(fee));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onFailure(@NotNull Throwable throwable) {
|
paymentAccounts.setAll(user.getPaymentAccounts());
|
||||||
UserThread.execute(() -> new Popup()
|
updateBalance(walletService.getBalanceForAddress(getAddressEntry().getAddress()));
|
||||||
.warning("We did not get a result for the mining fee used in the funding transaction.")
|
|
||||||
.show());
|
if (direction == Offer.Direction.BUY)
|
||||||
}
|
calculateTotalToPay();
|
||||||
});
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deactivate() {
|
||||||
|
removeBindings();
|
||||||
|
removeListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addBindings() {
|
||||||
|
btcCode.bind(preferences.btcDenominationProperty());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeBindings() {
|
||||||
|
btcCode.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addListeners() {
|
||||||
|
walletService.addBalanceListener(balanceListener);
|
||||||
|
walletService.getWallet().addEventListener(walletEventListener);
|
||||||
|
user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void removeListeners() {
|
private void removeListeners() {
|
||||||
walletService.removeBalanceListener(balanceListener);
|
walletService.removeBalanceListener(balanceListener);
|
||||||
|
walletService.getWallet().removeEventListener(walletEventListener);
|
||||||
user.getPaymentAccountsAsObservable().removeListener(paymentAccountsChangeListener);
|
user.getPaymentAccountsAsObservable().removeListener(paymentAccountsChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,10 +326,30 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
return user.getAcceptedArbitrators().size() > 0;
|
return user.getAcceptedArbitrators().size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isFeeFromFundingTxSufficient() {
|
||||||
|
return feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinRequiredFeeForFundingTx()) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Utils
|
// Utils
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void requestFeeFromBlockchain(String transactionId) {
|
||||||
|
SettableFuture<Coin> future = blockchainService.requestFeeFromBlockchain(transactionId);
|
||||||
|
Futures.addCallback(future, new FutureCallback<Coin>() {
|
||||||
|
public void onSuccess(Coin fee) {
|
||||||
|
UserThread.execute(() -> feeFromFundingTxProperty.set(fee));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFailure(@NotNull Throwable throwable) {
|
||||||
|
UserThread.execute(() -> new Popup()
|
||||||
|
.warning("We did not get a response for the request of the mining fee used in the funding transaction.")
|
||||||
|
.show());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void calculateVolume() {
|
void calculateVolume() {
|
||||||
if (priceAsFiat.get() != null &&
|
if (priceAsFiat.get() != null &&
|
||||||
amountAsCoin.get() != null &&
|
amountAsCoin.get() != null &&
|
||||||
|
|
|
@ -241,7 +241,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
"You can see the details when you move the mouse over the question mark.\n\n" +
|
"You can see the details when you move the mouse over the question mark.\n\n" +
|
||||||
"Important notice!\n" +
|
"Important notice!\n" +
|
||||||
"Please take care that you use a mining fee of at least " +
|
"Please take care that you use a mining fee of at least " +
|
||||||
model.formatter.formatCoinWithCode(FeePolicy.getMinFundingFee()) + " when you transfer bitcoin from your external " +
|
model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + " when you transfer bitcoin from your external " +
|
||||||
"wallet to ensure the trade transactions will get into the blockchain.\n" +
|
"wallet to ensure the trade transactions will get into the blockchain.\n" +
|
||||||
"A too low mining fee might result in a delayed trade and will be rejected!")
|
"A too low mining fee might result in a delayed trade and will be rejected!")
|
||||||
.closeButtonText("I understand")
|
.closeButtonText("I understand")
|
||||||
|
@ -448,7 +448,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
if (!model.dataModel.isFeeFromFundingTxSufficient()) {
|
if (!model.dataModel.isFeeFromFundingTxSufficient()) {
|
||||||
new Popup().warning("The mining fee from your funding transaction is not sufficiently high.\n\n" +
|
new Popup().warning("The mining fee from your funding transaction is not sufficiently high.\n\n" +
|
||||||
"You need to use at least a mining fee of " +
|
"You need to use at least a mining fee of " +
|
||||||
model.formatCoin(FeePolicy.getMinFundingFee()) + ".\n\n" +
|
model.formatCoin(FeePolicy.getMinRequiredFeeForFundingTx()) + ".\n\n" +
|
||||||
"The fee used in your funding transaction was only " + model.formatCoin(newValue) + ".\n\n" +
|
"The fee used in your funding transaction was only " + model.formatCoin(newValue) + ".\n\n" +
|
||||||
"The trade transactions might take too much time to be included in " +
|
"The trade transactions might take too much time to be included in " +
|
||||||
"a block if the fee is too low.\n" +
|
"a block if the fee is too low.\n" +
|
||||||
|
|
|
@ -347,7 +347,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
"You can see the details when you move the mouse over the question mark.\n\n" +
|
"You can see the details when you move the mouse over the question mark.\n\n" +
|
||||||
"Important notice!\n" +
|
"Important notice!\n" +
|
||||||
"Please take care that you use a mining fee of at least " +
|
"Please take care that you use a mining fee of at least " +
|
||||||
model.formatter.formatCoinWithCode(FeePolicy.getMinFundingFee()) + " when you transfer bitcoin from your external " +
|
model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + " when you transfer bitcoin from your external " +
|
||||||
"wallet to ensure the trade transactions will get into the blockchain.\n" +
|
"wallet to ensure the trade transactions will get into the blockchain.\n" +
|
||||||
"A too low mining fee might result in a delayed trade and will be rejected!")
|
"A too low mining fee might result in a delayed trade and will be rejected!")
|
||||||
.closeButtonText("I understand")
|
.closeButtonText("I understand")
|
||||||
|
|
|
@ -321,7 +321,8 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOpenDisputeTimeAsFormattedDate() {
|
public String getOpenDisputeTimeAsFormattedDate() {
|
||||||
return formatter.addBlocksToNowDateFormatted(getOpenDisputeTimeAsBlockHeight() - getBestChainHeight() + (getLockTime() - getBestChainHeight()));
|
return formatter.addBlocksToNowDateFormatted(getOpenDisputeTimeAsBlockHeight() - getBestChainHeight() +
|
||||||
|
(dataModel.getTrade().getOffer().getPaymentMethod().getLockTime()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getReference() {
|
public String getReference() {
|
||||||
|
|
|
@ -150,7 +150,6 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
tradeInfoTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 4, "Trade information");
|
tradeInfoTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 4, "Trade information");
|
||||||
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
||||||
|
|
||||||
//TODO
|
|
||||||
PaymentMethodForm.addAllowedPeriod(gridPane, ++gridRow, model.dataModel.getSellersPaymentAccountContractData(),
|
PaymentMethodForm.addAllowedPeriod(gridPane, ++gridRow, model.dataModel.getSellersPaymentAccountContractData(),
|
||||||
model.getOpenDisputeTimeAsFormattedDate());
|
model.getOpenDisputeTimeAsFormattedDate());
|
||||||
|
|
||||||
|
|
|
@ -294,8 +294,8 @@ public class FormBuilder {
|
||||||
|
|
||||||
InputTextField inputTextField = new InputTextField();
|
InputTextField inputTextField = new InputTextField();
|
||||||
CheckBox checkBox = new CheckBox(checkBoxTitle);
|
CheckBox checkBox = new CheckBox(checkBoxTitle);
|
||||||
checkBox.setPadding(new Insets(6, 0, 0, 0));
|
HBox.setMargin(checkBox, new Insets(4, 0, 0, 0));
|
||||||
|
|
||||||
HBox hBox = new HBox();
|
HBox hBox = new HBox();
|
||||||
hBox.setSpacing(10);
|
hBox.setSpacing(10);
|
||||||
hBox.getChildren().addAll(inputTextField, checkBox);
|
hBox.getChildren().addAll(inputTextField, checkBox);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,6 @@ public abstract class TorNode<M extends OnionProxyManager, C extends OnionProxyC
|
||||||
private static final Logger log = LoggerFactory.getLogger(TorNode.class);
|
private static final Logger log = LoggerFactory.getLogger(TorNode.class);
|
||||||
|
|
||||||
private final OnionProxyManager tor;
|
private final OnionProxyManager tor;
|
||||||
|
|
||||||
public Socks5Proxy getProxy() {
|
|
||||||
return proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Socks5Proxy proxy;
|
private final Socks5Proxy proxy;
|
||||||
|
|
||||||
public TorNode(M mgr) throws IOException {
|
public TorNode(M mgr) throws IOException {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,12 @@ public class SeedNodesRepository {
|
||||||
// regtest use port 8002
|
// regtest use port 8002
|
||||||
private Set<NodeAddress> torSeedNodeAddresses = Sets.newHashSet(
|
private Set<NodeAddress> torSeedNodeAddresses = Sets.newHashSet(
|
||||||
// mainnet
|
// mainnet
|
||||||
// 0.3.3
|
// v0.3.3
|
||||||
/* new NodeAddress("oyyii5ogv7y7iadi.onion:8000"),
|
/* new NodeAddress("oyyii5ogv7y7iadi.onion:8000"),
|
||||||
new NodeAddress("ugcro2f5xnkguash.onion:8000"),
|
new NodeAddress("ugcro2f5xnkguash.onion:8000"),
|
||||||
new NodeAddress("qarhpdsl6mfhbnud.onion:8000"),*/
|
new NodeAddress("qarhpdsl6mfhbnud.onion:8000"),*/
|
||||||
|
|
||||||
|
// v0.3.4
|
||||||
new NodeAddress("lih5zsr2bvxi24pk.onion:8000"),
|
new NodeAddress("lih5zsr2bvxi24pk.onion:8000"),
|
||||||
new NodeAddress("s5xpstlooosehtxm.onion:8000"),
|
new NodeAddress("s5xpstlooosehtxm.onion:8000"),
|
||||||
new NodeAddress("izs5oz7i5ta7c2ir.onion:8000"),
|
new NodeAddress("izs5oz7i5ta7c2ir.onion:8000"),
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -6,7 +6,7 @@
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
<description>Bitsquare - The decentralized bitcoin exchange</description>
|
<description>Bitsquare - The decentralized bitcoin exchange</description>
|
||||||
<url>https://bitsquare.io</url>
|
<url>https://bitsquare.io</url>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<groupId>io.bitsquare</groupId>
|
<groupId>io.bitsquare</groupId>
|
||||||
<version>0.3.4-SNAPSHOT</version>
|
<version>0.3.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue