Merge branch 'master' of github.com:bisq-network/bisq-desktop into redesign

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
This commit is contained in:
Christoph Atteneder 2018-09-24 11:34:05 +02:00
commit 3bb503d289
No known key found for this signature in database
GPG key ID: CD5DC1C529CDFD3B
43 changed files with 500 additions and 153 deletions

View file

@ -0,0 +1,55 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.asset;
/**
* {@link AddressValidator} for Base58-encoded Cryptonote addresses.
*
* @author Chris Beams
* @since 0.7.0
*/
public class CryptonoteAddressValidator implements AddressValidator {
private final String prefix;
private final String subAddressPrefix;
private final String validCharactersRegex = "^[1-9A-HJ-NP-Za-km-z]+$";
public CryptonoteAddressValidator(String prefix, String subAddressPrefix) {
this.prefix = prefix;
this.subAddressPrefix = subAddressPrefix;
}
@Override
public AddressValidationResult validate(String address) {
if (!address.matches(validCharactersRegex)) {
// Invalid characters
return AddressValidationResult.invalidStructure();
}
if (address.startsWith(prefix) && address.length() == 94 + prefix.length()) {
// Standard address
return AddressValidationResult.validAddress();
} else if (address.startsWith(subAddressPrefix) && address.length() == 94 + subAddressPrefix.length()) {
// Subaddress
return AddressValidationResult.validAddress();
} else {
// Integrated? Invalid? Doesn't matter
return AddressValidationResult.invalidStructure();
}
}
}

View file

@ -18,11 +18,11 @@
package bisq.asset.coins;
import bisq.asset.Coin;
import bisq.asset.DefaultAddressValidator;
import bisq.asset.CryptonoteAddressValidator;
public class Monero extends Coin {
public Monero() {
super("Monero", "XMR", new DefaultAddressValidator());
super("Monero", "XMR", new CryptonoteAddressValidator("4", "8"));
}
}

View file

@ -17,11 +17,28 @@
package bisq.asset.coins;
import bisq.asset.AbstractAssetWithDefaultValidatorTest;
import bisq.asset.AbstractAssetTest;
import org.junit.Test;
public class MoneroTest extends AbstractAssetWithDefaultValidatorTest {
public class MoneroTest extends AbstractAssetTest {
public MoneroTest() {
super(new Monero());
}
@Test
public void testValidAddresses() {
assertValidAddress("4BJHitCigGy6giuYsJFP26KGkTKiQDJ6HJP1pan2ir2CCV8Twc2WWmo4fu1NVXt8XLGYAkjo5cJ3yH68Lfz9ZXEUJ9MeqPW");
assertValidAddress("46tM15KsogEW5MiVmBn7waPF8u8ZsB6aHjJk7BAv1wvMKfWhQ2h2so5BCJ9cRakfPt5BFo452oy3K8UK6L2u2v7aJ3Nf7P2");
assertValidAddress("86iQTnEqQ9mXJFvBvbY3KU5do5Jh2NCkpTcZsw3TMZ6oKNJhELvAreZFQ1p8EknRRTKPp2vg9fJvy47Q4ARVChjLMuUAFQJ");
}
@Test
public void testInvalidAddresses() {
assertInvalidAddress("");
assertInvalidAddress("4BJHitCigGy6giuYsJFP26KGkTKiQDJ6HJP1pan2ir2CCV8Twc2WWmo4fu1NVXt8XLGYAkjo5cJ3yH68Lfz9ZXEUJ9MeqP");
assertInvalidAddress("4BJHitCigGy6giuYsJFP26KGkTKiQDJ6HJP1pan2ir2CCV8Twc2WWmo4fu1NVXt8XLGYAkjo5cJ3yH68Lfz9ZXEUJ9MeqPWW");
assertInvalidAddress("86iQTnEqQ9mXJFvBvbY3KU5do5Jh2NCkpTcZsw3TMZ6oKNJhELvAreZFQ1p8EknRRTKPp2vg9fJvy47Q4ARVChjLMuUAFQ!");
assertInvalidAddress("76iQTnEqQ9mXJFvBvbY3KU5do5Jh2NCkpTcZsw3TMZ6oKNJhELvAreZFQ1p8EknRRTKPp2vg9fJvy47Q4ARVChjLMuUAFQJ");
}
}

View file

@ -1263,6 +1263,7 @@ message PreferencesPayload {
bool use_trade_notifications = 42;
bool use_market_notifications = 43;
bool use_price_notifications = 44;
bool use_standby_mode = 45;
}
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -19,6 +19,7 @@ package bisq.core;
import bisq.core.alert.AlertModule;
import bisq.core.app.AppOptionKeys;
import bisq.core.app.AvoidStandbyMode;
import bisq.core.app.BisqEnvironment;
import bisq.core.app.BisqFacade;
import bisq.core.app.BisqSetup;
@ -93,6 +94,7 @@ public class CoreModule extends AppModule {
bind(Preferences.class).in(Singleton.class);
bind(BridgeAddressProvider.class).to(Preferences.class).in(Singleton.class);
bind(CorruptedDatabaseFilesHandler.class).in(Singleton.class);
bind(AvoidStandbyMode.class).in(Singleton.class);
bind(SeedNodeAddressLookup.class).in(Singleton.class);
bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class).in(Singleton.class);

View file

@ -0,0 +1,118 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.app;
import bisq.core.user.Preferences;
import javax.inject.Inject;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import lombok.extern.slf4j.Slf4j;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
@Slf4j
public class AvoidStandbyMode {
private final Preferences preferences;
private volatile boolean isStopped;
@Inject
public AvoidStandbyMode(Preferences preferences) {
this.preferences = preferences;
preferences.getUseStandbyModeProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
isStopped = true;
log.info("AvoidStandbyMode stopped");
} else {
start();
}
});
}
public void init() {
isStopped = preferences.isUseStandbyMode();
if (!isStopped) {
start();
}
}
private void start() {
isStopped = false;
log.info("AvoidStandbyMode started");
Thread thread = new Thread(this::play);
thread.setName("AvoidStandbyMode-thread");
thread.start();
}
private void play() {
if (!isStopped) {
OutputStream outputStream = null;
InputStream inputStream = null;
try {
inputStream = getClass().getClassLoader().getResourceAsStream("silent.aiff");
File soundFile = File.createTempFile("Bisq-", "-PreventAppNap-soundFile");
soundFile.deleteOnExit();
outputStream = new FileOutputStream(soundFile);
IOUtils.copy(inputStream, outputStream);
outputStream.close();
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
byte tempBuffer[] = new byte[10000];
AudioFormat audioFormat = audioInputStream.getFormat();
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
int cnt;
while ((cnt = audioInputStream.read(tempBuffer, 0, tempBuffer.length)) != -1 && !isStopped) {
if (cnt > 0) {
sourceDataLine.write(tempBuffer, 0, cnt);
}
}
sourceDataLine.drain();
sourceDataLine.close();
play();
} catch (Exception e) {
log.error(e.toString());
e.printStackTrace();
} finally {
try {
if (inputStream != null)
inputStream.close();
if (outputStream != null)
outputStream.close();
} catch (IOException ignore) {
}
}
}
}
}

View file

@ -45,8 +45,10 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -205,4 +207,152 @@ public class TradeStatisticsManager {
jsonFileManager.writeToDisc(Utilities.objectToJson(array), "trade_statistics");
}
}
// To have automatic check and removal we would need new fields in the asset class for the date when it was
// added/released and a property if it was removed due either getting blocked by the DAO stakehodlers in voting or
// removed due lack of activity.
// For now we use the old script below to print the usage of the coins.
private void printAllCurrencyStats() {
Map<String, Set<TradeStatistics2>> map1 = new HashMap<>();
for (TradeStatistics2 tradeStatistics : observableTradeStatisticsSet) {
if (CurrencyUtil.isFiatCurrency(tradeStatistics.getCounterCurrency())) {
String counterCurrency = CurrencyUtil.getNameAndCode(tradeStatistics.getCounterCurrency());
if (!map1.containsKey(counterCurrency))
map1.put(counterCurrency, new HashSet<>());
map1.get(counterCurrency).add(tradeStatistics);
}
}
StringBuilder sb1 = new StringBuilder("\nAll traded Fiat currencies:\n");
map1.entrySet().stream()
.sorted((o1, o2) -> Integer.compare(o2.getValue().size(), o1.getValue().size()))
.forEach(e -> sb1.append(e.getKey()).append(": ").append(e.getValue().size()).append("\n"));
log.error(sb1.toString());
Map<String, Set<TradeStatistics2>> map2 = new HashMap<>();
for (TradeStatistics2 tradeStatistics : observableTradeStatisticsSet) {
if (CurrencyUtil.isCryptoCurrency(tradeStatistics.getBaseCurrency())) {
final String code = CurrencyUtil.getNameAndCode(tradeStatistics.getBaseCurrency());
if (!map2.containsKey(code))
map2.put(code, new HashSet<>());
map2.get(code).add(tradeStatistics);
}
}
List<String> allCryptoCurrencies = new ArrayList<>();
Set<String> coinsWithValidator = new HashSet<>();
// List of coins with validator before 0.6.0 hard requirements for address validator
coinsWithValidator.add("BTC");
coinsWithValidator.add("BSQ");
coinsWithValidator.add("LTC");
coinsWithValidator.add("DOGE");
coinsWithValidator.add("DASH");
coinsWithValidator.add("ETH");
coinsWithValidator.add("PIVX");
coinsWithValidator.add("IOP");
coinsWithValidator.add("888");
coinsWithValidator.add("ZEC");
coinsWithValidator.add("GBYTE");
coinsWithValidator.add("NXT");
// All those need to have a address validator
Set<String> newlyAdded = new HashSet<>();
// v0.6.0
newlyAdded.add("DCT");
newlyAdded.add("PNC");
newlyAdded.add("WAC");
newlyAdded.add("ZEN");
newlyAdded.add("ELLA");
newlyAdded.add("XCN");
newlyAdded.add("TRC");
newlyAdded.add("INXT");
newlyAdded.add("PART");
// v0.6.1
newlyAdded.add("MAD");
newlyAdded.add("BCH");
newlyAdded.add("BCHC");
newlyAdded.add("BTG");
// v0.6.2
newlyAdded.add("CAGE");
newlyAdded.add("CRED");
newlyAdded.add("XSPEC");
// v0.6.3
newlyAdded.add("WILD");
newlyAdded.add("ONION");
// v0.6.4
newlyAdded.add("CREA");
newlyAdded.add("XIN");
// v0.6.5
newlyAdded.add("BETR");
newlyAdded.add("MVT");
newlyAdded.add("REF");
// v0.6.6
newlyAdded.add("STL");
newlyAdded.add("DAI");
newlyAdded.add("YTN");
newlyAdded.add("DARX");
newlyAdded.add("ODN");
newlyAdded.add("CDT");
newlyAdded.add("DGM");
newlyAdded.add("SCS");
newlyAdded.add("SOS");
newlyAdded.add("ACH");
newlyAdded.add("VDN");
// v0.7.0
newlyAdded.add("ALC");
newlyAdded.add("DIN");
newlyAdded.add("NAH");
newlyAdded.add("ROI");
newlyAdded.add("WMCC");
newlyAdded.add("RTO");
newlyAdded.add("KOTO");
newlyAdded.add("PHR");
newlyAdded.add("UBQ");
newlyAdded.add("QWARK");
newlyAdded.add("GEO");
newlyAdded.add("GRANS");
newlyAdded.add("ICH");
// TODO add remaining coins since 0.7.0
//newlyAdded.clear();
/* new AssetRegistry().stream()
.sorted(Comparator.comparing(o -> o.getName().toLowerCase()))
.filter(e -> !e.getTickerSymbol().equals("BSQ")) // BSQ is not out yet...
.filter(e -> !e.getTickerSymbol().equals("BTC"))
.map(e -> e.getTickerSymbol()) // We want to get rid of duplicated entries for regtest/testnet...
.distinct()
.forEach(e -> newlyAdded.add(e));*/
coinsWithValidator.addAll(newlyAdded);
CurrencyUtil.getAllSortedCryptoCurrencies()
.forEach(e -> allCryptoCurrencies.add(e.getNameAndCode()));
StringBuilder sb2 = new StringBuilder("\nAll traded Crypto currencies:\n");
StringBuilder sb3 = new StringBuilder("\nNever traded Crypto currencies:\n");
map2.entrySet().stream()
.sorted((o1, o2) -> Integer.compare(o2.getValue().size(), o1.getValue().size()))
.forEach(e -> {
String key = e.getKey();
sb2.append(key).append(": ").append(e.getValue().size()).append("\n");
// key is: USD Tether (USDT)
String code = key.substring(key.indexOf("(") + 1, key.length() - 1);
if (!coinsWithValidator.contains(code) && !newlyAdded.contains(code))
allCryptoCurrencies.remove(key);
});
log.error(sb2.toString());
// Not considered age of newly added coins, so take care with removal if coin was added recently.
allCryptoCurrencies.sort(String::compareTo);
allCryptoCurrencies
.forEach(e -> {
// key is: USD Tether (USDT)
String code = e.substring(e.indexOf("(") + 1, e.length() - 1);
if (!coinsWithValidator.contains(code) && !newlyAdded.contains(code))
sb3.append(e).append("\n");
});
log.error(sb3.toString());
}
}

View file

@ -142,6 +142,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
private final String btcNodesFromOptions;
private final String useTorFlagFromOptions;
private final String referralIdFromOptions;
@Getter
private final BooleanProperty useStandbyModeProperty = new SimpleBooleanProperty(prefPayload.isUseStandbyMode());
///////////////////////////////////////////////////////////////////////////////////////////
@ -168,6 +170,12 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
GlobalSettings.setUseAnimations(prefPayload.isUseAnimations());
persist();
});
useStandbyModeProperty.addListener((ov) -> {
prefPayload.setUseStandbyMode(useStandbyModeProperty.get());
persist();
});
fiatCurrenciesAsObservable.addListener((javafx.beans.Observable ov) -> {
prefPayload.getFiatCurrencies().clear();
prefPayload.getFiatCurrencies().addAll(fiatCurrenciesAsObservable);
@ -254,6 +262,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
// set all properties
useAnimationsProperty.set(prefPayload.isUseAnimations());
useStandbyModeProperty.set(prefPayload.isUseStandbyMode());
useCustomWithdrawalTxFeeProperty.set(prefPayload.isUseCustomWithdrawalTxFee());
withdrawalTxFeeInBytesProperty.set(prefPayload.getWithdrawalTxFeeInBytes());
@ -583,6 +592,9 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
persist();
}
public void setUseStandbyMode(boolean useStandbyMode) {
this.useStandbyModeProperty.set(useStandbyMode);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter
@ -782,5 +794,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
List<String> getBridgeAddresses();
long getWithdrawalTxFeeInBytes();
void setUseStandbyMode(boolean useStandbyMode);
}
}

View file

@ -109,6 +109,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
boolean useTradeNotifications = true;
boolean useMarketNotifications = true;
boolean usePriceNotifications = true;
boolean useStandbyMode = false;
///////////////////////////////////////////////////////////////////////////////////////////
@ -162,7 +163,8 @@ public final class PreferencesPayload implements PersistableEnvelope {
.setUseSoundForMobileNotifications(useSoundForMobileNotifications)
.setUseTradeNotifications(useTradeNotifications)
.setUseMarketNotifications(useMarketNotifications)
.setUsePriceNotifications(usePriceNotifications);
.setUsePriceNotifications(usePriceNotifications)
.setUseStandbyMode(useStandbyMode);
Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory);
Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((PB.TradeCurrency) e.toProtoMessage()));
Optional.ofNullable(offerBookChartScreenCurrencyCode).ifPresent(builder::setOfferBookChartScreenCurrencyCode);
@ -235,6 +237,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
proto.getUseSoundForMobileNotifications(),
proto.getUseTradeNotifications(),
proto.getUseMarketNotifications(),
proto.getUsePriceNotifications());
proto.getUsePriceNotifications(),
proto.getUseStandbyMode());
}
}

View file

@ -532,7 +532,7 @@ portfolio.pending.step2_buyer.halCashInfo.headline=Send HalCash code
portfolio.pending.step2_buyer.halCashInfo.msg=You need to send a text message with the HalCash code as well as the \
trade ID ({0}) to the BTC seller.\nThe seller''s mobile nr. is {1}.\n\n\
Did you send the code to the seller?
portfolio.pending.step2_buyer.fasterPaymentsHolderNameInfo=Some banks might require the receivers name. \
portfolio.pending.step2_buyer.fasterPaymentsHolderNameInfo=Some banks might require the receiver's name. \
The UK sort code and account number is sufficient for a Faster Payment transfer and the receivers name is not verified \
by any of the banks.
portfolio.pending.step2_buyer.confirmStart.headline=Confirm that you have started the payment
@ -540,6 +540,7 @@ portfolio.pending.step2_buyer.confirmStart.msg=Did you initiate the {0} payment
portfolio.pending.step2_buyer.confirmStart.yes=Yes, I have started the payment
portfolio.pending.step2_seller.waitPayment.headline=Wait for payment
portfolio.pending.step2_seller.f2fInfo.headline=Buyer's contact information
portfolio.pending.step2_seller.waitPayment.msg=The deposit transaction has at least one blockchain confirmation.\nYou need to wait until the BTC buyer starts the {0} payment.
portfolio.pending.step2_seller.warn=The BTC buyer still has not done the {0} payment.\nYou need to wait until he starts the payment.\nIf the trade has not been completed on {1} the arbitrator will investigate.
portfolio.pending.step2_seller.openForDispute=The BTC buyer has not started his payment!\nThe max. allowed period for the trade has elapsed.\nYou can wait longer and give the trading peer more time or contact the arbitrator for opening a dispute.
@ -826,6 +827,7 @@ setting.preferences.general=General preferences
setting.preferences.explorer=Bitcoin block explorer:
setting.preferences.deviation=Max. deviation from market price:
setting.preferences.autoSelectArbitrators=Auto select arbitrators:
setting.preferences.avoidStandbyMode=Avoid standby mode:
setting.preferences.deviationToLarge=Values higher than {0}% are not allowed.
setting.preferences.txFee=Withdrawal transaction fee (satoshis/byte):
setting.preferences.useCustomValue=Use custom value
@ -1787,6 +1789,13 @@ popup.info.securityDepositInfo=To ensure that both traders follow the trade prot
popup.info.cashDepositInfo=Please be sure that you have a bank branch in your area to be able to make the cash deposit.\n\
The bank ID (BIC/SWIFT) of the seller''s bank is: {0}.
popup.info.cashDepositInfo.confirm=I confirm that I can make the deposit
popup.info.shutDownWithOpenOffers=You try to shut down Bisq with open offers. \n\n\
When you shut down Bisq your offers are not available anymore in the P2P network. \
The next time you start up Bisq again your offers will get re-published to the P2P network.\n\n\
If you want to keep your offers online you need to leave Bisq running. \
Be sure that your computer does not switch to standby mode when not active. \
Standby mode of the monitor is not a problem.
popup.privateNotification.headline=Important private notification!

Binary file not shown.

View file

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 657 B

After

Width:  |  Height:  |  Size: 657 B

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View file

@ -2,53 +2,57 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LSMinimumSystemVersion</key>
<string>10.7.4</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<!-- See: https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -->
<key>CFBundleVersion</key>
<string>0.8.0</string>
<key>CFBundleShortVersionString</key>
<string>0.8.0</string>
<key>CFBundleExecutable</key>
<string>Bisq</string>
<key>CFBundleIconFile</key>
<string>package/osx/Bisq.icns</string>
<key>CFBundleName</key>
<string>Bisq</string>
<key>CFBundleIdentifier</key>
<string>io.bisq.CAT</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1</string>
<!-- CFBundleSignature exists only for compatibility with Classic macOS apps and documents. Modern macOS apps don't need to worry about assigning a Bundle Signature.-->
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleIconFile</key>
<string>Bisq.icns</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.finance</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright (C) 2018</string>
<string>Copyright © 2013-2018 - The Bisq developers</string>
<!-- Only supported in older OSX versions.
See: https://github.com/bitcoin/bitcoin/issues/11896#issuecomment-352148399-->
<key>LSAppNapIsDisabled</key>
<true/>
<!-- See: https://developer.apple.com/library/archive/qa/qa1734/_index.html-->
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>NSHighResolutionCapable</key>
<string>true</string>
<key>JVMRuntime</key>
<string>..</string>
<key>JVMMainClassName</key>
<string>bisq.desktop.app.BisqAppMain</string>
<key>JVMAppClasspath</key>
<string></string>
<key>JVMMainJarName</key>
<string>Bisq-0.8.0.jar</string>
<key>JVMPreferencesID</key>
<string>bisq</string>
<key>JVMOptions</key>
<array>
</array>
<key>JVMUserOptions</key>
<dict>
</dict>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>10.7.4</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
</dict>
</plist>

View file

@ -30,16 +30,17 @@ shasum -a256 $EXE_JAR | awk '{print $1}'
# We make a deterministic jar by stripping out comments with date, etc.
# jar file created from https://github.com/ManfredKarrer/tools
java -jar ./package/osx/tools-1.0.jar $EXE_JAR
java -jar ./package/macosx/tools-1.0.jar $EXE_JAR
echo SHA 256 after stripping jar file to get a deterministic jar:
shasum -a256 $EXE_JAR | awk '{print $1}' | tee deploy/Bisq-$version.jar.txt
linux32=/Volumes/vm_shared_ubuntu14_32bit
linux64=/Volumes/vm_shared_ubuntu
win32=/Volumes/vm_shared_windows_32bit
win64=/Volumes/vm_shared_windows
# vmPath=/Volumes
vmPath=/Users/dev
linux32=$vmPath/vm_shared_ubuntu14_32bit
linux64=$vmPath/vm_shared_ubuntu
win32=$vmPath/vm_shared_windows_32bit
win64=$vmPath/vm_shared_windows
mkdir -p $linux32 $linux64 $win32 $win64
@ -92,7 +93,7 @@ $JAVA_HOME/bin/javapackager \
-BappVersion=$version \
-Bmac.CFBundleIdentifier=io.bisq.CAT \
-Bmac.CFBundleName=Bisq \
-Bicon=package/osx/Bisq.icns \
-Bicon=package/macosx/Bisq.icns \
-Bruntime="$JAVA_HOME/jre" \
-native dmg \
-name Bisq \
@ -104,12 +105,6 @@ $JAVA_HOME/bin/javapackager \
-appclass bisq.desktop.app.BisqAppMain \
-outfile Bisq
rm "deploy/Bisq.html"
rm "deploy/Bisq.jnlp"
mv "deploy/bundles/Bisq-$version.dmg" "deploy/Bisq-$version.dmg"
rm -r "deploy/bundles"
open deploy
cd package/osx
cd package/macosx

View file

@ -1,11 +0,0 @@
#!/bin/bash
cd /home/bs/.local/share
find . -name \*.DS_Store -type f -delete
find . -name \*._.DS_Store -type f -delete
find . -name \*SequenceNumberMap -type f -delete
find . -name \*PersistedPeers -type f -delete
find . -name \*bisq.log -type f -delete
find . -name \*__MACOSX -type d -delete
find . -name \*backup -type d -exec rm -R -f {} +

View file

@ -1,10 +0,0 @@
#!/bin/bash
cd /Users/dev/Library/Application\ Support
for i in `seq 101 500`;
do
dir=BS_$i
mkdir $dir
cp -av BS_/* $dir/
done

View file

@ -1,22 +0,0 @@
#!/bin/bash
cd ../../seednode/target
logpath=/Users/dev/Documents/_intellij/bisq/logs
datapath="/Users/dev/Library/Application Support"
mkdir -p $logpath
# rm "$datapath/bisq_seed_node_hlitt7z4bec4kdh4.onion_8000/db/SequenceNumberMap"
# rm "$datapath/bisq_seed_node_hlitt7z4bec4kdh4.onion_8000/db/PersistedPeers"
# rm "$datapath/BS_arb/mainnet/db/SequenceNumberMap"
# rm "$datapath/BS_arb/mainnet/db/PersistedPeers"
nohup bisq-seednode hlitt7z4bec4kdh4.onion:8000 0 500 >/dev/null 2>$logpath/ST_0_seednode.log &
sleep 40
cd ../../build
nohup build/app/bin/bisq-desktop --app.name=BS_arb --maxConnections=12 >/dev/null 2>$logpath/ST_0_arb.log &
# kill `ps -ef | grep java | grep -v grep | awk '{print $2}'`

View file

@ -1,20 +0,0 @@
#!/bin/bash
dir=/Users/dev/Desktop/10_offers
for i in `seq 1 20`;
do
echo $i
rm $dir/BS_$i/mainnet/tor/tor.real
rm $dir/BS_$i/mainnet/tor/geoip
rm $dir/BS_$i/mainnet/tor/geoip6
rm $dir/BS_$i/mainnet/tor/cached-microdescs
rm $dir/BS_$i/mainnet/tor/cached-microdesc-consensus
rm $dir/BS_$i/mainnet/db/SequenceNumberMap
rm $dir/BS_$i/mainnet/db/PersistedPeers
rm -R -f $dir/BS_$i/mainnet/tor/__MACOSX
rm -R -f $dir/BS_$i/mainnet/tor/hiddenservice/backup
rm -R -f $dir/BS_$i/mainnet/keys/backup
rm -R -f $dir/BS_$i/mainnet/db/backup
rm -R -f $dir/BS_$i/mainnet/bitcoin/backup
done

View file

@ -1,20 +0,0 @@
#!/bin/bash
logpath=/home/bs/bisq/logs
datapath=/home/bs/.local/share
mkdir -p $logpath
cd ../../build
delay=40
# edit start end index
for i in `seq 0 0`;
do
echo $i
nohup build/app/bin/bisq-desktop --app.name=BS_$i --maxConnections=12 >/dev/null 2>$logpath/ST_$i.log &
sleep $delay
done
# kill `ps -ef | grep java | grep -v grep | awk '{print $2}'`

View file

@ -34,10 +34,13 @@ import bisq.desktop.util.ImageUtil;
import bisq.core.alert.AlertManager;
import bisq.core.app.AppOptionKeys;
import bisq.core.app.AvoidStandbyMode;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.WalletsManager;
import bisq.core.filter.FilterManager;
import bisq.core.locale.Res;
import bisq.core.offer.OpenOfferManager;
import bisq.core.user.Preferences;
import bisq.common.UserThread;
import bisq.common.app.DevEnv;
@ -122,6 +125,8 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
scene = createAndConfigScene(mainView, injector);
setupStage(scene);
injector.getInstance(AvoidStandbyMode.class).init();
UserThread.runPeriodically(() -> Profiler.printSystemLoad(log), LOG_MEMORY_PERIOD_MIN, TimeUnit.MINUTES);
} catch (Throwable throwable) {
log.error("Error during app init", throwable);
@ -209,7 +214,7 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
stage.setOnCloseRequest(event -> {
event.consume();
stop();
shutDownByUser();
});
// configure the primary stage
@ -244,7 +249,7 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
scene.addEventHandler(KeyEvent.KEY_RELEASED, keyEvent -> {
if (Utilities.isCtrlPressed(KeyCode.W, keyEvent) ||
Utilities.isCtrlPressed(KeyCode.Q, keyEvent)) {
stop();
shutDownByUser();
} else {
if (Utilities.isAltOrCtrlPressed(KeyCode.E, keyEvent)) {
showBtcEmergencyWalletPopup(injector);
@ -277,6 +282,26 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
});
}
private void shutDownByUser() {
if (injector.getInstance(OpenOfferManager.class).getObservableList().isEmpty()) {
// No open offers, so no need to show the popup.
stop();
return;
}
// We show a popup to inform user that open offers will be removed if Bisq is not running.
String key = "showOpenOfferWarnPopupAtShutDown";
if (injector.getInstance(Preferences.class).showAgain(key)) {
new Popup<>().information(Res.get("popup.info.shutDownWithOpenOffers"))
.dontShowAgainId(key)
.useShutDownButton()
.closeButtonText(Res.get("shared.cancel"))
.show();
} else {
stop();
}
}
private void showSendAlertMessagePopup(Injector injector) {
AlertManager alertManager = injector.getInstance(AlertManager.class);
boolean useDevPrivilegeKeys = injector.getInstance(Key.get(Boolean.class, Names.named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS)));

View file

@ -59,10 +59,10 @@ public class F2FForm extends PaymentMethodForm {
private Country selectedCountry;
public static int addFormForBuyer(GridPane gridPane, int gridRow,
PaymentAccountPayload paymentAccountPayload, Offer offer) {
PaymentAccountPayload paymentAccountPayload, Offer offer, double top) {
F2FAccountPayload f2fAccountPayload = (F2FAccountPayload) paymentAccountPayload;
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.getWithCol("shared.country"),
CountryUtil.getNameAndCode(f2fAccountPayload.getCountryCode()));
CountryUtil.getNameAndCode(f2fAccountPayload.getCountryCode()), top);
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.getWithCol("payment.f2f.contact"),
f2fAccountPayload.getContact());
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.getWithCol("payment.f2f.city"),

View file

@ -60,7 +60,7 @@ public class Notification extends Overlay<Notification> {
public void onReadyForDisplay() {
super.display();
if (autoClose && autoCloseTimer == null)
autoCloseTimer = UserThread.runAfter(this::doClose, 4);
autoCloseTimer = UserThread.runAfter(this::doClose, 6);
}
@Override

View file

@ -23,6 +23,8 @@ import bisq.desktop.util.FormBuilder;
import bisq.core.locale.Res;
import bisq.common.UserThread;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
@ -80,8 +82,12 @@ public class WebCamWindow extends Overlay<WebCamWindow> {
protected void addCloseButton() {
super.addCloseButton();
closeButton.setVisible(false);
listener = (observable, oldValue, newValue) -> closeButton.setVisible(newValue != null);
closeButton.setText(Res.get("shared.cancel"));
listener = (observable, oldValue, newValue) -> {
if (newValue != null)
UserThread.execute(() -> closeButton.setText(Res.get("shared.close")));
};
imageView.imageProperty().addListener(listener);
}

View file

@ -269,7 +269,7 @@ public class BuyerStep2View extends TradeStepView {
break;
case PaymentMethod.F2F_ID:
checkNotNull(model.dataModel.getTrade().getOffer(), "model.dataModel.getTrade().getOffer() must not be null");
gridRow = F2FForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload, model.dataModel.getTrade().getOffer());
gridRow = F2FForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload, model.dataModel.getTrade().getOffer(), 0);
break;
case PaymentMethod.BLOCK_CHAINS_ID:
String labelTitle = Res.get("portfolio.pending.step2_buyer.sellersAddress",

View file

@ -17,10 +17,14 @@
package bisq.desktop.main.portfolio.pendingtrades.steps.seller;
import bisq.desktop.components.paymentmethods.F2FForm;
import bisq.desktop.main.portfolio.pendingtrades.PendingTradesViewModel;
import bisq.desktop.main.portfolio.pendingtrades.steps.TradeStepView;
import bisq.desktop.util.FormBuilder;
import bisq.desktop.util.Layout;
import bisq.core.locale.Res;
import bisq.core.payment.payload.F2FAccountPayload;
public class SellerStep2View extends TradeStepView {
@ -32,6 +36,19 @@ public class SellerStep2View extends TradeStepView {
super(model);
}
@Override
protected void addContent() {
addTradeInfoBlock();
addInfoBlock();
if (model.dataModel.getSellersPaymentAccountPayload() instanceof F2FAccountPayload) {
FormBuilder.addTitledGroupBg(gridPane, ++gridRow, 4,
Res.get("portfolio.pending.step2_seller.f2fInfo.headline"), Layout.GROUP_DISTANCE);
gridRow = F2FForm.addFormForBuyer(gridPane, --gridRow, model.dataModel.getSellersPaymentAccountPayload(),
model.dataModel.getTrade().getOffer(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Info
///////////////////////////////////////////////////////////////////////////////////////////
@ -46,6 +63,7 @@ public class SellerStep2View extends TradeStepView {
return Res.get("portfolio.pending.step2_seller.waitPayment.msg", model.dataModel.getCurrencyCode());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Warning
///////////////////////////////////////////////////////////////////////////////////////////
@ -58,6 +76,7 @@ public class SellerStep2View extends TradeStepView {
model.getDateForOpenDispute());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Dispute
///////////////////////////////////////////////////////////////////////////////////////////
@ -70,7 +89,6 @@ public class SellerStep2View extends TradeStepView {
@Override
protected void applyOnDisputeOpened() {
}
}

View file

@ -94,7 +94,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private ComboBox<TradeCurrency> preferredTradeCurrencyComboBox;
// private ComboBox<BaseCurrencyNetwork> selectBaseCurrencyNetworkComboBox;
private CheckBox useAnimationsCheckBox, autoSelectArbitratorsCheckBox, showOwnOffersInOfferBook, sortMarketCurrenciesNumericallyCheckBox, useCustomFeeCheckbox;
private CheckBox useAnimationsCheckBox, autoSelectArbitratorsCheckBox, avoidStandbyModeCheckBox,
showOwnOffersInOfferBook, sortMarketCurrenciesNumericallyCheckBox, useCustomFeeCheckbox;
private int gridRow = 0;
private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, referralIdInputTextField;
private ChangeListener<Boolean> transactionFeeFocusedListener;
@ -177,7 +178,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
///////////////////////////////////////////////////////////////////////////////////////////
private void initializeGeneralOptions() {
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, 8, Res.get("setting.preferences.general"));
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, 9, Res.get("setting.preferences.general"));
GridPane.setColumnSpan(titledGroupBg, 4);
// selectBaseCurrencyNetwork
@ -296,6 +297,10 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
if (!newValue.equals(oldValue))
referralIdService.setReferralId(newValue);
};
// AvoidStandbyMode
avoidStandbyModeCheckBox = addLabelCheckBox(root, ++gridRow,
Res.get("setting.preferences.avoidStandbyMode"), "").second;
}
private void initializeDisplayCurrencies() {
@ -646,6 +651,11 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
autoSelectArbitratorsCheckBox.setSelected(preferences.isAutoSelectArbitrators());
autoSelectArbitratorsCheckBox.setOnAction(e -> preferences.setAutoSelectArbitrators(autoSelectArbitratorsCheckBox.isSelected()));
// We use opposite property (useStandbyMode) in preferences to have the default value (false) set as we want it,
// so users who update gets set avoidStandbyMode=true (useStandbyMode=false)
avoidStandbyModeCheckBox.setSelected(!preferences.isUseStandbyMode());
avoidStandbyModeCheckBox.setOnAction(e -> preferences.setUseStandbyMode(!avoidStandbyModeCheckBox.isSelected()));
}
/* private void onSelectNetwork() {
@ -695,5 +705,6 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
showOwnOffersInOfferBook.setOnAction(null);
autoSelectArbitratorsCheckBox.setOnAction(null);
resetDontShowAgainButton.setOnAction(null);
avoidStandbyModeCheckBox.setOnAction(null);
}
}

View file

@ -462,6 +462,8 @@ public class GUIUtil {
new Popup<>().information(Res.get("popup.warning.notSufficientConnectionsToBtcNetwork", walletsSetup.getMinBroadcastConnections())).show();
else if (!walletsSetup.isDownloadComplete())
new Popup<>().information(Res.get("popup.warning.downloadNotComplete")).show();
else
log.warn("showNotReadyForTxBroadcastPopups called but no case matched. This should never happen if isReadyForTxBroadcast was called before.");
}
public static void requestFocus(Node node) {

View file

@ -336,7 +336,7 @@ public class Connection implements MessageListener {
"That might happen because of async behaviour of CopyOnWriteArraySet");
}
public void addWeakRCapabilitiesListener(SupportedCapabilitiesListener listener) {
public void addWeakCapabilitiesListener(SupportedCapabilitiesListener listener) {
capabilitiesListeners.add(new WeakReference<>(listener));
}

View file

@ -676,7 +676,7 @@ public class PeerManager implements ConnectionListener, PersistedDataHost {
.orElse(new ArrayList<>());
}
Peer peer = new Peer(connection.getPeersNodeAddressOptional().get(), supportedCapabilities);
connection.addWeakRCapabilitiesListener(peer);
connection.addWeakCapabilitiesListener(peer);
return peer;
})
.collect(Collectors.toSet());