mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Merge branch 'master' of github.com:bisq-network/bisq into release/v1.1.6
# Conflicts: # core/src/main/java/bisq/core/offer/OfferUtil.java # core/src/main/resources/i18n/displayStrings.properties # desktop/src/main/java/bisq/desktop/main/MainView.java # desktop/src/main/java/bisq/desktop/main/MainViewModel.java # desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java # desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java # desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java # desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java # desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java # desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java # desktop/src/main/java/bisq/desktop/main/support/dispute/DisputeView.java # desktop/src/main/java/bisq/desktop/main/support/dispute/agent/DisputeAgentView.java
This commit is contained in:
commit
cc3128d4e0
@ -179,6 +179,7 @@
|
||||
</Properties>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="RIGHT_MARGIN" value="120" />
|
||||
<option name="KEEP_LINE_BREAKS" value="false" />
|
||||
<option name="BLANK_LINES_BEFORE_PACKAGE" value="1" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||
<option name="WRAP_ON_TYPING" value="0" />
|
||||
|
@ -19,6 +19,7 @@ All Bisq contributors submit changes via pull requests. The workflow is as follo
|
||||
- Fork the repository
|
||||
- Create a topic branch from the `master` branch
|
||||
- Commit patches
|
||||
- Squash redundant or unnecessary commits
|
||||
- Submit a pull request from your topic branch back to the `master` branch of the main repository
|
||||
|
||||
Pull requests should be focused on a single change. Do not mix, for example, refactorings with a bug fix or implementation of a new feature. This practice makes it easier for fellow contributors to review each pull request on its merits and and to give a clear ACK/NACK (see below).
|
||||
@ -73,6 +74,10 @@ https://help.github.com/articles/signing-commits-with-gpg/ for instructions.
|
||||
|
||||
The [.editorconfig](.editorconfig) settings in this repository ensure consistent management of whitespace, line endings and more. Most modern editors support it natively or with plugin. See http://editorconfig.org for details. See also [bisq-network/style#10](https://github.com/bisq-network/style/issues/10).
|
||||
|
||||
### Keep the git history clean
|
||||
|
||||
It's very important to keep the git history clear, light and easily browsable. This means contributors must make sure their pull requests include only meaningful commits (if they are redundant or were added after a review, they should be removed) and _no merge commits_.
|
||||
|
||||
### Additional style guidelines
|
||||
|
||||
See the issues in the [bisq-network/style](https://github.com/bisq-network/style/issues) repository.
|
||||
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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.coins;
|
||||
|
||||
import bisq.asset.AddressValidationResult;
|
||||
import bisq.asset.AddressValidator;
|
||||
import bisq.asset.Coin;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.bitcoinj.core.Base58;
|
||||
import org.bitcoinj.core.AddressFormatException;
|
||||
import org.bouncycastle.crypto.digests.Blake2bDigest;
|
||||
|
||||
public class Ergo extends Coin {
|
||||
|
||||
public Ergo() {
|
||||
super("Ergo", "ERG", new ErgoAddressValidator());
|
||||
}
|
||||
|
||||
public static class ErgoAddressValidator implements AddressValidator {
|
||||
|
||||
@Override
|
||||
public AddressValidationResult validate(String address) {
|
||||
try {
|
||||
byte[] decoded = Base58.decode(address);
|
||||
if (decoded.length < 4) {
|
||||
return AddressValidationResult.invalidAddress("Input too short: " + decoded.length);
|
||||
}
|
||||
if (decoded[0] != 1 && decoded[0] != 2 && decoded[0] != 3) {
|
||||
return AddressValidationResult.invalidAddress("Invalid prefix");
|
||||
}
|
||||
byte[] data = Arrays.copyOfRange(decoded, 0, decoded.length - 4);
|
||||
byte[] checksum = Arrays.copyOfRange(decoded, decoded.length - 4, decoded.length);
|
||||
byte[] hashed = new byte[32];
|
||||
{
|
||||
Blake2bDigest digest = new Blake2bDigest(256);
|
||||
digest.update(data, 0, data.length);
|
||||
digest.doFinal(hashed, 0);
|
||||
}
|
||||
byte[] actualChecksum = Arrays.copyOfRange(hashed, 0, 4);
|
||||
if (!Arrays.equals(checksum, actualChecksum)) {
|
||||
return AddressValidationResult.invalidAddress("Invalid checksum");
|
||||
}
|
||||
} catch (AddressFormatException e) {
|
||||
return AddressValidationResult.invalidAddress(e);
|
||||
}
|
||||
return AddressValidationResult.validAddress();
|
||||
}
|
||||
}
|
||||
}
|
@ -40,7 +40,6 @@ bisq.asset.coins.Donu
|
||||
bisq.asset.coins.Dragonglass
|
||||
bisq.asset.coins.DSTRA
|
||||
bisq.asset.coins.Emercoin
|
||||
bisq.asset.coins.Ergo
|
||||
bisq.asset.coins.Ether
|
||||
bisq.asset.coins.EtherClassic
|
||||
bisq.asset.coins.FourtyTwo
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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.coins;
|
||||
|
||||
import bisq.asset.AbstractAssetTest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ErgoTest extends AbstractAssetTest {
|
||||
|
||||
public ErgoTest() {
|
||||
super(new Ergo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidAddresses() {
|
||||
assertValidAddress("9fRAWhdxEsTcdb8PhGNrZfwqa65zfkuYHAMmkQLcic1gdLSV5vA");
|
||||
assertValidAddress("25qGdVWg2yyYho8uC1pLtc7KxFn4nEEAwD");
|
||||
assertValidAddress("23NL9a8ngN28ovtLiKLgHexcdTKBbUMLhH");
|
||||
assertValidAddress("7bwdkU5V8");
|
||||
assertValidAddress("BxKBaHkvrTvLZrDcZjcsxsF7aSsrN73ijeFZXtbj4CXZHHcvBtqSxQ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidAddresses() {
|
||||
assertInvalidAddress("9fRAWhdxEsTcdb8PhGNrZfwqa65zfkuYHAMmkQLcic1gdLSV5vAaa");
|
||||
assertInvalidAddress("afRAWhdxEsTcdb8PhGNrZfwqa65zfkuYHAMmkQLcic1gdLSV5vA");
|
||||
assertInvalidAddress("25qGdVWg2yyYho8uC1pLtc7KxFn4nEEAwDaa");
|
||||
assertInvalidAddress("23NL9a8ngN28ovtLiKLgHexcdTKBbUMLhHaa");
|
||||
assertInvalidAddress("7bwdkU5V8aa");
|
||||
assertInvalidAddress("BxKBaHkvrTvLZrDcZjcsxsF7aSsrN73ijeFZXtbj4CXZHHcvBtqSxQ#");
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ configure(subprojects) {
|
||||
logbackVersion = '1.1.10'
|
||||
lombokVersion = '1.18.2'
|
||||
mockitoVersion = '3.0.0'
|
||||
netlayerVersion = '0.6.5.1'
|
||||
netlayerVersion = '0.6.5.2'
|
||||
protobufVersion = '3.9.1'
|
||||
pushyVersion = '0.13.2'
|
||||
qrgenVersion = '1.3'
|
||||
@ -158,7 +158,6 @@ configure(project(':assets')) {
|
||||
compile "com.google.guava:guava:$guavaVersion"
|
||||
compile "org.slf4j:slf4j-api:$slf4jVersion"
|
||||
compile "org.apache.commons:commons-lang3:$langVersion"
|
||||
compile "org.bouncycastle:bcpg-jdk15on:$bcVersion"
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,9 +179,6 @@ configure(project(':common')) {
|
||||
compile "org.openjfx:javafx-graphics:11:$os"
|
||||
compile "com.google.protobuf:protobuf-java:$protobufVersion"
|
||||
compile 'com.google.code.gson:gson:2.7'
|
||||
compile("com.googlecode.json-simple:json-simple:$jsonsimpleVersion") {
|
||||
exclude(module: 'junit')
|
||||
}
|
||||
compile "org.springframework:spring-core:$springVersion"
|
||||
compile "org.slf4j:slf4j-api:$slf4jVersion"
|
||||
compile "ch.qos.logback:logback-core:$logbackVersion"
|
||||
@ -199,7 +195,6 @@ configure(project(':common')) {
|
||||
exclude(module: 'protobuf-java')
|
||||
}
|
||||
compile "org.jetbrains:annotations:$jetbrainsAnnotationsVersion"
|
||||
runtime "org.bouncycastle:bcprov-jdk15on:$bcVersion"
|
||||
compile "org.bouncycastle:bcpg-jdk15on:$bcVersion"
|
||||
compile "commons-io:commons-io:$ioVersion"
|
||||
compile "org.apache.commons:commons-lang3:$langVersion"
|
||||
@ -396,7 +391,6 @@ configure(project(':seednode')) {
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
runtime "org.bouncycastle:bcprov-jdk15on:$bcVersion"
|
||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
testCompile "org.springframework:spring-test:$springVersion"
|
||||
|
@ -54,8 +54,7 @@ public class FrameRateTimer implements Timer, Runnable {
|
||||
stop();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
log.error(t.getMessage());
|
||||
t.printStackTrace();
|
||||
log.error("exception in FrameRateTimer", t);
|
||||
stop();
|
||||
throw t;
|
||||
}
|
||||
|
@ -93,8 +93,7 @@ public class UserThread {
|
||||
return timerClass.getDeclaredConstructor().newInstance();
|
||||
} catch (InstantiationException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
String message = "Could not instantiate timer bsTimerClass=" + timerClass;
|
||||
log.error(message);
|
||||
e.printStackTrace();
|
||||
log.error(message, e);
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
}
|
||||
|
@ -38,4 +38,3 @@ public class CryptoUtils {
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,7 @@
|
||||
package bisq.common.crypto;
|
||||
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import bisq.common.util.Hex;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
@ -70,8 +69,7 @@ public class Encryption {
|
||||
log.trace("Generate msgEncryptionKeyPair needed {} ms", System.currentTimeMillis() - ts);
|
||||
return keyPair;
|
||||
} catch (Throwable e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
log.error("Could not create key.", e);
|
||||
throw new RuntimeException("Could not create key.");
|
||||
}
|
||||
}
|
||||
@ -87,7 +85,7 @@ public class Encryption {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
return cipher.doFinal(payload);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
log.error("error in encrypt", e);
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
@ -128,8 +126,7 @@ public class Encryption {
|
||||
outputStream.flush();
|
||||
payloadWithHmac = outputStream.toByteArray().clone();
|
||||
} catch (IOException | NoSuchProviderException e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
log.error("Could not create hmac", e);
|
||||
throw new RuntimeException("Could not create hmac");
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
@ -140,8 +137,7 @@ public class Encryption {
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
log.error("Could not create hmac", e);
|
||||
throw new RuntimeException("Could not create hmac");
|
||||
}
|
||||
return payloadWithHmac;
|
||||
@ -153,8 +149,7 @@ public class Encryption {
|
||||
byte[] hmacTest = getHmac(message, secretKey);
|
||||
return Arrays.equals(hmacTest, hmac);
|
||||
} catch (Throwable e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
log.error("Could not create cipher", e);
|
||||
throw new RuntimeException("Could not create cipher");
|
||||
}
|
||||
}
|
||||
@ -177,7 +172,7 @@ public class Encryption {
|
||||
|
||||
public static byte[] decryptPayloadWithHmac(byte[] encryptedPayloadWithHmac, SecretKey secretKey) throws CryptoException {
|
||||
byte[] payloadWithHmac = decrypt(encryptedPayloadWithHmac, secretKey);
|
||||
String payloadWithHmacAsHex = Hex.toHexString(payloadWithHmac);
|
||||
String payloadWithHmacAsHex = Hex.encode(payloadWithHmac);
|
||||
// first part is raw message
|
||||
int length = payloadWithHmacAsHex.length();
|
||||
int sep = length - 64;
|
||||
@ -204,7 +199,7 @@ public class Encryption {
|
||||
cipher.init(Cipher.WRAP_MODE, publicKey, oaepParameterSpec);
|
||||
return cipher.wrap(secretKey);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
log.error("Couldn't encrypt payload", e);
|
||||
throw new CryptoException("Couldn't encrypt payload");
|
||||
}
|
||||
}
|
||||
@ -233,8 +228,7 @@ public class Encryption {
|
||||
keyPairGenerator.init(bits);
|
||||
return keyPairGenerator.generateKey();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
log.error("Couldn't generate key", e);
|
||||
throw new RuntimeException("Couldn't generate key");
|
||||
}
|
||||
}
|
||||
@ -252,7 +246,6 @@ public class Encryption {
|
||||
return KeyFactory.getInstance(Encryption.ASYM_KEY_ALGO).generatePublic(new X509EncodedKeySpec(encryptionPubKeyBytes));
|
||||
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||
log.error("Error creating sigPublicKey from bytes. sigPublicKeyBytes as hex={}, error={}", Utilities.bytesAsHexString(encryptionPubKeyBytes), e);
|
||||
e.printStackTrace();
|
||||
throw new KeyConversionException(e);
|
||||
}
|
||||
}
|
||||
|
@ -43,8 +43,7 @@ public class Hash {
|
||||
digest.update(data, 0, data.length);
|
||||
return digest.digest();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
log.error("Could not create MessageDigest for hash. " + e.toString());
|
||||
e.printStackTrace();
|
||||
log.error("Could not create MessageDigest for hash. ", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
@ -20,18 +20,12 @@ package bisq.common.crypto;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
|
||||
import java.security.KeyPair;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@Slf4j
|
||||
@ -41,33 +35,18 @@ public final class KeyRing {
|
||||
private final KeyPair encryptionKeyPair;
|
||||
private final PubKeyRing pubKeyRing;
|
||||
|
||||
// We generate by default a PGP keypair but the user can set his own if he prefers.
|
||||
// Not impl. yet but prepared in data structure
|
||||
@Nullable
|
||||
@Setter
|
||||
// TODO remove Nullable once impl.
|
||||
private PGPKeyPair pgpKeyPair;
|
||||
|
||||
@Inject
|
||||
public KeyRing(KeyStorage keyStorage) {
|
||||
if (keyStorage.allKeyFilesExist()) {
|
||||
signatureKeyPair = keyStorage.loadKeyPair(KeyStorage.KeyEntry.MSG_SIGNATURE);
|
||||
encryptionKeyPair = keyStorage.loadKeyPair(KeyStorage.KeyEntry.MSG_ENCRYPTION);
|
||||
|
||||
// TODO not impl
|
||||
pgpKeyPair = keyStorage.loadPgpKeyPair(KeyStorage.KeyEntry.PGP);
|
||||
} else {
|
||||
// First time we create key pairs
|
||||
signatureKeyPair = Sig.generateKeyPair();
|
||||
encryptionKeyPair = Encryption.generateKeyPair();
|
||||
|
||||
// TODO not impl
|
||||
pgpKeyPair = PGP.generateKeyPair();
|
||||
keyStorage.saveKeyRing(this);
|
||||
}
|
||||
// TODO remove Nullable once impl.
|
||||
final PGPPublicKey pgpPublicKey = pgpKeyPair != null ? pgpKeyPair.getPublicKey() : null;
|
||||
pubKeyRing = new PubKeyRing(signatureKeyPair.getPublic(), encryptionKeyPair.getPublic(), pgpPublicKey);
|
||||
pubKeyRing = new PubKeyRing(signatureKeyPair.getPublic(), encryptionKeyPair.getPublic());
|
||||
}
|
||||
|
||||
// Don't print keys for security reasons
|
||||
|
@ -24,8 +24,6 @@ import com.google.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@ -54,8 +52,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
// TODO: use a password protection for key storage
|
||||
@Singleton
|
||||
public class KeyStorage {
|
||||
@ -65,9 +61,7 @@ public class KeyStorage {
|
||||
|
||||
public enum KeyEntry {
|
||||
MSG_SIGNATURE("sig", Sig.KEY_ALGO),
|
||||
MSG_ENCRYPTION("enc", Encryption.ASYM_KEY_ALGO),
|
||||
// TODO not impl
|
||||
PGP("pgp", null);
|
||||
MSG_ENCRYPTION("enc", Encryption.ASYM_KEY_ALGO);
|
||||
|
||||
private final String fileName;
|
||||
private final String algorithm;
|
||||
@ -111,14 +105,6 @@ public class KeyStorage {
|
||||
return new File(storageDir + "/" + keyEntry.getFileName() + ".key").exists();
|
||||
}
|
||||
|
||||
// TODO not impl
|
||||
@SuppressWarnings({"SameParameterValue", "SameReturnValue", "UnusedParameters"})
|
||||
@Nullable
|
||||
public PGPKeyPair loadPgpKeyPair(KeyEntry keyEntry) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public KeyPair loadKeyPair(KeyEntry keyEntry) {
|
||||
FileUtil.rollingBackup(storageDir, keyEntry.getFileName() + ".key", 20);
|
||||
// long now = System.currentTimeMillis();
|
||||
@ -136,8 +122,7 @@ public class KeyStorage {
|
||||
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
|
||||
privateKey = keyFactory.generatePrivate(privateKeySpec);
|
||||
} catch (InvalidKeySpecException | IOException e) {
|
||||
log.error(e.getMessage());
|
||||
e.printStackTrace();
|
||||
log.error("Could not load key " + keyEntry.toString(), e.getMessage());
|
||||
throw new RuntimeException("Could not load key " + keyEntry.toString(), e);
|
||||
}
|
||||
|
||||
@ -161,8 +146,7 @@ public class KeyStorage {
|
||||
log.debug("load completed in {} msec", System.currentTimeMillis() - new Date().getTime());
|
||||
return new KeyPair(publicKey, privateKey);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
log.error("Could not load key " + keyEntry.toString(), e);
|
||||
throw new RuntimeException("Could not load key " + keyEntry.toString(), e);
|
||||
}
|
||||
}
|
||||
@ -181,8 +165,7 @@ public class KeyStorage {
|
||||
try (FileOutputStream fos = new FileOutputStream(storageDir + "/" + name + ".key")) {
|
||||
fos.write(pkcs8EncodedKeySpec.getEncoded());
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
log.error("Could not save key " + name, e);
|
||||
throw new RuntimeException("Could not save key " + name, e);
|
||||
}
|
||||
}
|
||||
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
* 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.common.crypto;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
import org.bouncycastle.bcpg.BCPGKey;
|
||||
import org.bouncycastle.bcpg.RSAPublicBCPGKey;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPUtil;
|
||||
import org.bouncycastle.openpgp.jcajce.JcaPGPPublicKeyRingCollection;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@SuppressWarnings("UnusedAssignment")
|
||||
@Slf4j
|
||||
public class PGP {
|
||||
|
||||
// TODO not tested yet, remove Nullable once impl.
|
||||
// PEM encoding
|
||||
@Nullable
|
||||
public static PGPPublicKey getPubKeyFromPem(@Nullable String pem) {
|
||||
if (pem != null) {
|
||||
InputStream inputStream = new ByteArrayInputStream(pem.getBytes(Charsets.UTF_8));
|
||||
try {
|
||||
inputStream = PGPUtil.getDecoderStream(inputStream);
|
||||
try {
|
||||
JcaPGPPublicKeyRingCollection ringCollection = new JcaPGPPublicKeyRingCollection(inputStream);
|
||||
Iterator<PGPPublicKeyRing> keyRingsIterator = ringCollection.getKeyRings();
|
||||
while (keyRingsIterator.hasNext()) {
|
||||
PGPPublicKeyRing pgpPublicKeyRing = keyRingsIterator.next();
|
||||
Iterator<PGPPublicKey> pubKeysIterator = pgpPublicKeyRing.getPublicKeys();
|
||||
while (pubKeysIterator.hasNext()) {
|
||||
final PGPPublicKey pgpPublicKey = pubKeysIterator.next();
|
||||
if ((pgpPublicKey).isEncryptionKey()) {
|
||||
log.debug(pgpPublicKey.getClass().getName()
|
||||
+ " KeyID: " + Long.toHexString(pgpPublicKey.getKeyID())
|
||||
+ " type: " + pgpPublicKey.getAlgorithm()
|
||||
+ " fingerprint: " + new String(Hex.encode(pgpPublicKey.getFingerprint())));
|
||||
|
||||
BCPGKey bcKey = pgpPublicKey.getPublicKeyPacket().getKey();
|
||||
log.debug(bcKey.getClass().getName());
|
||||
if (bcKey instanceof RSAPublicBCPGKey) {
|
||||
RSAPublicBCPGKey bcRSA = (RSAPublicBCPGKey) bcKey;
|
||||
RSAPublicKeySpec specRSA = new RSAPublicKeySpec(bcRSA.getModulus(), bcRSA.getPublicExponent());
|
||||
PublicKey jceKey = KeyFactory.getInstance("RSA").generatePublic(specRSA);
|
||||
// if you want to use the key in JCE, use jceKey
|
||||
// if you want to write "X.509" (SPKI) DER format to a file:
|
||||
//Files.write(new File(pubKeyAsString).toPath(), jceKey.getEncoded());
|
||||
// if you want to write in PEM, bouncycastle can do that
|
||||
// or you can just do base64 and add BEGIN/END lines
|
||||
// return pubKeyAsString; // assume only one key; if need to handle multiple keys
|
||||
// or select other than the first, specify more clearly
|
||||
}
|
||||
|
||||
return pgpPublicKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (PGPException | InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||
log.error("Error creating publicKey from pem. pem={}, error={}", pem, e);
|
||||
e.printStackTrace();
|
||||
throw new KeyConversionException(e);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("Error creating publicKey from pem. pem={}, error={}", pem, e);
|
||||
e.printStackTrace();
|
||||
throw new KeyConversionException(e);
|
||||
} finally {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("Error creating publicKey from pem. pem=null");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO not impl, remove Nullable once impl.
|
||||
// PEM encoding
|
||||
@SuppressWarnings({"SameReturnValue", "UnusedParameters"})
|
||||
@NotNull
|
||||
public static String getPEMFromPubKey(@Nullable PGPPublicKey pgpPubKey) {
|
||||
// We use empty string as we must not have null in proto file
|
||||
return "";
|
||||
}
|
||||
|
||||
// TODO not impl, remove Nullable once impl.
|
||||
@SuppressWarnings("SameReturnValue")
|
||||
@Nullable
|
||||
public static PGPKeyPair generateKeyPair() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -25,16 +25,12 @@ import com.google.protobuf.ByteString;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Same as KeyRing but with public keys only.
|
||||
* Used to send public keys over the wire to other peer.
|
||||
@ -45,22 +41,15 @@ import javax.annotation.Nullable;
|
||||
public final class PubKeyRing implements NetworkPayload, UsedForTradeContractJson {
|
||||
private final byte[] signaturePubKeyBytes;
|
||||
private final byte[] encryptionPubKeyBytes;
|
||||
@Nullable
|
||||
private final String pgpPubKeyAsPem;
|
||||
|
||||
private transient PublicKey signaturePubKey;
|
||||
private transient PublicKey encryptionPubKey;
|
||||
@Nullable
|
||||
private transient PGPPublicKey pgpPubKey;
|
||||
|
||||
public PubKeyRing(PublicKey signaturePubKey, PublicKey encryptionPubKey, @Nullable PGPPublicKey pgpPubKey) {
|
||||
public PubKeyRing(PublicKey signaturePubKey, PublicKey encryptionPubKey) {
|
||||
this.signaturePubKeyBytes = Sig.getPublicKeyBytes(signaturePubKey);
|
||||
this.encryptionPubKeyBytes = Encryption.getPublicKeyBytes(encryptionPubKey);
|
||||
this.pgpPubKeyAsPem = PGP.getPEMFromPubKey(pgpPubKey);
|
||||
|
||||
this.signaturePubKey = signaturePubKey;
|
||||
this.encryptionPubKey = encryptionPubKey;
|
||||
this.pgpPubKey = pgpPubKey;
|
||||
}
|
||||
|
||||
|
||||
@ -69,15 +58,11 @@ public final class PubKeyRing implements NetworkPayload, UsedForTradeContractJso
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@VisibleForTesting
|
||||
public PubKeyRing(byte[] signaturePubKeyBytes, byte[] encryptionPubKeyBytes, @Nullable String pgpPubKeyAsPem) {
|
||||
public PubKeyRing(byte[] signaturePubKeyBytes, byte[] encryptionPubKeyBytes) {
|
||||
this.signaturePubKeyBytes = signaturePubKeyBytes;
|
||||
this.encryptionPubKeyBytes = encryptionPubKeyBytes;
|
||||
this.pgpPubKeyAsPem = pgpPubKeyAsPem;
|
||||
|
||||
signaturePubKey = Sig.getPublicKeyFromBytes(signaturePubKeyBytes);
|
||||
encryptionPubKey = Encryption.getPublicKeyFromBytes(encryptionPubKeyBytes);
|
||||
if (pgpPubKeyAsPem != null)
|
||||
pgpPubKey = PGP.getPubKeyFromPem(pgpPubKeyAsPem);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,14 +70,13 @@ public final class PubKeyRing implements NetworkPayload, UsedForTradeContractJso
|
||||
return protobuf.PubKeyRing.newBuilder()
|
||||
.setSignaturePubKeyBytes(ByteString.copyFrom(signaturePubKeyBytes))
|
||||
.setEncryptionPubKeyBytes(ByteString.copyFrom(encryptionPubKeyBytes))
|
||||
.setPgpPubKeyAsPem(pgpPubKeyAsPem)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static PubKeyRing fromProto(protobuf.PubKeyRing proto) {
|
||||
return new PubKeyRing(proto.getSignaturePubKeyBytes().toByteArray(),
|
||||
proto.getEncryptionPubKeyBytes().toByteArray(),
|
||||
proto.getPgpPubKeyAsPem());
|
||||
return new PubKeyRing(
|
||||
proto.getSignaturePubKeyBytes().toByteArray(),
|
||||
proto.getEncryptionPubKeyBytes().toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,7 +84,6 @@ public final class PubKeyRing implements NetworkPayload, UsedForTradeContractJso
|
||||
return "PubKeyRing{" +
|
||||
"signaturePubKeyHex=" + Utilities.bytesAsHexString(signaturePubKeyBytes) +
|
||||
", encryptionPubKeyHex=" + Utilities.bytesAsHexString(encryptionPubKeyBytes) +
|
||||
", pgpPubKeyAsString=" + pgpPubKeyAsPem +
|
||||
'}';
|
||||
"}";
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,10 @@
|
||||
package bisq.common.crypto;
|
||||
|
||||
import bisq.common.util.Utilities;
|
||||
import bisq.common.util.Base64;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
@ -65,8 +64,7 @@ public class Sig {
|
||||
log.trace("Generate msgSignatureKeyPair needed {} ms", System.currentTimeMillis() - ts);
|
||||
return keyPair;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.toString());
|
||||
log.error("Could not create key.", e);
|
||||
throw new RuntimeException("Could not create key.");
|
||||
}
|
||||
}
|
||||
@ -95,7 +93,7 @@ public class Sig {
|
||||
*/
|
||||
public static String sign(PrivateKey privateKey, String message) throws CryptoException {
|
||||
byte[] sigAsBytes = sign(privateKey, message.getBytes(Charsets.UTF_8));
|
||||
return Base64.toBase64String(sigAsBytes);
|
||||
return Base64.encode(sigAsBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,4 +141,3 @@ public class Sig {
|
||||
return new X509EncodedKeySpec(sigPublicKey.getEncoded()).getEncoded();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,14 +20,9 @@ package bisq.common.storage;
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
@ -102,15 +97,4 @@ public class JsonFileManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Object readJsonFromDisc(String fileName) {
|
||||
final File jsonFile = new File(Paths.get(dir.getAbsolutePath(), fileName + ".json").toString());
|
||||
JSONParser parser = new JSONParser();
|
||||
try {
|
||||
return parser.parse(new FileReader(jsonFile));
|
||||
} catch (ParseException | IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
33
common/src/main/java/bisq/common/util/Base64.java
Normal file
33
common/src/main/java/bisq/common/util/Base64.java
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.common.util;
|
||||
|
||||
/**
|
||||
* We use Java 8 builtin Base64 because it is much faster than Guava and Apache versions:
|
||||
* http://java-performance.info/base64-encoding-and-decoding-performance/
|
||||
*/
|
||||
public class Base64 {
|
||||
|
||||
public static byte[] decode(String base64) {
|
||||
return java.util.Base64.getDecoder().decode(base64);
|
||||
}
|
||||
|
||||
public static String encode(byte[] bytes) {
|
||||
return java.util.Base64.getEncoder().encodeToString(bytes);
|
||||
}
|
||||
}
|
31
common/src/main/java/bisq/common/util/Hex.java
Normal file
31
common/src/main/java/bisq/common/util/Hex.java
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.common.util;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
|
||||
public class Hex {
|
||||
|
||||
public static byte[] decode(String hex) {
|
||||
return BaseEncoding.base16().lowerCase().decode(hex.toLowerCase());
|
||||
}
|
||||
|
||||
public static String encode(byte[] bytes) {
|
||||
return BaseEncoding.base16().lowerCase().encode(bytes);
|
||||
}
|
||||
}
|
@ -431,7 +431,7 @@ message Peer {
|
||||
message PubKeyRing {
|
||||
bytes signature_pub_key_bytes = 1;
|
||||
bytes encryption_pub_key_bytes = 2;
|
||||
string pgp_pub_key_as_pem = 3;
|
||||
reserved 3; // WAS: string pgp_pub_key_as_pem = 3;
|
||||
}
|
||||
|
||||
message SealedAndSigned {
|
||||
|
@ -70,9 +70,7 @@ public class AvoidStandbyModeService {
|
||||
private void start() {
|
||||
isStopped = false;
|
||||
log.info("AvoidStandbyModeService started");
|
||||
Thread thread = new Thread(this::play);
|
||||
thread.setName("AvoidStandbyModeService-thread");
|
||||
thread.start();
|
||||
new Thread(this::play, "AvoidStandbyModeService-thread").start();
|
||||
}
|
||||
|
||||
|
||||
|
@ -446,11 +446,8 @@ public class BisqSetup {
|
||||
bisqEnvironment.getIgnoreLocalBtcNode()) {
|
||||
step3();
|
||||
} else {
|
||||
Thread checkIfLocalHostNodeIsRunningThread = new Thread(() -> {
|
||||
Thread.currentThread().setName("checkIfLocalHostNodeIsRunningThread");
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = new Socket();
|
||||
new Thread(() -> {
|
||||
try (Socket socket = new Socket()) {
|
||||
socket.connect(new InetSocketAddress(InetAddresses.forString("127.0.0.1"),
|
||||
BisqEnvironment.getBaseCurrencyNetwork().getParameters().getPort()), 5000);
|
||||
log.info("Localhost Bitcoin node detected.");
|
||||
@ -460,16 +457,8 @@ public class BisqSetup {
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
UserThread.execute(BisqSetup.this::step3);
|
||||
} finally {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
checkIfLocalHostNodeIsRunningThread.start();
|
||||
}, "checkIfLocalHostNodeIsRunningThread").start();
|
||||
}
|
||||
}
|
||||
|
||||
@ -486,9 +475,8 @@ public class BisqSetup {
|
||||
// If users compile themselves they might miss that step and then would get an exception in the trade.
|
||||
// To avoid that we add here at startup a sample encryption and signing to see if it don't causes an exception.
|
||||
// See: https://github.com/bisq-network/exchange/blob/master/doc/build.md#7-enable-unlimited-strength-for-cryptographic-keys
|
||||
Thread checkCryptoThread = new Thread(() -> {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.currentThread().setName("checkCryptoThread");
|
||||
// just use any simple dummy msg
|
||||
Ping payload = new Ping(1, 1);
|
||||
SealedAndSigned sealedAndSigned = EncryptionService.encryptHybridWithSignature(payload,
|
||||
@ -508,8 +496,7 @@ public class BisqSetup {
|
||||
if (cryptoSetupFailedHandler != null)
|
||||
cryptoSetupFailedHandler.accept(msg);
|
||||
}
|
||||
});
|
||||
checkCryptoThread.start();
|
||||
}, "checkCryptoThread").start();
|
||||
}
|
||||
|
||||
private void startP2pNetworkAndWallet() {
|
||||
|
@ -49,11 +49,8 @@ public class SetupUtils {
|
||||
// If users compile themselves they might miss that step and then would get an exception in the trade.
|
||||
// To avoid that we add here at startup a sample encryption and signing to see if it don't causes an exception.
|
||||
// See: https://github.com/bisq-network/exchange/blob/master/doc/build.md#7-enable-unlimited-strength-for-cryptographic-keys
|
||||
Thread checkCryptoThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
Thread checkCryptoThread = new Thread(() -> {
|
||||
try {
|
||||
Thread.currentThread().setName("checkCryptoThread");
|
||||
// just use any simple dummy msg
|
||||
Ping payload = new Ping(1, 1);
|
||||
SealedAndSigned sealedAndSigned = EncryptionService.encryptHybridWithSignature(payload,
|
||||
@ -74,15 +71,13 @@ public class SetupUtils {
|
||||
e.printStackTrace();
|
||||
errorHandler.accept(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}, "checkCryptoThread");
|
||||
checkCryptoThread.start();
|
||||
}
|
||||
|
||||
public static BooleanProperty readFromResources(P2PDataStorage p2PDataStorage) {
|
||||
BooleanProperty result = new SimpleBooleanProperty();
|
||||
Thread thread = new Thread(() -> {
|
||||
Thread.currentThread().setName("readFromResourcesThread");
|
||||
new Thread(() -> {
|
||||
// Used to load different files per base currency (EntryMap_BTC_MAINNET, EntryMap_LTC,...)
|
||||
final BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
|
||||
final String postFix = "_" + baseCurrencyNetwork.name();
|
||||
@ -90,8 +85,7 @@ public class SetupUtils {
|
||||
p2PDataStorage.readFromResources(postFix);
|
||||
log.info("readFromResources took {} ms", (new Date().getTime() - ts));
|
||||
UserThread.execute(() -> result.set(true));
|
||||
});
|
||||
thread.start();
|
||||
}, "readFromResourcesThread").start();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ public class WalletAppSetup {
|
||||
result = Res.get("mainView.footer.btcInfo",
|
||||
peers,
|
||||
Res.get("mainView.footer.btcInfo.synchronizingWith"),
|
||||
getBtcNetworkAsString() + ": " + formatter.formatToPercentWithSymbol(percentage));
|
||||
getBtcNetworkAsString() + ": " + BSFormatter.formatToPercentWithSymbol(percentage));
|
||||
} else {
|
||||
result = Res.get("mainView.footer.btcInfo",
|
||||
peers,
|
||||
|
@ -561,13 +561,12 @@ public class WalletConfig extends AbstractIdleService {
|
||||
|
||||
private void installShutdownHook() {
|
||||
if (autoStop) Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
Thread.currentThread().setName("ShutdownHook");
|
||||
try {
|
||||
WalletConfig.this.stopAsync();
|
||||
WalletConfig.this.awaitTerminated();
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
}));
|
||||
}, "WalletConfig ShutdownHook"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -180,9 +180,9 @@ public class TradeWalletService {
|
||||
boolean doBroadcast,
|
||||
@Nullable TxBroadcaster.Callback callback)
|
||||
throws InsufficientMoneyException, AddressFormatException {
|
||||
log.debug("fundingAddress {}", fundingAddress.toString());
|
||||
log.debug("reservedForTradeAddress {}", reservedForTradeAddress.toString());
|
||||
log.debug("changeAddress {}", changeAddress.toString());
|
||||
log.debug("fundingAddress {}", fundingAddress);
|
||||
log.debug("reservedForTradeAddress {}", reservedForTradeAddress);
|
||||
log.debug("changeAddress {}", changeAddress);
|
||||
log.info("reservedFundsForOffer {}", reservedFundsForOffer.toPlainString());
|
||||
log.debug("useSavingsWallet {}", useSavingsWallet);
|
||||
log.info("tradingFee {}", tradingFee.toPlainString());
|
||||
@ -245,9 +245,9 @@ public class TradeWalletService {
|
||||
TransactionVerificationException, WalletException,
|
||||
InsufficientMoneyException, AddressFormatException {
|
||||
|
||||
log.debug("preparedBsqTx {}", preparedBsqTx.toString());
|
||||
log.debug("fundingAddress {}", fundingAddress.toString());
|
||||
log.debug("changeAddress {}", changeAddress.toString());
|
||||
log.debug("preparedBsqTx {}", preparedBsqTx);
|
||||
log.debug("fundingAddress {}", fundingAddress);
|
||||
log.debug("changeAddress {}", changeAddress);
|
||||
log.debug("reservedFundsForOffer {}", reservedFundsForOffer.toPlainString());
|
||||
log.debug("useSavingsWallet {}", useSavingsWallet);
|
||||
log.debug("txFee {}", txFee.toPlainString());
|
||||
@ -346,10 +346,12 @@ public class TradeWalletService {
|
||||
Coin txFee,
|
||||
Address takersAddress) throws
|
||||
TransactionVerificationException {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("takerCreatesDepositsTxInputs called");
|
||||
log.debug("inputAmount {}", inputAmount.toFriendlyString());
|
||||
log.debug("txFee {}", txFee.toFriendlyString());
|
||||
log.debug("takersAddress {}", takersAddress.toString());
|
||||
}
|
||||
|
||||
// We add the mining fee 2 times to the deposit tx:
|
||||
// 1. Will be spent when publishing the deposit tx (paid by buyer)
|
||||
@ -448,9 +450,9 @@ public class TradeWalletService {
|
||||
log.debug("takerChangeAddressString {}", takerChangeAddressString);
|
||||
log.debug("makerAddress {}", makerAddress);
|
||||
log.debug("makerChangeAddress {}", makerChangeAddress);
|
||||
log.debug("buyerPubKey {}", ECKey.fromPublicOnly(buyerPubKey).toString());
|
||||
log.debug("sellerPubKey {}", ECKey.fromPublicOnly(sellerPubKey).toString());
|
||||
log.debug("arbitratorPubKey {}", ECKey.fromPublicOnly(arbitratorPubKey).toString());
|
||||
log.debug("buyerPubKey {}", ECKey.fromPublicOnly(buyerPubKey));
|
||||
log.debug("sellerPubKey {}", ECKey.fromPublicOnly(sellerPubKey));
|
||||
log.debug("arbitratorPubKey {}", ECKey.fromPublicOnly(arbitratorPubKey));
|
||||
|
||||
checkArgument(!takerRawTransactionInputs.isEmpty());
|
||||
|
||||
|
@ -40,8 +40,8 @@ public class DaoUtil {
|
||||
long now = new Date().getTime();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM", Locale.getDefault());
|
||||
SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm", Locale.getDefault());
|
||||
String startDateTime = formatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String endDateTime = formatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String startDateTime = BSFormatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String endDateTime = BSFormatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
|
||||
return Res.get("dao.cycle.phaseDurationWithoutBlocks", start, end, startDateTime, endDateTime);
|
||||
}
|
||||
@ -53,9 +53,9 @@ public class DaoUtil {
|
||||
long now = new Date().getTime();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM", Locale.getDefault());
|
||||
SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm", Locale.getDefault());
|
||||
String startDateTime = formatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String endDateTime = formatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String durationTime = formatter.formatDurationAsWords(duration * 10 * 60 * 1000, false, false);
|
||||
String startDateTime = BSFormatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String endDateTime = BSFormatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String durationTime = BSFormatter.formatDurationAsWords(duration * 10 * 60 * 1000, false, false);
|
||||
return Res.get("dao.cycle.phaseDuration", duration, durationTime, start, end, startDateTime, endDateTime);
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import bisq.core.dao.state.model.governance.Issuance;
|
||||
import bisq.core.dao.state.model.governance.IssuanceType;
|
||||
import bisq.core.dao.state.model.governance.ParamChange;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
@ -923,7 +924,7 @@ public class DaoStateService implements DaoSetupService {
|
||||
}
|
||||
|
||||
public double getParamValueAsPercentDouble(String paramValue) {
|
||||
return bsqFormatter.parsePercentStringToDouble(paramValue);
|
||||
return ParsingUtils.parsePercentStringToDouble(paramValue);
|
||||
}
|
||||
|
||||
public int getParamValueAsBlock(String paramValue) {
|
||||
|
@ -34,6 +34,7 @@ public class LanguageUtil {
|
||||
"el", // Greek
|
||||
"es", // Spanish
|
||||
"pt", // Portuguese
|
||||
"pt_BR", // Brazilian Portuguese
|
||||
"zh", // Chinese
|
||||
"ru", // Russian
|
||||
"fr", // French
|
||||
@ -118,6 +119,8 @@ public class LanguageUtil {
|
||||
// Serbia
|
||||
// shows it in russian by default
|
||||
return "Srpski";
|
||||
} else if (locale.getLanguage().equals("pt_br")) {
|
||||
return "português (Brasil)";
|
||||
} else {
|
||||
return locale.getDisplayName(locale);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
package bisq.core.monetary;
|
||||
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import org.bitcoinj.core.Monetary;
|
||||
import org.bitcoinj.utils.MonetaryFormat;
|
||||
@ -89,7 +89,7 @@ public final class Altcoin implements Monetary, Comparable<Altcoin> {
|
||||
* @throws IllegalArgumentException if you try to specify fractional satoshis, or a value out of range.
|
||||
*/
|
||||
public static Altcoin parseAltcoin(final String currencyCode, String input) {
|
||||
String cleaned = BSFormatter.convertCharsForNumber(input);
|
||||
String cleaned = ParsingUtils.convertCharsForNumber(input);
|
||||
try {
|
||||
long val = new BigDecimal(cleaned).movePointRight(SMALLEST_UNIT_EXPONENT)
|
||||
.toBigIntegerExact().longValue();
|
||||
|
@ -18,7 +18,7 @@
|
||||
package bisq.core.monetary;
|
||||
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Monetary;
|
||||
@ -58,7 +58,7 @@ public class Price extends MonetaryWrapper implements Comparable<Price> {
|
||||
* @return The parsed Price.
|
||||
*/
|
||||
public static Price parse(String currencyCode, String input) {
|
||||
String cleaned = BSFormatter.convertCharsForNumber(input);
|
||||
String cleaned = ParsingUtils.convertCharsForNumber(input);
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
||||
return new Price(Fiat.parseFiat(currencyCode, cleaned));
|
||||
else
|
||||
|
@ -18,7 +18,7 @@
|
||||
package bisq.core.monetary;
|
||||
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import org.bitcoinj.core.Monetary;
|
||||
import org.bitcoinj.utils.Fiat;
|
||||
@ -36,7 +36,7 @@ public class Volume extends MonetaryWrapper implements Comparable<Volume> {
|
||||
}
|
||||
|
||||
public static Volume parse(String input, String currencyCode) {
|
||||
String cleaned = BSFormatter.convertCharsForNumber(input);
|
||||
String cleaned = ParsingUtils.convertCharsForNumber(input);
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
||||
return new Volume(Fiat.parseFiat(currencyCode, cleaned));
|
||||
else
|
||||
|
@ -180,9 +180,9 @@ public class MarketAlerts {
|
||||
ratio = Math.abs(ratio);
|
||||
String msg = Res.get("account.notifications.marketAlert.message.msg",
|
||||
direction,
|
||||
formatter.getCurrencyPair(currencyCode),
|
||||
formatter.formatPrice(offerPrice),
|
||||
formatter.formatToPercentWithSymbol(ratio / 10000d),
|
||||
BSFormatter.getCurrencyPair(currencyCode),
|
||||
BSFormatter.formatPrice(offerPrice),
|
||||
BSFormatter.formatToPercentWithSymbol(ratio / 10000d),
|
||||
marketDir,
|
||||
Res.get(offer.getPaymentMethod().getId()),
|
||||
shortOfferId);
|
||||
|
@ -70,8 +70,8 @@ public class PriceAlert {
|
||||
if (priceAsLong > filter.getHigh() || priceAsLong < filter.getLow()) {
|
||||
String msg = Res.get("account.notifications.priceAlert.message.msg",
|
||||
currencyName,
|
||||
formatter.formatMarketPrice(priceAsDouble, currencyCode),
|
||||
formatter.getCurrencyPair(currencyCode));
|
||||
BSFormatter.formatMarketPrice(priceAsDouble, currencyCode),
|
||||
BSFormatter.getCurrencyPair(currencyCode));
|
||||
MobileMessage message = new MobileMessage(Res.get("account.notifications.priceAlert.message.title", currencyName),
|
||||
msg,
|
||||
MobileMessageType.PRICE);
|
||||
|
@ -322,19 +322,6 @@ public class OfferUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFeeWithFiatAmount(Coin makerFeeAsCoin,
|
||||
Optional<Volume> optionalFeeInFiat,
|
||||
BSFormatter formatter) {
|
||||
String fee = makerFeeAsCoin != null ? formatter.formatCoinWithCode(makerFeeAsCoin) : Res.get("shared.na");
|
||||
String feeInFiatAsString;
|
||||
if (optionalFeeInFiat != null && optionalFeeInFiat.isPresent()) {
|
||||
feeInFiatAsString = formatter.formatVolumeWithCode(optionalFeeInFiat.get());
|
||||
} else {
|
||||
feeInFiatAsString = Res.get("shared.na");
|
||||
}
|
||||
return Res.get("feeOptionWindow.fee", fee, feeInFiatAsString);
|
||||
}
|
||||
|
||||
|
||||
public static Map<String, String> getExtraDataMap(AccountAgeWitnessService accountAgeWitnessService,
|
||||
ReferralIdService referralIdService,
|
||||
|
@ -48,7 +48,7 @@ public class ApplyFilter extends TradeTask {
|
||||
|
||||
FilterManager filterManager = processModel.getFilterManager();
|
||||
if (nodeAddress != null && filterManager.isNodeAddressBanned(nodeAddress)) {
|
||||
failed("Other trader is banned by his node address.\n" +
|
||||
failed("Other trader is banned by their node address.\n" +
|
||||
"tradingPeerNodeAddress=" + nodeAddress);
|
||||
} else if (filterManager.isOfferIdBanned(trade.getId())) {
|
||||
failed("Offer ID is banned.\n" +
|
||||
@ -60,7 +60,7 @@ public class ApplyFilter extends TradeTask {
|
||||
failed("Payment method is banned.\n" +
|
||||
"Payment method=" + trade.getOffer().getPaymentMethod().getId());
|
||||
} else if (filterManager.isPeersPaymentAccountDataAreBanned(paymentAccountPayload, appliedPaymentAccountFilter)) {
|
||||
failed("Other trader is banned by his trading account data.\n" +
|
||||
failed("Other trader is banned by their trading account data.\n" +
|
||||
"paymentAccountPayload=" + paymentAccountPayload.getPaymentDetails() + "\n" +
|
||||
"banFilter=" + appliedPaymentAccountFilter[0].toString());
|
||||
} else if (filterManager.requireUpdateToNewVersionForTrading()) {
|
||||
|
@ -39,11 +39,13 @@ public class SellerVerifiesPeersAccountAge extends TradeTask {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
boolean isTradeRisky = OfferRestrictions.isTradeRisky(trade);
|
||||
boolean isTradePeersAccountAgeImmature = AccountAgeRestrictions.isTradePeersAccountAgeImmature(
|
||||
processModel.getAccountAgeWitnessService(), trade);
|
||||
log.debug("SellerVerifiesPeersAccountAge isOfferRisky={} isTradePeersAccountAgeImmature={}",
|
||||
OfferRestrictions.isTradeRisky(trade), AccountAgeRestrictions.isTradePeersAccountAgeImmature(
|
||||
processModel.getAccountAgeWitnessService(), trade));
|
||||
if (OfferRestrictions.isTradeRisky(trade) &&
|
||||
AccountAgeRestrictions.isTradePeersAccountAgeImmature(processModel.getAccountAgeWitnessService(), trade)) {
|
||||
isTradeRisky, isTradePeersAccountAgeImmature);
|
||||
if (isTradeRisky &&
|
||||
isTradePeersAccountAgeImmature) {
|
||||
failed("Violation of security restrictions:\n" +
|
||||
" - The peer's account was created after March 1st 2019\n" +
|
||||
" - The trade amount is above 0.01 BTC\n" +
|
||||
|
@ -20,12 +20,9 @@ package bisq.core.util;
|
||||
import bisq.core.app.BisqEnvironment;
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.locale.GlobalSettings;
|
||||
import bisq.core.locale.LanguageUtil;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.monetary.Altcoin;
|
||||
import bisq.core.monetary.Price;
|
||||
import bisq.core.monetary.Volume;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
@ -55,6 +52,7 @@ import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -64,27 +62,24 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class BSFormatter {
|
||||
public final static String RANGE_SEPARATOR = " - ";
|
||||
|
||||
protected boolean useMilliBit;
|
||||
protected int scale = 3;
|
||||
|
||||
// We don't support localized formatting. Format is always using "." as decimal mark and no grouping separator.
|
||||
// Input of "," as decimal mark (like in german locale) will be replaced with ".".
|
||||
// Input of a group separator (1,123,45) lead to an validation error.
|
||||
// Note: BtcFormat was intended to be used, but it lead to many problems (automatic format to mBit,
|
||||
// no way to remove grouping separator). It seems to be not optimal for user input formatting.
|
||||
protected MonetaryFormat coinFormat;
|
||||
@Getter
|
||||
protected MonetaryFormat monetaryFormat;
|
||||
|
||||
// protected String currencyCode = CurrencyUtil.getDefaultFiatCurrencyAsCode();
|
||||
|
||||
protected final MonetaryFormat fiatPriceFormat = new MonetaryFormat().shift(0).minDecimals(4).repeatOptionalDecimals(0, 0);
|
||||
protected final MonetaryFormat fiatVolumeFormat = new MonetaryFormat().shift(0).minDecimals(2).repeatOptionalDecimals(0, 0);
|
||||
protected final MonetaryFormat altcoinFormat = new MonetaryFormat().shift(0).minDecimals(8).repeatOptionalDecimals(0, 0);
|
||||
protected final DecimalFormat decimalFormat = new DecimalFormat("#.#");
|
||||
public static final MonetaryFormat fiatPriceFormat = new MonetaryFormat().shift(0).minDecimals(4).repeatOptionalDecimals(0, 0);
|
||||
protected static final MonetaryFormat altcoinFormat = new MonetaryFormat().shift(0).minDecimals(8).repeatOptionalDecimals(0, 0);
|
||||
protected static final DecimalFormat decimalFormat = new DecimalFormat("#.#");
|
||||
|
||||
|
||||
@Inject
|
||||
public BSFormatter() {
|
||||
coinFormat = BisqEnvironment.getParameters().getMonetaryFormat();
|
||||
monetaryFormat = BisqEnvironment.getParameters().getMonetaryFormat();
|
||||
}
|
||||
|
||||
|
||||
@ -106,10 +101,14 @@ public class BSFormatter {
|
||||
}
|
||||
|
||||
public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits) {
|
||||
return formatCoin(coin, decimalPlaces, decimalAligned, maxNumberOfDigits, coinFormat);
|
||||
return formatCoin(coin, decimalPlaces, decimalAligned, maxNumberOfDigits, monetaryFormat);
|
||||
}
|
||||
|
||||
public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits, MonetaryFormat coinFormat) {
|
||||
public static String formatCoin(Coin coin,
|
||||
int decimalPlaces,
|
||||
boolean decimalAligned,
|
||||
int maxNumberOfDigits,
|
||||
MonetaryFormat coinFormat) {
|
||||
String formattedCoin = "";
|
||||
|
||||
if (coin != null) {
|
||||
@ -132,18 +131,18 @@ public class BSFormatter {
|
||||
}
|
||||
|
||||
public String formatCoinWithCode(Coin coin) {
|
||||
return formatCoinWithCode(coin, coinFormat);
|
||||
return formatCoinWithCode(coin, monetaryFormat);
|
||||
}
|
||||
|
||||
public String formatCoinWithCode(long value) {
|
||||
return formatCoinWithCode(Coin.valueOf(value), monetaryFormat);
|
||||
}
|
||||
|
||||
public static String formatCoinWithCode(long value, MonetaryFormat coinFormat) {
|
||||
return formatCoinWithCode(Coin.valueOf(value), coinFormat);
|
||||
}
|
||||
|
||||
public String formatCoinWithCode(long value, MonetaryFormat coinFormat) {
|
||||
return formatCoinWithCode(Coin.valueOf(value), coinFormat);
|
||||
}
|
||||
|
||||
public String formatCoinWithCode(Coin coin, MonetaryFormat coinFormat) {
|
||||
public static String formatCoinWithCode(Coin coin, MonetaryFormat coinFormat) {
|
||||
if (coin != null) {
|
||||
try {
|
||||
// we don't use the code feature from coinFormat as it does automatic switching between mBTC and BTC and
|
||||
@ -158,62 +157,11 @@ public class BSFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
public Coin parseToCoin(String input) {
|
||||
return parseToCoin(input, coinFormat);
|
||||
}
|
||||
|
||||
public Coin parseToCoin(String input, MonetaryFormat coinFormat) {
|
||||
if (input != null && input.length() > 0) {
|
||||
try {
|
||||
return coinFormat.parse(cleanDoubleInput(input));
|
||||
} catch (Throwable t) {
|
||||
log.warn("Exception at parseToBtc: " + t.toString());
|
||||
return Coin.ZERO;
|
||||
}
|
||||
} else {
|
||||
return Coin.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to a coin with max. 4 decimal places. Last place gets rounded.
|
||||
* 0.01234 -> 0.0123
|
||||
* 0.01235 -> 0.0124
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public Coin parseToCoinWith4Decimals(String input) {
|
||||
try {
|
||||
return Coin.valueOf(new BigDecimal(parseToCoin(cleanDoubleInput(input)).value).setScale(-scale - 1,
|
||||
BigDecimal.ROUND_HALF_UP).setScale(scale + 1, BigDecimal.ROUND_HALF_UP).toBigInteger().longValue());
|
||||
} catch (Throwable t) {
|
||||
if (input != null && input.length() > 0)
|
||||
log.warn("Exception at parseToCoinWith4Decimals: " + t.toString());
|
||||
return Coin.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasBtcValidDecimals(String input) {
|
||||
return parseToCoin(input).equals(parseToCoinWith4Decimals(input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a coin with the properties defined in the format (used to reduce decimal places)
|
||||
*
|
||||
* @param coin The coin which should be transformed
|
||||
* @return The transformed coin
|
||||
*/
|
||||
public Coin reduceTo4Decimals(Coin coin) {
|
||||
return parseToCoin(formatCoin(coin));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FIAT
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String formatFiat(Fiat fiat, MonetaryFormat format, boolean appendCurrencyCode) {
|
||||
public static String formatFiat(Fiat fiat, MonetaryFormat format, boolean appendCurrencyCode) {
|
||||
if (fiat != null) {
|
||||
try {
|
||||
final String res = format.noCode().format(fiat).toString();
|
||||
@ -230,10 +178,10 @@ public class BSFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
protected Fiat parseToFiat(String input, String currencyCode) {
|
||||
private static Fiat parseToFiat(String input, String currencyCode) {
|
||||
if (input != null && input.length() > 0) {
|
||||
try {
|
||||
return Fiat.parseFiat(currencyCode, cleanDoubleInput(input));
|
||||
return Fiat.parseFiat(currencyCode, ParsingUtils.cleanDoubleInput(input));
|
||||
} catch (Exception e) {
|
||||
log.warn("Exception at parseToFiat: " + e.toString());
|
||||
return Fiat.valueOf(currencyCode, 0);
|
||||
@ -253,10 +201,10 @@ public class BSFormatter {
|
||||
* @return
|
||||
*/
|
||||
|
||||
public Fiat parseToFiatWithPrecision(String input, String currencyCode) {
|
||||
public static Fiat parseToFiatWithPrecision(String input, String currencyCode) {
|
||||
if (input != null && input.length() > 0) {
|
||||
try {
|
||||
return parseToFiat(new BigDecimal(cleanDoubleInput(input)).setScale(2, BigDecimal.ROUND_HALF_UP).toString(),
|
||||
return parseToFiat(new BigDecimal(ParsingUtils.cleanDoubleInput(input)).setScale(2, BigDecimal.ROUND_HALF_UP).toString(),
|
||||
currencyCode);
|
||||
} catch (Throwable t) {
|
||||
log.warn("Exception at parseToFiatWithPrecision: " + t.toString());
|
||||
@ -267,24 +215,12 @@ public class BSFormatter {
|
||||
return Fiat.valueOf(currencyCode, 0);
|
||||
}
|
||||
|
||||
public boolean isFiatAlteredWhenPrecisionApplied(String input, String currencyCode) {
|
||||
return parseToFiat(input, currencyCode).equals(parseToFiatWithPrecision(input, currencyCode));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Altcoin
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String formatAltcoin(Altcoin altcoin) {
|
||||
return formatAltcoin(altcoin, false);
|
||||
}
|
||||
|
||||
public String formatAltcoinWithCode(Altcoin altcoin) {
|
||||
return formatAltcoin(altcoin, true);
|
||||
}
|
||||
|
||||
public String formatAltcoin(Altcoin altcoin, boolean appendCurrencyCode) {
|
||||
private static String formatAltcoin(Altcoin altcoin, boolean appendCurrencyCode) {
|
||||
if (altcoin != null) {
|
||||
try {
|
||||
String res = altcoinFormat.noCode().format(altcoin).toString();
|
||||
@ -306,21 +242,8 @@ public class BSFormatter {
|
||||
// Volume
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String formatVolume(Offer offer, Boolean decimalAligned, int maxNumberOfDigits) {
|
||||
return formatVolume(offer, decimalAligned, maxNumberOfDigits, true);
|
||||
}
|
||||
|
||||
public String formatVolume(Offer offer, Boolean decimalAligned, int maxNumberOfDigits, boolean showRange) {
|
||||
String formattedVolume = offer.isRange() && showRange ? formatVolume(offer.getMinVolume()) + RANGE_SEPARATOR + formatVolume(offer.getVolume()) : formatVolume(offer.getVolume());
|
||||
|
||||
if (decimalAligned) {
|
||||
formattedVolume = fillUpPlacesWithEmptyStrings(formattedVolume, maxNumberOfDigits);
|
||||
}
|
||||
return formattedVolume;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String fillUpPlacesWithEmptyStrings(String formattedNumber, int maxNumberOfDigits) {
|
||||
public static String fillUpPlacesWithEmptyStrings(String formattedNumber, int maxNumberOfDigits) {
|
||||
//FIXME: temporary deactivate adding spaces in front of numbers as we don't use a monospace font right now.
|
||||
/*int numberOfPlacesToFill = maxNumberOfDigits - formattedNumber.length();
|
||||
for (int i = 0; i < numberOfPlacesToFill; i++) {
|
||||
@ -329,27 +252,7 @@ public class BSFormatter {
|
||||
return formattedNumber;
|
||||
}
|
||||
|
||||
public String formatVolume(Volume volume) {
|
||||
return formatVolume(volume, fiatVolumeFormat, false);
|
||||
}
|
||||
|
||||
public String formatVolumeWithCode(Volume volume) {
|
||||
return formatVolume(volume, fiatVolumeFormat, true);
|
||||
}
|
||||
|
||||
public String formatVolume(Volume volume, MonetaryFormat fiatVolumeFormat, boolean appendCurrencyCode) {
|
||||
if (volume != null) {
|
||||
Monetary monetary = volume.getMonetary();
|
||||
if (monetary instanceof Fiat)
|
||||
return formatFiat((Fiat) monetary, fiatVolumeFormat, appendCurrencyCode);
|
||||
else
|
||||
return formatAltcoinVolume((Altcoin) monetary, appendCurrencyCode);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String formatAltcoinVolume(Altcoin altcoin, boolean appendCurrencyCode) {
|
||||
public static String formatAltcoinVolume(Altcoin altcoin, boolean appendCurrencyCode) {
|
||||
if (altcoin != null) {
|
||||
try {
|
||||
// TODO quick hack...
|
||||
@ -371,47 +274,13 @@ public class BSFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
public String formatVolumeLabel(String currencyCode) {
|
||||
return formatVolumeLabel(currencyCode, "");
|
||||
}
|
||||
|
||||
public String formatVolumeLabel(String currencyCode, String postFix) {
|
||||
return Res.get("formatter.formatVolumeLabel",
|
||||
currencyCode, postFix);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Amount
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String formatAmount(Offer offer) {
|
||||
return formatAmount(offer, false);
|
||||
}
|
||||
|
||||
public String formatAmount(Offer offer, boolean decimalAligned) {
|
||||
String formattedAmount = offer.isRange() ? formatCoin(offer.getMinAmount()) + RANGE_SEPARATOR + formatCoin(offer.getAmount()) : formatCoin(offer.getAmount());
|
||||
if (decimalAligned) {
|
||||
formattedAmount = fillUpPlacesWithEmptyStrings(formattedAmount, 15);
|
||||
}
|
||||
return formattedAmount;
|
||||
}
|
||||
|
||||
public String formatAmount(Offer offer, int decimalPlaces, boolean decimalAligned, int maxPlaces) {
|
||||
String formattedAmount = offer.isRange() ? formatCoin(offer.getMinAmount(), decimalPlaces) + RANGE_SEPARATOR + formatCoin(offer.getAmount(), decimalPlaces) : formatCoin(offer.getAmount(), decimalPlaces);
|
||||
|
||||
if (decimalAligned) {
|
||||
formattedAmount = fillUpPlacesWithEmptyStrings(formattedAmount, maxPlaces);
|
||||
}
|
||||
return formattedAmount;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Price
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public String formatPrice(Price price, MonetaryFormat fiatPriceFormat, boolean appendCurrencyCode) {
|
||||
public static String formatPrice(Price price, MonetaryFormat fiatPriceFormat, boolean appendCurrencyCode) {
|
||||
if (price != null) {
|
||||
Monetary monetary = price.getMonetary();
|
||||
if (monetary instanceof Fiat)
|
||||
@ -423,35 +292,26 @@ public class BSFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
public String formatPrice(Price price, boolean appendCurrencyCode) {
|
||||
public static String formatPrice(Price price, boolean appendCurrencyCode) {
|
||||
return formatPrice(price, fiatPriceFormat, true);
|
||||
}
|
||||
|
||||
public String formatPrice(Price price) {
|
||||
public static String formatPrice(Price price) {
|
||||
return formatPrice(price, fiatPriceFormat, false);
|
||||
}
|
||||
|
||||
public String formatPrice(Price price, Boolean decimalAligned, int maxPlaces) {
|
||||
String formattedPrice = formatPrice(price);
|
||||
|
||||
if (decimalAligned) {
|
||||
formattedPrice = fillUpPlacesWithEmptyStrings(formattedPrice, maxPlaces);
|
||||
}
|
||||
return formattedPrice;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Market price
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String formatMarketPrice(double price, String currencyCode) {
|
||||
public static String formatMarketPrice(double price, String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
||||
return formatMarketPrice(price, 2);
|
||||
else
|
||||
return formatMarketPrice(price, 8);
|
||||
}
|
||||
|
||||
public String formatMarketPrice(double price, int precision) {
|
||||
public static String formatMarketPrice(double price, int precision) {
|
||||
return formatRoundedDoubleWithPrecision(price, precision);
|
||||
}
|
||||
|
||||
@ -460,40 +320,25 @@ public class BSFormatter {
|
||||
// Other
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String formatRoundedDoubleWithPrecision(double value, int precision) {
|
||||
public static String formatRoundedDoubleWithPrecision(double value, int precision) {
|
||||
decimalFormat.setMinimumFractionDigits(precision);
|
||||
decimalFormat.setMaximumFractionDigits(precision);
|
||||
return decimalFormat.format(MathUtils.roundDouble(value, precision)).replace(",", ".");
|
||||
}
|
||||
|
||||
public String getDirectionWithCode(OfferPayload.Direction direction, String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
||||
return (direction == OfferPayload.Direction.BUY) ? Res.get("shared.buyCurrency", Res.getBaseCurrencyCode()) : Res.get("shared.sellCurrency", Res.getBaseCurrencyCode());
|
||||
else
|
||||
return (direction == OfferPayload.Direction.SELL) ? Res.get("shared.buyCurrency", currencyCode) : Res.get("shared.sellCurrency", currencyCode);
|
||||
}
|
||||
|
||||
public String getDirectionWithCodeDetailed(OfferPayload.Direction direction, String currencyCode) {
|
||||
public static String getDirectionWithCodeDetailed(OfferPayload.Direction direction, String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
||||
return (direction == OfferPayload.Direction.BUY) ? Res.get("shared.buyingBTCWith", currencyCode) : Res.get("shared.sellingBTCFor", currencyCode);
|
||||
else
|
||||
return (direction == OfferPayload.Direction.SELL) ? Res.get("shared.buyingCurrency", currencyCode) : Res.get("shared.sellingCurrency", currencyCode);
|
||||
}
|
||||
|
||||
public String arbitratorAddressesToString(List<NodeAddress> nodeAddresses) {
|
||||
public static String arbitratorAddressesToString(List<NodeAddress> nodeAddresses) {
|
||||
return nodeAddresses.stream().map(NodeAddress::getFullAddress).collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
public String languageCodesToString(List<String> languageLocales) {
|
||||
return languageLocales.stream().map(LanguageUtil::getDisplayName).collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
public String formatDateTime(Date date) {
|
||||
return formatDateTime(date, true);
|
||||
}
|
||||
|
||||
public String formatDateTime(Date date, boolean useLocaleAndLocalTimezone) {
|
||||
Locale locale = useLocaleAndLocalTimezone ? getLocale() : Locale.US;
|
||||
public static String formatDateTime(Date date, boolean useLocaleAndLocalTimezone) {
|
||||
Locale locale = useLocaleAndLocalTimezone ? GlobalSettings.getLocale() : Locale.US;
|
||||
DateFormat dateInstance = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
|
||||
DateFormat timeInstance = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
|
||||
if (!useLocaleAndLocalTimezone) {
|
||||
@ -503,7 +348,7 @@ public class BSFormatter {
|
||||
return formatDateTime(date, dateInstance, timeInstance);
|
||||
}
|
||||
|
||||
public String formatDateTime(Date date, DateFormat dateFormatter, DateFormat timeFormatter) {
|
||||
public static String formatDateTime(Date date, DateFormat dateFormatter, DateFormat timeFormatter) {
|
||||
if (date != null) {
|
||||
return dateFormatter.format(date) + " " + timeFormatter.format(date);
|
||||
} else {
|
||||
@ -511,113 +356,26 @@ public class BSFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
public String formatDateTimeSpan(Date dateFrom, Date dateTo) {
|
||||
if (dateFrom != null && dateTo != null) {
|
||||
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale());
|
||||
DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale());
|
||||
return dateFormatter.format(dateFrom) + " " + timeFormatter.format(dateFrom) + RANGE_SEPARATOR + timeFormatter.format(dateTo);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String formatTime(Date date) {
|
||||
if (date != null) {
|
||||
DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale());
|
||||
return timeFormatter.format(date);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String formatDate(Date date) {
|
||||
if (date != null) {
|
||||
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale());
|
||||
return dateFormatter.format(date);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String formatToPercentWithSymbol(double value) {
|
||||
public static String formatToPercentWithSymbol(double value) {
|
||||
return formatToPercent(value) + "%";
|
||||
}
|
||||
|
||||
public String formatPercentagePrice(double value) {
|
||||
public static String formatPercentagePrice(double value) {
|
||||
return formatToPercentWithSymbol(value);
|
||||
}
|
||||
|
||||
public String formatToPercent(double value) {
|
||||
public static String formatToPercent(double value) {
|
||||
DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
||||
decimalFormat.setMinimumFractionDigits(2);
|
||||
decimalFormat.setMaximumFractionDigits(2);
|
||||
return decimalFormat.format(MathUtils.roundDouble(value * 100.0, 2)).replace(",", ".");
|
||||
}
|
||||
|
||||
public double parseNumberStringToDouble(String input) throws NumberFormatException {
|
||||
return Double.parseDouble(cleanDoubleInput(input));
|
||||
}
|
||||
|
||||
public double parsePercentStringToDouble(String percentString) throws NumberFormatException {
|
||||
String input = percentString.replace("%", "");
|
||||
input = cleanDoubleInput(input);
|
||||
double value = Double.parseDouble(input);
|
||||
return MathUtils.roundDouble(value / 100d, 4);
|
||||
}
|
||||
|
||||
public long parsePriceStringToLong(String currencyCode, String amount, int precision) {
|
||||
if (amount == null || amount.isEmpty())
|
||||
return 0;
|
||||
|
||||
long value = 0;
|
||||
try {
|
||||
double amountValue = Double.parseDouble(amount);
|
||||
amount = formatRoundedDoubleWithPrecision(amountValue, precision);
|
||||
value = Price.parse(currencyCode, amount).getValue();
|
||||
} catch (NumberFormatException ignore) {
|
||||
// expected NumberFormatException if input is not a number
|
||||
} catch (Throwable t) {
|
||||
log.error("parsePriceStringToLong: " + t.toString());
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static String convertCharsForNumber(String input) {
|
||||
// Some languages like finnish use the long dash for the minus
|
||||
input = input.replace("−", "-");
|
||||
input = StringUtils.deleteWhitespace(input);
|
||||
return input.replace(",", ".");
|
||||
}
|
||||
|
||||
protected String cleanDoubleInput(String input) {
|
||||
input = convertCharsForNumber(input);
|
||||
if (input.equals("."))
|
||||
input = input.replace(".", "0.");
|
||||
if (input.equals("-."))
|
||||
input = input.replace("-.", "-0.");
|
||||
// don't use String.valueOf(Double.parseDouble(input)) as return value as it gives scientific
|
||||
// notation (1.0E-6) which screw up coinFormat.parse
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
// Just called to check if we have a valid double, throws exception otherwise
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
Double.parseDouble(input);
|
||||
return input;
|
||||
}
|
||||
|
||||
public String formatAccountAge(long durationMillis) {
|
||||
durationMillis = Math.max(0, durationMillis);
|
||||
String day = Res.get("time.day").toLowerCase();
|
||||
String days = Res.get("time.days");
|
||||
String format = "d\' " + days + "\'";
|
||||
return StringUtils.replaceOnce(DurationFormatUtils.formatDuration(durationMillis, format), "1 " + days, "1 " + day);
|
||||
}
|
||||
|
||||
public String formatDurationAsWords(long durationMillis) {
|
||||
public static String formatDurationAsWords(long durationMillis) {
|
||||
return formatDurationAsWords(durationMillis, false, true);
|
||||
}
|
||||
|
||||
public String formatDurationAsWords(long durationMillis, boolean showSeconds, boolean showZeroValues) {
|
||||
public static String formatDurationAsWords(long durationMillis, boolean showSeconds, boolean showZeroValues) {
|
||||
String format = "";
|
||||
String second = Res.get("time.second");
|
||||
String minute = Res.get("time.minute");
|
||||
@ -657,77 +415,7 @@ public class BSFormatter {
|
||||
return duration.trim();
|
||||
}
|
||||
|
||||
public String booleanToYesNo(boolean value) {
|
||||
return value ? Res.get("shared.yes") : Res.get("shared.no");
|
||||
}
|
||||
|
||||
public String getDirectionBothSides(OfferPayload.Direction direction, String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
currencyCode = Res.getBaseCurrencyCode();
|
||||
return direction == OfferPayload.Direction.BUY ?
|
||||
Res.get("formatter.makerTaker", currencyCode, Res.get("shared.buyer"), currencyCode, Res.get("shared.seller")) :
|
||||
Res.get("formatter.makerTaker", currencyCode, Res.get("shared.seller"), currencyCode, Res.get("shared.buyer"));
|
||||
} else {
|
||||
return direction == OfferPayload.Direction.SELL ?
|
||||
Res.get("formatter.makerTaker", currencyCode, Res.get("shared.buyer"), currencyCode, Res.get("shared.seller")) :
|
||||
Res.get("formatter.makerTaker", currencyCode, Res.get("shared.seller"), currencyCode, Res.get("shared.buyer"));
|
||||
}
|
||||
}
|
||||
|
||||
public String getDirectionForBuyer(boolean isMyOffer, String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
String code = Res.getBaseCurrencyCode();
|
||||
return isMyOffer ?
|
||||
Res.get("formatter.youAreAsMaker", Res.get("shared.buying"), code, Res.get("shared.selling"), code) :
|
||||
Res.get("formatter.youAreAsTaker", Res.get("shared.buying"), code, Res.get("shared.selling"), code);
|
||||
} else {
|
||||
return isMyOffer ?
|
||||
Res.get("formatter.youAreAsMaker", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), currencyCode) :
|
||||
Res.get("formatter.youAreAsTaker", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), currencyCode);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDirectionForSeller(boolean isMyOffer, String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
String code = Res.getBaseCurrencyCode();
|
||||
return isMyOffer ?
|
||||
Res.get("formatter.youAreAsMaker", Res.get("shared.selling"), code, Res.get("shared.buying"), code) :
|
||||
Res.get("formatter.youAreAsTaker", Res.get("shared.selling"), code, Res.get("shared.buying"), code);
|
||||
} else {
|
||||
return isMyOffer ?
|
||||
Res.get("formatter.youAreAsMaker", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), currencyCode) :
|
||||
Res.get("formatter.youAreAsTaker", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), currencyCode);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDirectionForTakeOffer(OfferPayload.Direction direction, String currencyCode) {
|
||||
String baseCurrencyCode = Res.getBaseCurrencyCode();
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
return direction == OfferPayload.Direction.BUY ?
|
||||
Res.get("formatter.youAre", Res.get("shared.selling"), baseCurrencyCode, Res.get("shared.buying"), currencyCode) :
|
||||
Res.get("formatter.youAre", Res.get("shared.buying"), baseCurrencyCode, Res.get("shared.selling"), currencyCode);
|
||||
} else {
|
||||
|
||||
return direction == OfferPayload.Direction.SELL ?
|
||||
Res.get("formatter.youAre", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), baseCurrencyCode) :
|
||||
Res.get("formatter.youAre", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), baseCurrencyCode);
|
||||
}
|
||||
}
|
||||
|
||||
public String getOfferDirectionForCreateOffer(OfferPayload.Direction direction, String currencyCode) {
|
||||
String baseCurrencyCode = Res.getBaseCurrencyCode();
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
return direction == OfferPayload.Direction.BUY ?
|
||||
Res.get("formatter.youAreCreatingAnOffer.fiat", Res.get("shared.buy"), baseCurrencyCode) :
|
||||
Res.get("formatter.youAreCreatingAnOffer.fiat", Res.get("shared.sell"), baseCurrencyCode);
|
||||
} else {
|
||||
return direction == OfferPayload.Direction.SELL ?
|
||||
Res.get("formatter.youAreCreatingAnOffer.altcoin", Res.get("shared.buy"), currencyCode, Res.get("shared.selling"), baseCurrencyCode) :
|
||||
Res.get("formatter.youAreCreatingAnOffer.altcoin", Res.get("shared.sell"), currencyCode, Res.get("shared.buying"), baseCurrencyCode);
|
||||
}
|
||||
}
|
||||
|
||||
public String getRole(boolean isBuyerMakerAndSellerTaker, boolean isMaker, String currencyCode) {
|
||||
public static String getRole(boolean isBuyerMakerAndSellerTaker, boolean isMaker, String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
String baseCurrencyCode = Res.getBaseCurrencyCode();
|
||||
if (isBuyerMakerAndSellerTaker)
|
||||
@ -751,7 +439,7 @@ public class BSFormatter {
|
||||
|
||||
}
|
||||
|
||||
public String formatBytes(long bytes) {
|
||||
public static String formatBytes(long bytes) {
|
||||
double kb = 1024;
|
||||
double mb = kb * kb;
|
||||
DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
||||
@ -763,47 +451,28 @@ public class BSFormatter {
|
||||
return decimalFormat.format(bytes / mb) + " MB";
|
||||
}
|
||||
|
||||
public String getCurrencyPair(String currencyCode) {
|
||||
public static String getCurrencyPair(String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
||||
return Res.getBaseCurrencyCode() + "/" + currencyCode;
|
||||
else
|
||||
return currencyCode + "/" + Res.getBaseCurrencyCode();
|
||||
}
|
||||
|
||||
public String getCounterCurrency(String currencyCode) {
|
||||
public static String getCounterCurrency(String currencyCode) {
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
||||
return currencyCode;
|
||||
else
|
||||
return Res.getBaseCurrencyCode();
|
||||
}
|
||||
|
||||
public String getBaseCurrency(String currencyCode) {
|
||||
if (CurrencyUtil.isCryptoCurrency(currencyCode))
|
||||
return currencyCode;
|
||||
else
|
||||
return Res.getBaseCurrencyCode();
|
||||
}
|
||||
|
||||
public String getCounterCurrencyAndCurrencyPair(String currencyCode) {
|
||||
return getCounterCurrency(currencyCode) + " (" + getCurrencyPair(currencyCode) + ")";
|
||||
}
|
||||
|
||||
public String getCurrencyNameAndCurrencyPair(String currencyCode) {
|
||||
return CurrencyUtil.getNameByCode(currencyCode) + " (" + getCurrencyPair(currencyCode) + ")";
|
||||
}
|
||||
|
||||
public String getPriceWithCurrencyCode(String currencyCode) {
|
||||
public static String getPriceWithCurrencyCode(String currencyCode) {
|
||||
return getPriceWithCurrencyCode(currencyCode, "shared.priceInCurForCur");
|
||||
}
|
||||
|
||||
public String getPriceWithCurrencyCode(String currencyCode, String translationKey) {
|
||||
public static String getPriceWithCurrencyCode(String currencyCode, String translationKey) {
|
||||
if (CurrencyUtil.isCryptoCurrency(currencyCode))
|
||||
return Res.get(translationKey, Res.getBaseCurrencyCode(), currencyCode);
|
||||
else
|
||||
return Res.get(translationKey, currencyCode, Res.getBaseCurrencyCode());
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return GlobalSettings.getLocale();
|
||||
}
|
||||
}
|
||||
|
@ -61,12 +61,12 @@ public class BsqFormatter extends BSFormatter {
|
||||
GlobalSettings.localeProperty().addListener((observable, oldValue, newValue) -> setFormatter(newValue));
|
||||
setFormatter(GlobalSettings.getLocale());
|
||||
|
||||
btcCoinFormat = super.coinFormat;
|
||||
btcCoinFormat = super.monetaryFormat;
|
||||
|
||||
final String baseCurrencyCode = BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode();
|
||||
switch (baseCurrencyCode) {
|
||||
case "BTC":
|
||||
coinFormat = new MonetaryFormat().shift(6).code(6, "BSQ").minDecimals(2);
|
||||
monetaryFormat = new MonetaryFormat().shift(6).code(6, "BSQ").minDecimals(2);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("baseCurrencyCode not defined. baseCurrencyCode=" + baseCurrencyCode);
|
||||
@ -123,11 +123,11 @@ public class BsqFormatter extends BSFormatter {
|
||||
}
|
||||
|
||||
public String formatBSQSatoshis(long satoshi) {
|
||||
return super.formatCoin(satoshi, coinFormat);
|
||||
return super.formatCoin(satoshi, monetaryFormat);
|
||||
}
|
||||
|
||||
public String formatBSQSatoshisWithCode(long satoshi) {
|
||||
return super.formatCoinWithCode(satoshi, coinFormat);
|
||||
return super.formatCoinWithCode(satoshi, monetaryFormat);
|
||||
}
|
||||
|
||||
public String formatBTCSatoshis(long satoshi) {
|
||||
@ -147,7 +147,7 @@ public class BsqFormatter extends BSFormatter {
|
||||
}
|
||||
|
||||
public Coin parseToBTC(String input) {
|
||||
return super.parseToCoin(input, btcCoinFormat);
|
||||
return ParsingUtils.parseToCoin(input, btcCoinFormat);
|
||||
}
|
||||
|
||||
public void validateBtcInput(String input) throws ProposalValidationException {
|
||||
@ -155,12 +155,12 @@ public class BsqFormatter extends BSFormatter {
|
||||
}
|
||||
|
||||
public void validateBsqInput(String input) throws ProposalValidationException {
|
||||
validateCoinInput(input, this.coinFormat);
|
||||
validateCoinInput(input, this.monetaryFormat);
|
||||
}
|
||||
|
||||
private void validateCoinInput(String input, MonetaryFormat coinFormat) throws ProposalValidationException {
|
||||
try {
|
||||
coinFormat.parse(cleanDoubleInput(input));
|
||||
coinFormat.parse(ParsingUtils.cleanDoubleInput(input));
|
||||
} catch (Throwable t) {
|
||||
throw new ProposalValidationException("Invalid format for a " + coinFormat.code() + " value");
|
||||
}
|
||||
@ -172,11 +172,11 @@ public class BsqFormatter extends BSFormatter {
|
||||
// In case we add a new param old clients will not know that enum and fall back to UNDEFINED.
|
||||
return Res.get("shared.na");
|
||||
case BSQ:
|
||||
return formatCoinWithCode(parseToCoin(value));
|
||||
return formatCoinWithCode(ParsingUtils.parseToCoin(value, this));
|
||||
case BTC:
|
||||
return formatBTCWithCode(parseToBTC(value));
|
||||
case PERCENT:
|
||||
return formatToPercentWithSymbol(parsePercentStringToDouble(value));
|
||||
return formatToPercentWithSymbol(ParsingUtils.parsePercentStringToDouble(value));
|
||||
case BLOCK:
|
||||
return Res.get("dao.param.blocks", Integer.parseInt(value));
|
||||
case ADDRESS:
|
||||
@ -190,7 +190,7 @@ public class BsqFormatter extends BSFormatter {
|
||||
public Coin parseParamValueToCoin(Param param, String inputValue) {
|
||||
switch (param.getParamType()) {
|
||||
case BSQ:
|
||||
return parseToCoin(inputValue);
|
||||
return ParsingUtils.parseToCoin(inputValue, this);
|
||||
case BTC:
|
||||
return parseToBTC(inputValue);
|
||||
default:
|
||||
@ -216,7 +216,7 @@ public class BsqFormatter extends BSFormatter {
|
||||
case BTC:
|
||||
return formatBTC(parseParamValueToCoin(param, inputValue));
|
||||
case PERCENT:
|
||||
return formatToPercent(parsePercentStringToDouble(inputValue));
|
||||
return formatToPercent(ParsingUtils.parsePercentStringToDouble(inputValue));
|
||||
case BLOCK:
|
||||
return Integer.toString(parseParamValueToBlocks(param, inputValue));
|
||||
case ADDRESS:
|
||||
|
83
core/src/main/java/bisq/core/util/ParsingUtils.java
Normal file
83
core/src/main/java/bisq/core/util/ParsingUtils.java
Normal file
@ -0,0 +1,83 @@
|
||||
package bisq.core.util;
|
||||
|
||||
import bisq.core.monetary.Price;
|
||||
|
||||
import bisq.common.util.MathUtils;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.utils.MonetaryFormat;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ParsingUtils {
|
||||
public static Coin parseToCoin(String input, BSFormatter bsFormatter) {
|
||||
return parseToCoin(input, bsFormatter.getMonetaryFormat());
|
||||
}
|
||||
|
||||
public static Coin parseToCoin(String input, MonetaryFormat coinFormat) {
|
||||
if (input != null && input.length() > 0) {
|
||||
try {
|
||||
return coinFormat.parse(cleanDoubleInput(input));
|
||||
} catch (Throwable t) {
|
||||
log.warn("Exception at parseToBtc: " + t.toString());
|
||||
return Coin.ZERO;
|
||||
}
|
||||
} else {
|
||||
return Coin.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
public static double parseNumberStringToDouble(String input) throws NumberFormatException {
|
||||
return Double.parseDouble(cleanDoubleInput(input));
|
||||
}
|
||||
|
||||
public static double parsePercentStringToDouble(String percentString) throws NumberFormatException {
|
||||
String input = percentString.replace("%", "");
|
||||
input = cleanDoubleInput(input);
|
||||
double value = Double.parseDouble(input);
|
||||
return MathUtils.roundDouble(value / 100d, 4);
|
||||
}
|
||||
|
||||
public static long parsePriceStringToLong(String currencyCode, String amount, int precision) {
|
||||
if (amount == null || amount.isEmpty())
|
||||
return 0;
|
||||
|
||||
long value = 0;
|
||||
try {
|
||||
double amountValue = Double.parseDouble(amount);
|
||||
amount = BSFormatter.formatRoundedDoubleWithPrecision(amountValue, precision);
|
||||
value = Price.parse(currencyCode, amount).getValue();
|
||||
} catch (NumberFormatException ignore) {
|
||||
// expected NumberFormatException if input is not a number
|
||||
} catch (Throwable t) {
|
||||
log.error("parsePriceStringToLong: " + t.toString());
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static String convertCharsForNumber(String input) {
|
||||
// Some languages like finnish use the long dash for the minus
|
||||
input = input.replace("−", "-");
|
||||
input = StringUtils.deleteWhitespace(input);
|
||||
return input.replace(",", ".");
|
||||
}
|
||||
|
||||
public static String cleanDoubleInput(String input) {
|
||||
input = convertCharsForNumber(input);
|
||||
if (input.equals("."))
|
||||
input = input.replace(".", "0.");
|
||||
if (input.equals("-."))
|
||||
input = input.replace("-.", "-0.");
|
||||
// don't use String.valueOf(Double.parseDouble(input)) as return value as it gives scientific
|
||||
// notation (1.0E-6) which screw up coinFormat.parse
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
// Just called to check if we have a valid double, throws exception otherwise
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
Double.parseDouble(input);
|
||||
return input;
|
||||
}
|
||||
}
|
@ -506,7 +506,7 @@ takeOffer.failed.offerTaken=You cannot take that offer because the offer was alr
|
||||
takeOffer.failed.offerRemoved=You cannot take that offer because the offer has been removed in the meantime.
|
||||
takeOffer.failed.offererNotOnline=Take offer request failed because maker is not online anymore.
|
||||
takeOffer.failed.offererOffline=You cannot take that offer because the maker is offline.
|
||||
takeOffer.warning.connectionToPeerLost=You lost connection to the maker.\nHe might have gone offline or has closed the connection to you because of too many open connections.\n\nIf you can still see his offer in the offerbook you can try to take the offer again.
|
||||
takeOffer.warning.connectionToPeerLost=You lost connection to the maker.\nThey might have gone offline or has closed the connection to you because of too many open connections.\n\nIf you can still see their offer in the offerbook you can try to take the offer again.
|
||||
|
||||
takeOffer.error.noFundsLost=\n\nNo funds have left your wallet yet.\nPlease try to restart your application and check your network connection to see if you can resolve the issue.
|
||||
takeOffer.error.feePaid=\n\nPlease try to restart your application and check your network connection to see if you can resolve the issue.
|
||||
@ -613,7 +613,7 @@ 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 they have started the payment.\nThe trade has to be completed by {1}.
|
||||
portfolio.pending.step2_seller.warn=The BTC buyer still has not done the {0} payment.\nYou need to wait until they have started 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 their payment!\nThe max. allowed period for the trade has elapsed.\nYou can wait longer and give the trading peer more time or contact the mediator for assistance.
|
||||
|
||||
tradeChat.chatWindowTitle=Chat window for trade with ID ''{0}''
|
||||
@ -779,7 +779,7 @@ portfolio.pending.mediationRequested=Mediation requested
|
||||
portfolio.pending.openSupport=Open support ticket
|
||||
portfolio.pending.supportTicketOpened=Support ticket opened
|
||||
portfolio.pending.requestSupport=Request support
|
||||
portfolio.pending.error.requestSupport=Please report the problem to your mediator or arbitrator.\n\nHe will forward the \
|
||||
portfolio.pending.error.requestSupport=Please report the problem to your mediator or arbitrator.\n\nThey will forward the \
|
||||
information to the developers to investigate the problem.\nAfter the problem has been analyzed you will \
|
||||
get back all locked funds.
|
||||
portfolio.pending.communicateWithArbitrator=Please communicate in the \"Support\" screen with the arbitrator.
|
||||
@ -910,7 +910,7 @@ support.filter=Filter list
|
||||
support.filter.prompt=Enter trade ID, date, onion address or account data
|
||||
support.noTickets=There are no open tickets
|
||||
support.sendingMessage=Sending Message...
|
||||
support.receiverNotOnline=Receiver is not online. Message is saved to his mailbox.
|
||||
support.receiverNotOnline=Receiver is not online. Message is saved to their mailbox.
|
||||
support.sendMessageError=Sending message failed. Error: {0}
|
||||
support.wrongVersion=The offer in that dispute has been created with an older version of Bisq.\n\
|
||||
You cannot close that dispute with your version of the application.\n\n\
|
||||
|
2501
core/src/main/resources/i18n/displayStrings_pt_BR.properties
Normal file
2501
core/src/main/resources/i18n/displayStrings_pt_BR.properties
Normal file
File diff suppressed because it is too large
Load Diff
@ -46,7 +46,7 @@ public class ArbitratorTest {
|
||||
return new Arbitrator(new NodeAddress("host", 1000),
|
||||
getBytes(100),
|
||||
"btcaddress",
|
||||
new PubKeyRing(getBytes(100), getBytes(100), "key"),
|
||||
new PubKeyRing(getBytes(100), getBytes(100)),
|
||||
Lists.newArrayList(),
|
||||
new Date().getTime(),
|
||||
getBytes(100),
|
||||
@ -58,4 +58,3 @@ public class ArbitratorTest {
|
||||
return RandomUtils.nextBytes(count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class MediatorTest {
|
||||
|
||||
public static Mediator getMediatorMock() {
|
||||
return new Mediator(new NodeAddress("host", 1000),
|
||||
new PubKeyRing(getBytes(100), getBytes(100), "key"),
|
||||
new PubKeyRing(getBytes(100), getBytes(100)),
|
||||
Lists.newArrayList(),
|
||||
new Date().getTime(),
|
||||
getBytes(100),
|
||||
@ -53,6 +53,4 @@ public class MediatorTest {
|
||||
"info",
|
||||
null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -22,11 +22,8 @@ import bisq.common.crypto.KeyRing;
|
||||
import bisq.common.crypto.KeyStorage;
|
||||
import bisq.common.storage.FileUtil;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Security;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
import java.io.File;
|
||||
@ -62,5 +59,3 @@ public class EncryptionTest {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cd $(dirname $0)
|
||||
tx pull -l de,el_GR,es,ja,pt,ru,zh_CN,vi,th_TH,fa,fr
|
||||
tx pull -l de,el_GR,es,ja,pt,ru,zh_CN,vi,th_TH,fa,fr,pt_BR
|
||||
|
||||
translations="translations/bisq-desktop.displaystringsproperties"
|
||||
i18n="src/main/resources/i18n"
|
||||
@ -17,5 +17,6 @@ mv "$translations/vi.properties" "$i18n/displayStrings_vi.properties"
|
||||
mv "$translations/th_TH.properties" "$i18n/displayStrings_th.properties"
|
||||
mv "$translations/fa.properties" "$i18n/displayStrings_fa.properties"
|
||||
mv "$translations/fr.properties" "$i18n/displayStrings_fr.properties"
|
||||
mv "$translations/pt_BR.properties" "$i18n/displayStrings_pt_BR.properties"
|
||||
|
||||
rm -rf $translations
|
||||
|
43
desktop/package/macosx/create_desktop_for_testing.sh
Executable file
43
desktop/package/macosx/create_desktop_for_testing.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $(dirname $0)/../../
|
||||
|
||||
mkdir -p deploy
|
||||
|
||||
set -e
|
||||
|
||||
version="1.1.5-SNAPSHOT"
|
||||
commithash="ec633f0c3771893b47956b8d05b17c6f3f1919c1"
|
||||
|
||||
cd ..
|
||||
./gradlew :desktop:build -x test shadowJar
|
||||
cd desktop
|
||||
|
||||
EXE_JAR=build/libs/desktop-$version-all.jar
|
||||
JAR_WITH_HASH_NAME=desktop-$version-$commithash-all.jar
|
||||
EXE_JAR_WITH_HASH=build/libs/$JAR_WITH_HASH_NAME
|
||||
DEPLOY_JAR=deploy/$JAR_WITH_HASH_NAME
|
||||
|
||||
# we need to strip out Java 9 module configuration used in the fontawesomefx library as it causes the javapackager to stop,
|
||||
# because of this existing module information, although it is not used as a module.
|
||||
echo Unzipping jar to delete module config
|
||||
tmp=build/libs/tmp
|
||||
unzip -o -q $EXE_JAR -d $tmp
|
||||
|
||||
# Sometimes $tmp/module-info.class is not available. TODO check why and if still needed
|
||||
rm -f $tmp/module-info.class
|
||||
|
||||
rm $EXE_JAR
|
||||
echo Zipping jar again without module config
|
||||
cd $tmp; zip -r -q -X "../$JAR_WITH_HASH_NAME" *
|
||||
cd ../../../; rm -rf $tmp
|
||||
|
||||
cp $EXE_JAR_WITH_HASH $DEPLOY_JAR
|
||||
|
||||
echo Create signature
|
||||
gpg --digest-algo SHA256 --local-user $BISQ_GPG_USER --output $DEPLOY_JAR.asc --detach-sig --armor $DEPLOY_JAR
|
||||
|
||||
echo Verify signatures
|
||||
gpg --digest-algo SHA256 --verify $DEPLOY_JAR{.asc*,}
|
||||
|
||||
open deploy
|
43
desktop/package/macosx/create_seednode_for_testing.sh
Executable file
43
desktop/package/macosx/create_seednode_for_testing.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $(dirname $0)/../../
|
||||
|
||||
set -e
|
||||
|
||||
version="1.1.5-SNAPSHOT"
|
||||
commithash="ec633f0c3771893b47956b8d05b17c6f3f1919c1"
|
||||
|
||||
cd ..
|
||||
./gradlew :seednode:build -x test shadowJar
|
||||
cd seednode
|
||||
|
||||
mkdir -p deploy
|
||||
|
||||
EXE_JAR=build/libs/seednode-all.jar
|
||||
JAR_WITH_HASH_NAME=seednode-$version-$commithash-all.jar
|
||||
EXE_JAR_WITH_HASH=build/libs/$JAR_WITH_HASH_NAME
|
||||
DEPLOY_JAR=deploy/$JAR_WITH_HASH_NAME
|
||||
|
||||
# we need to strip out Java 9 module configuration used in the fontawesomefx library as it causes the javapackager to stop,
|
||||
# because of this existing module information, although it is not used as a module.
|
||||
echo Unzipping jar to delete module config
|
||||
tmp=build/libs/tmp
|
||||
unzip -o -q $EXE_JAR -d $tmp
|
||||
|
||||
# Sometimes $tmp/module-info.class is not available. TODO check why and if still needed
|
||||
rm -f $tmp/module-info.class
|
||||
|
||||
rm $EXE_JAR
|
||||
echo Zipping jar again without module config
|
||||
cd $tmp; zip -r -q -X "../$JAR_WITH_HASH_NAME" *
|
||||
cd ../../../; rm -rf $tmp
|
||||
|
||||
cp $EXE_JAR_WITH_HASH $DEPLOY_JAR
|
||||
|
||||
echo Create signature
|
||||
gpg --digest-algo SHA256 --local-user $BISQ_GPG_USER --output $DEPLOY_JAR.asc --detach-sig --armor $DEPLOY_JAR
|
||||
|
||||
echo Verify signatures
|
||||
gpg --digest-algo SHA256 --verify $DEPLOY_JAR{.asc*,}
|
||||
|
||||
open deploy
|
@ -18,6 +18,7 @@
|
||||
package bisq.desktop.components;
|
||||
|
||||
import bisq.desktop.main.overlays.editor.PeerInfoWithTagEditor;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
import bisq.core.alert.PrivateNotificationManager;
|
||||
@ -141,7 +142,7 @@ public class PeerInfoIcon extends Group {
|
||||
boolean isFiatCurrency = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode());
|
||||
|
||||
String accountAge = isFiatCurrency ?
|
||||
peersAccountAge > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(peersAccountAge)) :
|
||||
peersAccountAge > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(peersAccountAge)) :
|
||||
Res.get("peerInfoIcon.tooltip.unknownAge") :
|
||||
"";
|
||||
tooltipText = hasTraded ?
|
||||
@ -268,7 +269,7 @@ public class PeerInfoIcon extends Group {
|
||||
long makersAccountAge) {
|
||||
final String accountAgeTagEditor = isFiatCurrency ?
|
||||
makersAccountAge > -1 ?
|
||||
formatter.formatAccountAge(makersAccountAge) :
|
||||
DisplayUtils.formatAccountAge(makersAccountAge) :
|
||||
Res.get("peerInfo.unknownAge") :
|
||||
null;
|
||||
setOnMouseClicked(e -> new PeerInfoWithTagEditor(privateNotificationManager, offer, preferences, useDevPrivilegeKeys)
|
||||
|
@ -21,6 +21,7 @@ import bisq.desktop.components.AutoTooltipCheckBox;
|
||||
import bisq.desktop.components.InfoTextField;
|
||||
import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
@ -182,7 +183,7 @@ public abstract class PaymentMethodForm {
|
||||
Res.get("payment.maxPeriodAndLimit",
|
||||
getTimeText(hours),
|
||||
formatter.formatCoinWithCode(Coin.valueOf(accountAgeWitnessService.getMyTradeLimit(paymentAccount, tradeCurrency.getCode()))),
|
||||
formatter.formatAccountAge(accountAge));
|
||||
DisplayUtils.formatAccountAge(accountAge));
|
||||
|
||||
if (isDisplayForm)
|
||||
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.limitations"), limitationsText);
|
||||
|
@ -38,6 +38,7 @@ import bisq.desktop.main.portfolio.PortfolioView;
|
||||
import bisq.desktop.main.settings.SettingsView;
|
||||
import bisq.desktop.main.shared.PriceFeedComboBoxItem;
|
||||
import bisq.desktop.main.support.SupportView;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.Transitions;
|
||||
|
||||
import bisq.core.dao.monitoring.DaoStateMonitoringService;
|
||||
@ -523,14 +524,14 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
|
||||
res = Res.get("mainView.marketPrice.tooltip",
|
||||
"https://bitcoinaverage.com",
|
||||
"",
|
||||
formatter.formatTime(model.getPriceFeedService().getLastRequestTimeStampBtcAverage()),
|
||||
DisplayUtils.formatTime(model.getPriceFeedService().getLastRequestTimeStampBtcAverage()),
|
||||
model.getPriceFeedService().getProviderNodeAddress());
|
||||
} else {
|
||||
String altcoinExtra = "\n" + Res.get("mainView.marketPrice.tooltip.altcoinExtra");
|
||||
res = Res.get("mainView.marketPrice.tooltip",
|
||||
"https://poloniex.com",
|
||||
altcoinExtra,
|
||||
formatter.formatTime(model.getPriceFeedService().getLastRequestTimeStampPoloniex()),
|
||||
DisplayUtils.formatTime(model.getPriceFeedService().getLastRequestTimeStampPoloniex()),
|
||||
model.getPriceFeedService().getProviderNodeAddress());
|
||||
}
|
||||
return res;
|
||||
|
@ -33,6 +33,7 @@ import bisq.desktop.main.overlays.windows.downloadupdate.DisplayUpdateDownloadWi
|
||||
import bisq.desktop.main.presentation.DaoPresentation;
|
||||
import bisq.desktop.main.presentation.MarketPricePresentation;
|
||||
import bisq.desktop.main.shared.PriceFeedComboBoxItem;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
@ -218,7 +219,7 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupCompleteList
|
||||
DontShowAgainLookup.dontShowAgain(key, true);
|
||||
new Popup<>().warning(Res.get("popup.warning.tradePeriod.halfReached",
|
||||
trade.getShortId(),
|
||||
formatter.formatDateTime(maxTradePeriodDate)))
|
||||
DisplayUtils.formatDateTime(maxTradePeriodDate)))
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
@ -228,7 +229,7 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupCompleteList
|
||||
DontShowAgainLookup.dontShowAgain(key, true);
|
||||
new Popup<>().warning(Res.get("popup.warning.tradePeriod.ended",
|
||||
trade.getShortId(),
|
||||
formatter.formatDateTime(maxTradePeriodDate)))
|
||||
DisplayUtils.formatDateTime(maxTradePeriodDate)))
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
|
@ -140,7 +140,7 @@ public class ManageMarketAlertsWindow extends Overlay<ManageMarketAlertsWindow>
|
||||
public void updateItem(final MarketAlertFilter item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(formatter.formatPercentagePrice(item.getTriggerValue() / 10000d));
|
||||
setText(BSFormatter.formatPercentagePrice(item.getTriggerValue() / 10000d));
|
||||
} else {
|
||||
setText("");
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ import bisq.core.provider.price.PriceFeedService;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.user.User;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
import bisq.core.util.validation.InputValidator;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
@ -347,7 +348,7 @@ public class MobileNotificationsView extends ActivatableView<GridPane, Void> {
|
||||
|
||||
private void onAddMarketAlert() {
|
||||
PaymentAccount paymentAccount = paymentAccountsComboBox.getSelectionModel().getSelectedItem();
|
||||
double percentAsDouble = formatter.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText());
|
||||
double percentAsDouble = ParsingUtils.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText());
|
||||
int triggerValue = (int) Math.round(percentAsDouble * 10000);
|
||||
boolean isBuyOffer = offerTypeRadioButtonsToggleGroup.getSelectedToggle() == buyOffersRadioButton;
|
||||
MarketAlertFilter marketAlertFilter = new MarketAlertFilter(paymentAccount, triggerValue, isBuyOffer);
|
||||
@ -510,8 +511,8 @@ public class MobileNotificationsView extends ActivatableView<GridPane, Void> {
|
||||
marketAlertTriggerFocusListener = (observable, oldValue, newValue) -> {
|
||||
if (oldValue && !newValue) {
|
||||
try {
|
||||
double percentAsDouble = formatter.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText()) * 100;
|
||||
marketAlertTriggerInputTextField.setText(formatter.formatRoundedDoubleWithPrecision(percentAsDouble, 2) + "%");
|
||||
double percentAsDouble = ParsingUtils.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText()) * 100;
|
||||
marketAlertTriggerInputTextField.setText(BSFormatter.formatRoundedDoubleWithPrecision(percentAsDouble, 2) + "%");
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
|
||||
@ -695,8 +696,8 @@ public class MobileNotificationsView extends ActivatableView<GridPane, Void> {
|
||||
currencyComboBox.getSelectionModel().select(optionalTradeCurrency.get());
|
||||
onSelectedTradeCurrency();
|
||||
|
||||
priceAlertHighInputTextField.setText(formatter.formatMarketPrice(priceAlertFilter.getHigh() / 10000d, currencyCode));
|
||||
priceAlertLowInputTextField.setText(formatter.formatMarketPrice(priceAlertFilter.getLow() / 10000d, currencyCode));
|
||||
priceAlertHighInputTextField.setText(BSFormatter.formatMarketPrice(priceAlertFilter.getHigh() / 10000d, currencyCode));
|
||||
priceAlertLowInputTextField.setText(BSFormatter.formatMarketPrice(priceAlertFilter.getLow() / 10000d, currencyCode));
|
||||
} else {
|
||||
currencyComboBox.getSelectionModel().clearSelection();
|
||||
}
|
||||
@ -747,15 +748,15 @@ public class MobileNotificationsView extends ActivatableView<GridPane, Void> {
|
||||
try {
|
||||
String inputValue = inputTextField.getText();
|
||||
if (inputValue != null && !inputValue.isEmpty() && selectedPriceAlertTradeCurrency != null) {
|
||||
double priceAsDouble = formatter.parseNumberStringToDouble(inputValue);
|
||||
double priceAsDouble = ParsingUtils.parseNumberStringToDouble(inputValue);
|
||||
String currencyCode = selectedPriceAlertTradeCurrency;
|
||||
int precision = CurrencyUtil.isCryptoCurrency(currencyCode) ?
|
||||
Altcoin.SMALLEST_UNIT_EXPONENT : 2;
|
||||
// We want to use the converted value not the inout value as we apply the converted value at focus out.
|
||||
// E.g. if input is 5555.5555 it will be rounded to 5555.55 and we use that as the value for comparing
|
||||
// low and high price...
|
||||
String stringValue = formatter.formatRoundedDoubleWithPrecision(priceAsDouble, precision);
|
||||
return formatter.parsePriceStringToLong(currencyCode, stringValue, precision);
|
||||
String stringValue = BSFormatter.formatRoundedDoubleWithPrecision(priceAsDouble, precision);
|
||||
return ParsingUtils.parsePriceStringToLong(currencyCode, stringValue, precision);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -768,11 +769,11 @@ public class MobileNotificationsView extends ActivatableView<GridPane, Void> {
|
||||
try {
|
||||
String inputValue = inputTextField.getText();
|
||||
if (inputValue != null && !inputValue.isEmpty() && selectedPriceAlertTradeCurrency != null) {
|
||||
double priceAsDouble = formatter.parseNumberStringToDouble(inputValue);
|
||||
double priceAsDouble = ParsingUtils.parseNumberStringToDouble(inputValue);
|
||||
String currencyCode = selectedPriceAlertTradeCurrency;
|
||||
int precision = CurrencyUtil.isCryptoCurrency(currencyCode) ?
|
||||
Altcoin.SMALLEST_UNIT_EXPONENT : 2;
|
||||
String stringValue = formatter.formatRoundedDoubleWithPrecision(priceAsDouble, precision);
|
||||
String stringValue = BSFormatter.formatRoundedDoubleWithPrecision(priceAsDouble, precision);
|
||||
inputTextField.setText(stringValue);
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
|
@ -113,7 +113,7 @@ public class BondingViewUtils {
|
||||
Coin miningFee = miningFeeAndTxSize.first;
|
||||
int txSize = miningFeeAndTxSize.second;
|
||||
BSFormatter formatter = new BSFormatter();
|
||||
String duration = formatter.formatDurationAsWords(lockupTime * 10 * 60 * 1000L, false, false);
|
||||
String duration = BSFormatter.formatDurationAsWords(lockupTime * 10 * 60 * 1000L, false, false);
|
||||
new Popup<>().headLine(Res.get("dao.bond.reputation.lockup.headline"))
|
||||
.confirmation(Res.get("dao.bond.reputation.lockup.details",
|
||||
bsqFormatter.formatCoinWithCode(lockupAmount),
|
||||
@ -172,7 +172,7 @@ public class BondingViewUtils {
|
||||
Coin miningFee = miningFeeAndTxSize.first;
|
||||
int txSize = miningFeeAndTxSize.second;
|
||||
BSFormatter formatter = new BSFormatter();
|
||||
String duration = formatter.formatDurationAsWords(lockTime * 10 * 60 * 1000L, false, false);
|
||||
String duration = BSFormatter.formatDurationAsWords(lockTime * 10 * 60 * 1000L, false, false);
|
||||
new Popup<>().headLine(Res.get("dao.bond.reputation.unlock.headline"))
|
||||
.confirmation(Res.get("dao.bond.reputation.unlock.details",
|
||||
bsqFormatter.formatCoinWithCode(unlockAmount),
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package bisq.desktop.main.dao.bonding.bonds;
|
||||
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
@ -58,7 +60,7 @@ class BondListItem {
|
||||
bondDetails = Utilities.bytesAsHexString(bond.getBondedAsset().getHash());
|
||||
}
|
||||
lockupTxId = bond.getLockupTxId();
|
||||
lockupDateString = bond.getLockupDate() > 0 ? bsqFormatter.formatDateTime(new Date(bond.getLockupDate())) : "-";
|
||||
lockupDateString = bond.getLockupDate() > 0 ? DisplayUtils.formatDateTime(new Date(bond.getLockupDate())) : "-";
|
||||
bondState = bond.getBondState();
|
||||
bondStateString = Res.get("dao.bond.bondState." + bond.getBondState().name());
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package bisq.desktop.main.dao.bonding.reputation;
|
||||
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.MyReputation;
|
||||
@ -57,7 +59,7 @@ class MyReputationListItem {
|
||||
txId = myBondedReputation.getLockupTxId();
|
||||
amount = bsqFormatter.formatCoin(Coin.valueOf(myBondedReputation.getAmount()));
|
||||
lockupDate = new Date(myBondedReputation.getLockupDate());
|
||||
lockupDateString = bsqFormatter.formatDateTime(lockupDate);
|
||||
lockupDateString = DisplayUtils.formatDateTime(lockupDate);
|
||||
lockTime = Integer.toString(myBondedReputation.getLockTime());
|
||||
lockupTxId = myBondedReputation.getLockupTxId();
|
||||
bondState = myBondedReputation.getBondState();
|
||||
|
@ -38,6 +38,7 @@ import bisq.core.dao.governance.bond.reputation.MyBondedReputation;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
import bisq.core.util.validation.HexStringValidator;
|
||||
import bisq.core.util.validation.IntegerValidator;
|
||||
|
||||
@ -170,7 +171,7 @@ public class MyReputationView extends ActivatableView<GridPane, Void> implements
|
||||
bsqWalletService.addBsqBalanceListener(this);
|
||||
|
||||
lockupButton.setOnAction((event) -> {
|
||||
Coin lockupAmount = bsqFormatter.parseToCoin(amountInputTextField.getText());
|
||||
Coin lockupAmount = ParsingUtils.parseToCoin(amountInputTextField.getText(), bsqFormatter);
|
||||
int lockupTime = Integer.parseInt(timeInputTextField.getText());
|
||||
byte[] salt = Utilities.decodeFromHex(saltInputTextField.getText());
|
||||
bondingViewUtils.lockupBondForReputation(lockupAmount,
|
||||
|
@ -18,6 +18,7 @@
|
||||
package bisq.desktop.main.dao.bonding.roles;
|
||||
|
||||
import bisq.desktop.main.overlays.Overlay;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
@ -97,6 +98,6 @@ class RoleDetailsWindow extends Overlay<RoleDetailsWindow> {
|
||||
bondedRoleType.getLink(), bondedRoleType.getLink(), 0);
|
||||
|
||||
FormBuilder.addTopLabelTextField(gridPane, ++rowIndex, Res.get("dao.bond.details.isSingleton"),
|
||||
bsqFormatter.booleanToYesNo(bondedRoleType.isAllowMultipleHolders()));
|
||||
DisplayUtils.booleanToYesNo(bondedRoleType.isAllowMultipleHolders()));
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import bisq.common.app.DevEnv;
|
||||
|
||||
@ -273,7 +274,7 @@ public class AssetFeeView extends ActivatableView<GridPane, Void> implements Bsq
|
||||
}
|
||||
|
||||
private Coin getListingFee() {
|
||||
return bsqFormatter.parseToCoin(feeAmountInputTextField.getText());
|
||||
return ParsingUtils.parseToCoin(feeAmountInputTextField.getText(), bsqFormatter);
|
||||
}
|
||||
|
||||
private void doPublishFeeTx(Transaction transaction) {
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package bisq.desktop.main.dao.burnbsq.proofofburn;
|
||||
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.dao.governance.proofofburn.MyProofOfBurn;
|
||||
import bisq.core.dao.governance.proofofburn.ProofOfBurnService;
|
||||
import bisq.core.dao.state.model.blockchain.Tx;
|
||||
@ -52,7 +54,7 @@ class MyProofOfBurnListItem {
|
||||
if (optionalTx.isPresent()) {
|
||||
Tx tx = optionalTx.get();
|
||||
date = new Date(tx.getTime());
|
||||
dateAsString = bsqFormatter.formatDateTime(date);
|
||||
dateAsString = DisplayUtils.formatDateTime(date);
|
||||
amount = proofOfBurnService.getAmount(tx);
|
||||
amountAsString = bsqFormatter.formatCoinWithCode(Coin.valueOf(amount));
|
||||
txId = tx.getId();
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package bisq.desktop.main.dao.burnbsq.proofofburn;
|
||||
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.dao.governance.proofofburn.ProofOfBurnService;
|
||||
import bisq.core.dao.state.model.blockchain.Tx;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
@ -46,6 +48,6 @@ class ProofOfBurnListItem {
|
||||
hashAsHex = Utilities.bytesAsHexString(proofOfBurnService.getHashFromOpReturnData(tx));
|
||||
pubKey = Utilities.bytesAsHexString(proofOfBurnService.getPubKey(txId));
|
||||
date = new Date(tx.getTime());
|
||||
dateAsString = bsqFormatter.formatDateTime(date);
|
||||
dateAsString = DisplayUtils.formatDateTime(date);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
import bisq.core.util.validation.InputValidator;
|
||||
|
||||
import bisq.common.app.DevEnv;
|
||||
@ -273,7 +274,7 @@ public class ProofOfBurnView extends ActivatableView<GridPane, Void> implements
|
||||
}
|
||||
|
||||
private Coin getAmountFee() {
|
||||
return bsqFormatter.parseToCoin(amountInputTextField.getText());
|
||||
return ParsingUtils.parseToCoin(amountInputTextField.getText(), bsqFormatter);
|
||||
}
|
||||
|
||||
private void doPublishFeeTx(Transaction transaction, String preImageAsString) {
|
||||
|
@ -34,6 +34,7 @@ import bisq.core.provider.price.PriceFeedService;
|
||||
import bisq.core.trade.statistics.TradeStatistics2;
|
||||
import bisq.core.trade.statistics.TradeStatisticsManager;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.MathUtils;
|
||||
@ -321,7 +322,7 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
||||
Optional<Price> optionalBsqPrice = priceFeedService.getBsqPrice();
|
||||
if (optionalBsqPrice.isPresent()) {
|
||||
Price bsqPrice = optionalBsqPrice.get();
|
||||
marketPriceLabel.setText(bsqFormatter.formatPrice(bsqPrice) + " BSQ/BTC");
|
||||
marketPriceLabel.setText(BSFormatter.formatPrice(bsqPrice) + " BSQ/BTC");
|
||||
|
||||
marketCapTextField.setText(bsqFormatter.formatMarketCap(priceFeedService.getMarketPrice("BSQ"),
|
||||
priceFeedService.getMarketPrice(preferences.getPreferredTradeCurrency().getCode()),
|
||||
|
@ -52,6 +52,7 @@ import bisq.core.dao.state.model.governance.Role;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import bisq.asset.Asset;
|
||||
|
||||
@ -395,13 +396,13 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
|
||||
"proposalDisplay.requestedBsqTextField must not be null");
|
||||
return daoFacade.getCompensationProposalWithTransaction(name,
|
||||
link,
|
||||
bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText()));
|
||||
ParsingUtils.parseToCoin(proposalDisplay.requestedBsqTextField.getText(), bsqFormatter));
|
||||
case REIMBURSEMENT_REQUEST:
|
||||
checkNotNull(proposalDisplay.requestedBsqTextField,
|
||||
"proposalDisplay.requestedBsqTextField must not be null");
|
||||
return daoFacade.getReimbursementProposalWithTransaction(name,
|
||||
link,
|
||||
bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText()));
|
||||
ParsingUtils.parseToCoin(proposalDisplay.requestedBsqTextField.getText(), bsqFormatter));
|
||||
case CHANGE_PARAM:
|
||||
checkNotNull(proposalDisplay.paramComboBox,
|
||||
"proposalDisplay.paramComboBox must not be null");
|
||||
|
@ -30,6 +30,7 @@ import bisq.desktop.components.TxIdTextField;
|
||||
import bisq.desktop.main.dao.governance.PhasesView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.SelectProposalWindow;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
import bisq.desktop.util.validation.BsqValidator;
|
||||
@ -54,6 +55,7 @@ import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.DevEnv;
|
||||
@ -462,7 +464,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
||||
}
|
||||
|
||||
private void onVote() {
|
||||
Coin stake = bsqFormatter.parseToCoin(stakeInputTextField.getText());
|
||||
Coin stake = ParsingUtils.parseToCoin(stakeInputTextField.getText(), bsqFormatter);
|
||||
try {
|
||||
// We create a dummy tx to get the miningFee for displaying it at the confirmation popup
|
||||
Tuple2<Coin, Integer> miningFeeAndTxSize = daoFacade.getBlindVoteMiningFeeAndTxSize(stake);
|
||||
@ -718,7 +720,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
||||
public void updateItem(final ProposalsListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(bsqFormatter.formatDateTime(item.getProposal().getCreationDateAsDate()));
|
||||
setText(DisplayUtils.formatDateTime(item.getProposal().getCreationDateAsDate()));
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import bisq.desktop.components.TableGroupHeadline;
|
||||
import bisq.desktop.main.dao.governance.PhasesView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.ProposalResultsWindow;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
@ -637,7 +638,7 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
||||
public void updateItem(final ProposalListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(bsqFormatter.formatDateTime(item.getProposal().getCreationDateAsDate()));
|
||||
setText(DisplayUtils.formatDateTime(item.getProposal().getCreationDateAsDate()));
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ import bisq.core.locale.Res;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
import bisq.core.util.CoinUtil;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
import bisq.core.util.validation.BtcAddressValidator;
|
||||
|
||||
import bisq.network.p2p.P2PService;
|
||||
@ -234,7 +235,7 @@ public class BsqSendView extends ActivatableView<GridPane, Void> implements BsqB
|
||||
// TODO break up in methods
|
||||
if (GUIUtil.isReadyForTxBroadcastOrShowPopup(p2PService, walletsSetup)) {
|
||||
String receiversAddressString = bsqFormatter.getAddressFromBsqAddress(receiversAddressInputTextField.getText()).toString();
|
||||
Coin receiverAmount = bsqFormatter.parseToCoin(amountInputTextField.getText());
|
||||
Coin receiverAmount = ParsingUtils.parseToCoin(amountInputTextField.getText(), bsqFormatter);
|
||||
try {
|
||||
Transaction preparedSendTx = bsqWalletService.getPreparedSendBsqTx(receiversAddressString, receiverAmount);
|
||||
Transaction txWithBtcFee = btcWalletService.completePreparedSendBsqTx(preparedSendTx, true);
|
||||
|
@ -24,6 +24,7 @@ import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.main.dao.wallet.BsqBalanceUtil;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
@ -367,7 +368,7 @@ public class BsqTxView extends ActivatableView<GridPane, Void> implements BsqBal
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
setText(bsqFormatter.formatDateTime(item.getDate()));
|
||||
setText(DisplayUtils.formatDateTime(item.getDate()));
|
||||
} else {
|
||||
setText("");
|
||||
}
|
||||
@ -630,7 +631,7 @@ public class BsqTxView extends ActivatableView<GridPane, Void> implements BsqBal
|
||||
style = "dao-tx-type-issuance-icon";
|
||||
int issuanceBlockHeight = daoFacade.getIssuanceBlockHeight(txId);
|
||||
long blockTime = daoFacade.getBlockTime(issuanceBlockHeight);
|
||||
String formattedDate = bsqFormatter.formatDateTime(new Date(blockTime));
|
||||
String formattedDate = DisplayUtils.formatDateTime(new Date(blockTime));
|
||||
toolTipText = Res.get("dao.tx.issuanceFromCompReq.tooltip", formattedDate);
|
||||
} else {
|
||||
awesomeIcon = AwesomeIcon.FILE_TEXT;
|
||||
@ -644,7 +645,7 @@ public class BsqTxView extends ActivatableView<GridPane, Void> implements BsqBal
|
||||
style = "dao-tx-type-issuance-icon";
|
||||
int issuanceBlockHeight = daoFacade.getIssuanceBlockHeight(txId);
|
||||
long blockTime = daoFacade.getBlockTime(issuanceBlockHeight);
|
||||
String formattedDate = bsqFormatter.formatDateTime(new Date(blockTime));
|
||||
String formattedDate = DisplayUtils.formatDateTime(new Date(blockTime));
|
||||
toolTipText = Res.get("dao.tx.issuanceFromReimbursement.tooltip", formattedDate);
|
||||
} else {
|
||||
awesomeIcon = AwesomeIcon.FILE_TEXT;
|
||||
|
@ -36,6 +36,7 @@ import bisq.core.locale.Res;
|
||||
import bisq.core.provider.fee.FeeService;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.DevEnv;
|
||||
@ -232,7 +233,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
||||
|
||||
walletService.addBalanceListener(balanceListener);
|
||||
amountTextFieldSubscription = EasyBind.subscribe(amountTextField.textProperty(), t -> {
|
||||
addressTextField.setAmountAsCoin(formatter.parseToCoin(t));
|
||||
addressTextField.setAmountAsCoin(ParsingUtils.parseToCoin(t, formatter));
|
||||
updateQRCode();
|
||||
});
|
||||
|
||||
@ -301,7 +302,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
||||
}
|
||||
|
||||
private Coin getAmountAsCoin() {
|
||||
return formatter.parseToCoin(amountTextField.getText());
|
||||
return ParsingUtils.parseToCoin(amountTextField.getText(), formatter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -23,6 +23,7 @@ import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.main.overlays.windows.OfferDetailsWindow;
|
||||
import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.btc.listeners.BalanceListener;
|
||||
@ -228,7 +229,7 @@ public class LockedView extends ActivatableView<VBox, Void> {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
if (getTradable(item).isPresent())
|
||||
setGraphic(new AutoTooltipLabel(formatter.formatDateTime(getTradable(item).get().getDate())));
|
||||
setGraphic(new AutoTooltipLabel(DisplayUtils.formatDateTime(getTradable(item).get().getDate())));
|
||||
else
|
||||
setGraphic(new AutoTooltipLabel(Res.get("shared.noDateAvailable")));
|
||||
} else {
|
||||
|
@ -23,6 +23,7 @@ import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.main.overlays.windows.OfferDetailsWindow;
|
||||
import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.btc.listeners.BalanceListener;
|
||||
@ -228,7 +229,7 @@ public class ReservedView extends ActivatableView<VBox, Void> {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
if (getTradable(item).isPresent())
|
||||
setGraphic(new AutoTooltipLabel(formatter.formatDateTime(getTradable(item).get().getDate())));
|
||||
setGraphic(new AutoTooltipLabel(DisplayUtils.formatDateTime(getTradable(item).get().getDate())));
|
||||
else
|
||||
setGraphic(new AutoTooltipLabel(Res.get("shared.noDateAvailable")));
|
||||
} else {
|
||||
|
@ -18,6 +18,7 @@
|
||||
package bisq.desktop.main.funds.transactions;
|
||||
|
||||
import bisq.desktop.components.indicator.TxConfidenceIndicator;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.btc.listeners.TxConfidenceListener;
|
||||
@ -239,7 +240,7 @@ class TransactionsListItem {
|
||||
}
|
||||
// Use tx.getIncludedInBestChainAt() when available, otherwise use tx.getUpdateTime()
|
||||
date = transaction.getIncludedInBestChainAt() != null ? transaction.getIncludedInBestChainAt() : transaction.getUpdateTime();
|
||||
dateString = formatter.formatDateTime(date);
|
||||
dateString = DisplayUtils.formatDateTime(date);
|
||||
|
||||
isDustAttackTx = received && valueSentToMe.value < ignoreDustThreshold;
|
||||
if (isDustAttackTx) {
|
||||
|
@ -41,6 +41,7 @@ import bisq.core.trade.TradeManager;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.CoinUtil;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
import bisq.core.util.validation.BtcAddressValidator;
|
||||
|
||||
import bisq.network.p2p.P2PService;
|
||||
@ -246,7 +247,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
|
||||
amountListener = (observable, oldValue, newValue) -> {
|
||||
if (amountTextField.focusedProperty().get()) {
|
||||
try {
|
||||
amountAsCoin = formatter.parseToCoin(amountTextField.getText());
|
||||
amountAsCoin = ParsingUtils.parseToCoin(amountTextField.getText(), formatter);
|
||||
} catch (Throwable t) {
|
||||
log.error("Error at amountTextField input. " + t.toString());
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import bisq.desktop.main.market.trades.TradesChartsView;
|
||||
import bisq.desktop.main.offer.offerbook.OfferBook;
|
||||
import bisq.desktop.main.offer.offerbook.OfferBookListItem;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
@ -183,11 +184,11 @@ public class MarketView extends ActivatableViewAndModel<TabPane, Activatable> {
|
||||
.map(trade -> {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Trade ID: ").append(trade.getOfferId()).append("\n")
|
||||
.append("Date: ").append(formatter.formatDateTime(trade.getTradeDate())).append("\n")
|
||||
.append("Market: ").append(formatter.getCurrencyPair(trade.getCurrencyCode())).append("\n")
|
||||
.append("Price: ").append(formatter.formatPrice(trade.getTradePrice())).append("\n")
|
||||
.append("Date: ").append(DisplayUtils.formatDateTime(trade.getTradeDate())).append("\n")
|
||||
.append("Market: ").append(BSFormatter.getCurrencyPair(trade.getCurrencyCode())).append("\n")
|
||||
.append("Price: ").append(BSFormatter.formatPrice(trade.getTradePrice())).append("\n")
|
||||
.append("Amount: ").append(formatter.formatCoin(trade.getTradeAmount())).append("\n")
|
||||
.append("Volume: ").append(formatter.formatVolume(trade.getTradeVolume())).append("\n")
|
||||
.append("Volume: ").append(DisplayUtils.formatVolume(trade.getTradeVolume())).append("\n")
|
||||
.append("Payment method: ").append(Res.get(trade.getOfferPaymentMethod())).append("\n")
|
||||
.append("ReferralID: ").append(trade.getExtraDataMap().get(OfferPayload.REFERRAL_ID));
|
||||
return sb.toString();
|
||||
@ -205,9 +206,9 @@ public class MarketView extends ActivatableViewAndModel<TabPane, Activatable> {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Offer ID: ").append(offer.getId()).append("\n")
|
||||
.append("Type: ").append(offer.getDirection().name()).append("\n")
|
||||
.append("Market: ").append(formatter.getCurrencyPair(offer.getCurrencyCode())).append("\n")
|
||||
.append("Price: ").append(formatter.formatPrice(offer.getPrice())).append("\n")
|
||||
.append("Amount: ").append(formatter.formatAmount(offer)).append(" BTC\n")
|
||||
.append("Market: ").append(BSFormatter.getCurrencyPair(offer.getCurrencyCode())).append("\n")
|
||||
.append("Price: ").append(BSFormatter.formatPrice(offer.getPrice())).append("\n")
|
||||
.append("Amount: ").append(DisplayUtils.formatAmount(offer, formatter)).append(" BTC\n")
|
||||
.append("Payment method: ").append(Res.get(offer.getPaymentMethod().getId())).append("\n")
|
||||
.append("ReferralID: ").append(offer.getOfferPayload().getExtraDataMap().get(OfferPayload.REFERRAL_ID));
|
||||
return sb.toString();
|
||||
|
@ -223,15 +223,15 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||
public String toString(Number object) {
|
||||
final double doubleValue = (double) object;
|
||||
if (CurrencyUtil.isCryptoCurrency(model.getCurrencyCode())) {
|
||||
final String withCryptoPrecision = formatter.formatRoundedDoubleWithPrecision(doubleValue, cryptoPrecision);
|
||||
final String withCryptoPrecision = BSFormatter.formatRoundedDoubleWithPrecision(doubleValue, cryptoPrecision);
|
||||
if (withCryptoPrecision.equals("0.000")) {
|
||||
cryptoPrecision = 8;
|
||||
return formatter.formatRoundedDoubleWithPrecision(doubleValue, cryptoPrecision);
|
||||
return BSFormatter.formatRoundedDoubleWithPrecision(doubleValue, cryptoPrecision);
|
||||
} else {
|
||||
return withCryptoPrecision;
|
||||
}
|
||||
} else {
|
||||
return formatter.formatRoundedDoubleWithPrecision(doubleValue, 2);
|
||||
return BSFormatter.formatRoundedDoubleWithPrecision(doubleValue, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +268,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||
|
||||
priceColumnLabel.set(Res.get("shared.priceWithCur", code));
|
||||
}
|
||||
xAxis.setLabel(formatter.getPriceWithCurrencyCode(code));
|
||||
xAxis.setLabel(BSFormatter.getPriceWithCurrencyCode(code));
|
||||
|
||||
seriesBuy.setName(leftHeaderLabel.getText() + " ");
|
||||
seriesSell.setName(rightHeaderLabel.getText());
|
||||
|
@ -26,6 +26,7 @@ import bisq.desktop.main.settings.SettingsView;
|
||||
import bisq.desktop.main.settings.preferences.PreferencesView;
|
||||
import bisq.desktop.util.CurrencyList;
|
||||
import bisq.desktop.util.CurrencyListItem;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
@ -254,7 +255,7 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
||||
}
|
||||
|
||||
private String formatPrice(Offer offer, boolean decimalAligned) {
|
||||
return formatter.formatPrice(offer.getPrice(), decimalAligned, offer.isBuyOffer() ? maxPlacesForBuyPrice.get() : maxPlacesForSellPrice.get());
|
||||
return DisplayUtils.formatPrice(offer.getPrice(), decimalAligned, offer.isBuyOffer() ? maxPlacesForBuyPrice.get() : maxPlacesForSellPrice.get());
|
||||
}
|
||||
|
||||
public String getVolume(Offer offer) {
|
||||
@ -262,7 +263,7 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
||||
}
|
||||
|
||||
private String formatVolume(Offer offer, boolean decimalAligned) {
|
||||
return formatter.formatVolume(offer, decimalAligned, offer.isBuyOffer() ? maxPlacesForBuyVolume.get() : maxPlacesForSellVolume.get(), false);
|
||||
return DisplayUtils.formatVolume(offer, decimalAligned, offer.isBuyOffer() ? maxPlacesForBuyVolume.get() : maxPlacesForSellVolume.get(), false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -185,7 +185,7 @@ class SpreadViewModel extends ActivatableViewModel {
|
||||
.multiply(BigDecimal.valueOf(10000))
|
||||
.divide(marketPriceAsBigDecimal, RoundingMode.HALF_UP)
|
||||
.doubleValue() / 10000;
|
||||
percentage = formatter.formatPercentagePrice(percentageValue);
|
||||
percentage = BSFormatter.formatPercentagePrice(percentageValue);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
|
@ -27,6 +27,7 @@ import bisq.desktop.components.ColoredDecimalPlacesWithZerosText;
|
||||
import bisq.desktop.main.market.trades.charts.price.CandleStickChart;
|
||||
import bisq.desktop.main.market.trades.charts.volume.VolumeChart;
|
||||
import bisq.desktop.util.CurrencyListItem;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
@ -239,7 +240,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
String code = selectedTradeCurrency.getCode();
|
||||
volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountWithCur", code)));
|
||||
|
||||
priceColumnLabel.set(formatter.getPriceWithCurrencyCode(code));
|
||||
priceColumnLabel.set(BSFormatter.getPriceWithCurrencyCode(code));
|
||||
|
||||
tableView.getColumns().remove(marketColumn);
|
||||
}
|
||||
@ -345,9 +346,9 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
double doubleValue = (double) object;
|
||||
if (CurrencyUtil.isCryptoCurrency(currencyCode)) {
|
||||
final double value = MathUtils.scaleDownByPowerOf10(doubleValue, 8);
|
||||
return formatter.formatRoundedDoubleWithPrecision(value, 8);
|
||||
return BSFormatter.formatRoundedDoubleWithPrecision(value, 8);
|
||||
} else {
|
||||
return formatter.formatPrice(Price.valueOf(currencyCode, MathUtils.doubleToLong(doubleValue)));
|
||||
return BSFormatter.formatPrice(Price.valueOf(currencyCode, MathUtils.doubleToLong(doubleValue)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,9 +363,9 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
public String toString(Number object) {
|
||||
if (CurrencyUtil.isCryptoCurrency(model.getCurrencyCode())) {
|
||||
final double value = MathUtils.scaleDownByPowerOf10((long) object, 8);
|
||||
return formatter.formatRoundedDoubleWithPrecision(value, 8);
|
||||
return BSFormatter.formatRoundedDoubleWithPrecision(value, 8);
|
||||
} else {
|
||||
return formatter.formatPrice(Price.valueOf(model.getCurrencyCode(), (long) object));
|
||||
return BSFormatter.formatPrice(Price.valueOf(model.getCurrencyCode(), (long) object));
|
||||
}
|
||||
}
|
||||
|
||||
@ -480,9 +481,9 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
long index = MathUtils.doubleToLong((double) object);
|
||||
long time = model.getTimeFromTickIndex(index);
|
||||
if (model.tickUnit.ordinal() <= TradesChartsViewModel.TickUnit.DAY.ordinal())
|
||||
return index % 4 == 0 ? formatter.formatDate(new Date(time)) : "";
|
||||
return index % 4 == 0 ? DisplayUtils.formatDate(new Date(time)) : "";
|
||||
else
|
||||
return index % 3 == 0 ? formatter.formatTime(new Date(time)) : "";
|
||||
return index % 3 == 0 ? DisplayUtils.formatTime(new Date(time)) : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -568,7 +569,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
public void updateItem(final TradeStatistics2 item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(formatter.formatDateTime(item.getTradeDate()));
|
||||
setText(DisplayUtils.formatDateTime(item.getTradeDate()));
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
@ -597,7 +598,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
public void updateItem(final TradeStatistics2 item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(formatter.getCurrencyPair(item.getCurrencyCode()));
|
||||
setText(BSFormatter.getCurrencyPair(item.getCurrencyCode()));
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
@ -621,7 +622,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
public void updateItem(final TradeStatistics2 item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(formatter.formatPrice(item.getTradePrice()));
|
||||
setText(BSFormatter.formatPrice(item.getTradePrice()));
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
@ -671,8 +672,8 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(model.showAllTradeCurrenciesProperty.get() ?
|
||||
formatter.formatVolumeWithCode(item.getTradeVolume()) :
|
||||
formatter.formatVolume(item.getTradeVolume()));
|
||||
DisplayUtils.formatVolumeWithCode(item.getTradeVolume()) :
|
||||
DisplayUtils.formatVolume(item.getTradeVolume()));
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
@ -744,7 +745,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||
|
||||
@NotNull
|
||||
private String getDirectionLabel(TradeStatistics2 item) {
|
||||
return formatter.getDirectionWithCode(OfferPayload.Direction.valueOf(item.getDirection().name()), item.getCurrencyCode());
|
||||
return DisplayUtils.getDirectionWithCode(OfferPayload.Direction.valueOf(item.getDirection().name()), item.getCurrencyCode());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -25,6 +25,7 @@ import bisq.desktop.main.settings.SettingsView;
|
||||
import bisq.desktop.main.settings.preferences.PreferencesView;
|
||||
import bisq.desktop.util.CurrencyList;
|
||||
import bisq.desktop.util.CurrencyListItem;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.locale.CryptoCurrency;
|
||||
@ -345,8 +346,8 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
||||
final Date dateFrom = new Date(getTimeFromTickIndex(tick));
|
||||
final Date dateTo = new Date(getTimeFromTickIndex(tick + 1));
|
||||
String dateString = tickUnit.ordinal() > TickUnit.DAY.ordinal() ?
|
||||
formatter.formatDateTimeSpan(dateFrom, dateTo) :
|
||||
formatter.formatDate(dateFrom) + " - " + formatter.formatDate(dateTo);
|
||||
DisplayUtils.formatDateTimeSpan(dateFrom, dateTo) :
|
||||
DisplayUtils.formatDate(dateFrom) + " - " + DisplayUtils.formatDate(dateTo);
|
||||
return new CandleData(tick, open, close, high, low, averagePrice, medianPrice, accumulatedAmount, accumulatedVolume,
|
||||
numTrades, isBullish, dateString);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
package bisq.desktop.main.offer;
|
||||
|
||||
import bisq.desktop.Navigation;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeRestrictions;
|
||||
@ -642,7 +643,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
|
||||
!price.get().isZero() &&
|
||||
allowAmountUpdate) {
|
||||
try {
|
||||
Coin value = btcFormatter.reduceTo4Decimals(price.get().getAmountByVolume(volume.get()));
|
||||
Coin value = DisplayUtils.reduceTo4Decimals(price.get().getAmountByVolume(volume.get()), btcFormatter);
|
||||
if (isHalCashAccount())
|
||||
value = OfferUtil.getAdjustedAmountForHalCash(value, price.get(), getMaxTradeLimit());
|
||||
else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get()))
|
||||
|
@ -565,11 +565,11 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel> extends
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void addBindings() {
|
||||
priceCurrencyLabel.textProperty().bind(createStringBinding(() -> btcFormatter.getCounterCurrency(model.tradeCurrencyCode.get()), model.tradeCurrencyCode));
|
||||
priceCurrencyLabel.textProperty().bind(createStringBinding(() -> BSFormatter.getCounterCurrency(model.tradeCurrencyCode.get()), model.tradeCurrencyCode));
|
||||
|
||||
marketBasedPriceLabel.prefWidthProperty().bind(priceCurrencyLabel.widthProperty());
|
||||
volumeCurrencyLabel.textProperty().bind(model.tradeCurrencyCode);
|
||||
priceDescriptionLabel.textProperty().bind(createStringBinding(() -> btcFormatter.getPriceWithCurrencyCode(model.tradeCurrencyCode.get(), "shared.fixedPriceInCurForCur"), model.tradeCurrencyCode));
|
||||
priceDescriptionLabel.textProperty().bind(createStringBinding(() -> BSFormatter.getPriceWithCurrencyCode(model.tradeCurrencyCode.get(), "shared.fixedPriceInCurForCur"), model.tradeCurrencyCode));
|
||||
volumeDescriptionLabel.textProperty().bind(createStringBinding(model.volumeDescriptionLabel::get, model.tradeCurrencyCode, model.volumeDescriptionLabel));
|
||||
amountTextField.textProperty().bindBidirectional(model.amount);
|
||||
minAmountTextField.textProperty().bindBidirectional(model.minAmount);
|
||||
|
@ -25,6 +25,7 @@ import bisq.desktop.main.funds.deposit.DepositView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.settings.SettingsView;
|
||||
import bisq.desktop.main.settings.preferences.PreferencesView;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.validation.AltcoinValidator;
|
||||
import bisq.desktop.util.validation.BsqValidator;
|
||||
@ -51,6 +52,7 @@ import bisq.core.provider.price.PriceFeedService;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
import bisq.core.util.validation.InputValidator;
|
||||
|
||||
import bisq.common.Timer;
|
||||
@ -306,7 +308,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
if (marketPrice != null && marketPrice.isRecentExternalPriceAvailable()) {
|
||||
double marketPriceAsDouble = marketPrice.getPrice();
|
||||
try {
|
||||
double priceAsDouble = btcFormatter.parseNumberStringToDouble(price.get());
|
||||
double priceAsDouble = ParsingUtils.parseNumberStringToDouble(price.get());
|
||||
double relation = priceAsDouble / marketPriceAsDouble;
|
||||
final OfferPayload.Direction compareDirection = CurrencyUtil.isCryptoCurrency(currencyCode) ?
|
||||
OfferPayload.Direction.SELL :
|
||||
@ -314,7 +316,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
double percentage = dataModel.getDirection() == compareDirection ? 1 - relation : relation - 1;
|
||||
percentage = MathUtils.roundDouble(percentage, 4);
|
||||
dataModel.setMarketPriceMargin(percentage);
|
||||
marketPriceMargin.set(btcFormatter.formatToPercent(percentage));
|
||||
marketPriceMargin.set(BSFormatter.formatToPercent(percentage));
|
||||
applyMakerFee();
|
||||
} catch (NumberFormatException t) {
|
||||
marketPriceMargin.set("");
|
||||
@ -332,7 +334,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
if (inputIsMarketBasedPrice) {
|
||||
try {
|
||||
if (!newValue.isEmpty() && !newValue.equals("-")) {
|
||||
double percentage = btcFormatter.parsePercentStringToDouble(newValue);
|
||||
double percentage = ParsingUtils.parsePercentStringToDouble(newValue);
|
||||
if (percentage >= 1 || percentage <= -1) {
|
||||
new Popup<>().warning(Res.get("popup.warning.tooLargePercentageValue") + "\n" +
|
||||
Res.get("popup.warning.examplePercentageValue"))
|
||||
@ -355,7 +357,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
Altcoin.SMALLEST_UNIT_EXPONENT : Fiat.SMALLEST_UNIT_EXPONENT;
|
||||
// protect from triggering unwanted updates
|
||||
ignorePriceStringListener = true;
|
||||
price.set(btcFormatter.formatRoundedDoubleWithPrecision(targetPrice, precision));
|
||||
price.set(BSFormatter.formatRoundedDoubleWithPrecision(targetPrice, precision));
|
||||
ignorePriceStringListener = false;
|
||||
setPriceToModel();
|
||||
dataModel.setMarketPriceMargin(percentage);
|
||||
@ -432,7 +434,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
priceListener = (ov, oldValue, newValue) -> {
|
||||
ignorePriceStringListener = true;
|
||||
if (newValue != null)
|
||||
price.set(btcFormatter.formatPrice(newValue));
|
||||
price.set(BSFormatter.formatPrice(newValue));
|
||||
else
|
||||
price.set("");
|
||||
|
||||
@ -442,7 +444,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
volumeListener = (ov, oldValue, newValue) -> {
|
||||
ignoreVolumeStringListener = true;
|
||||
if (newValue != null)
|
||||
volume.set(btcFormatter.formatVolume(newValue));
|
||||
volume.set(DisplayUtils.formatVolume(newValue));
|
||||
else
|
||||
volume.set("");
|
||||
|
||||
@ -452,7 +454,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
securityDepositAsDoubleListener = (ov, oldValue, newValue) -> {
|
||||
if (newValue != null) {
|
||||
buyerSecurityDeposit.set(btcFormatter.formatToPercent((double) newValue));
|
||||
buyerSecurityDeposit.set(BSFormatter.formatToPercent((double) newValue));
|
||||
if (dataModel.getAmount().get() != null)
|
||||
buyerSecurityDepositInBTC.set(btcFormatter.formatCoinWithCode(dataModel.getBuyerSecurityDepositAsCoin()));
|
||||
} else {
|
||||
@ -483,7 +485,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
Coin makerFeeInBtc = dataModel.getMakerFeeInBtc();
|
||||
Optional<Volume> optionalBtcFeeInFiat = OfferUtil.getFeeInUserFiatCurrency(makerFeeInBtc,
|
||||
true, preferences, priceFeedService, bsqFormatter);
|
||||
String btcFeeWithFiatAmount = OfferUtil.getFeeWithFiatAmount(makerFeeInBtc, optionalBtcFeeInFiat, btcFormatter);
|
||||
String btcFeeWithFiatAmount = DisplayUtils.getFeeWithFiatAmount(makerFeeInBtc, optionalBtcFeeInFiat, btcFormatter);
|
||||
if (DevEnv.isDaoActivated()) {
|
||||
tradeFeeInBtcWithFiat.set(btcFeeWithFiatAmount);
|
||||
} else {
|
||||
@ -493,14 +495,14 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
Coin makerFeeInBsq = dataModel.getMakerFeeInBsq();
|
||||
Optional<Volume> optionalBsqFeeInFiat = OfferUtil.getFeeInUserFiatCurrency(makerFeeInBsq,
|
||||
false, preferences, priceFeedService, bsqFormatter);
|
||||
String bsqFeeWithFiatAmount = OfferUtil.getFeeWithFiatAmount(makerFeeInBsq, optionalBsqFeeInFiat, bsqFormatter);
|
||||
String bsqFeeWithFiatAmount = DisplayUtils.getFeeWithFiatAmount(makerFeeInBsq, optionalBsqFeeInFiat, bsqFormatter);
|
||||
if (DevEnv.isDaoActivated()) {
|
||||
tradeFeeInBsqWithFiat.set(bsqFeeWithFiatAmount);
|
||||
} else {
|
||||
// Before DAO is enabled we show fee as fiat and % in second line
|
||||
String feeInFiatAsString;
|
||||
if (optionalBtcFeeInFiat != null && optionalBtcFeeInFiat.isPresent()) {
|
||||
feeInFiatAsString = btcFormatter.formatVolumeWithCode(optionalBtcFeeInFiat.get());
|
||||
feeInFiatAsString = DisplayUtils.formatVolumeWithCode(optionalBtcFeeInFiat.get());
|
||||
} else {
|
||||
feeInFiatAsString = Res.get("shared.na");
|
||||
}
|
||||
@ -511,7 +513,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
tradeFeeInBsqWithFiat.set(Res.get("createOffer.tradeFee.fiatAndPercent",
|
||||
feeInFiatAsString,
|
||||
btcFormatter.formatToPercentWithSymbol(percent)));
|
||||
BSFormatter.formatToPercentWithSymbol(percent)));
|
||||
}
|
||||
}
|
||||
tradeFeeCurrencyCode.set(dataModel.isCurrencyForMakerFeeBtc() ? Res.getBaseCurrencyCode() : "BSQ");
|
||||
@ -592,7 +594,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
isBuy ? Res.get("shared.buy") : Res.get("shared.sell"));
|
||||
|
||||
securityDepositValidator.setPaymentAccount(dataModel.paymentAccount);
|
||||
buyerSecurityDeposit.set(btcFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
|
||||
buyerSecurityDeposit.set(BSFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
|
||||
buyerSecurityDepositLabel.set(getSecurityDepositLabel());
|
||||
|
||||
applyMakerFee();
|
||||
@ -748,7 +750,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
if (dataModel.getMinVolume().get() != null) {
|
||||
InputValidator.ValidationResult minVolumeResult = isVolumeInputValid(
|
||||
btcFormatter.formatVolume(dataModel.getMinVolume().get()));
|
||||
DisplayUtils.formatVolume(dataModel.getMinVolume().get()));
|
||||
|
||||
volumeValidationResult.set(minVolumeResult);
|
||||
|
||||
@ -779,7 +781,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
setPriceToModel();
|
||||
ignorePriceStringListener = true;
|
||||
if (dataModel.getPrice().get() != null)
|
||||
price.set(btcFormatter.formatPrice(dataModel.getPrice().get()));
|
||||
price.set(BSFormatter.formatPrice(dataModel.getPrice().get()));
|
||||
ignorePriceStringListener = false;
|
||||
dataModel.calculateVolume();
|
||||
dataModel.calculateAmount();
|
||||
@ -803,7 +805,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
// field wasn't set manually
|
||||
inputIsMarketBasedPrice = true;
|
||||
}
|
||||
marketPriceMargin.set(btcFormatter.formatRoundedDoubleWithPrecision(dataModel.getMarketPriceMargin() * 100, 2));
|
||||
marketPriceMargin.set(BSFormatter.formatRoundedDoubleWithPrecision(dataModel.getMarketPriceMargin() * 100, 2));
|
||||
|
||||
// We want to trigger a recalculation of the volume
|
||||
UserThread.execute(() -> {
|
||||
@ -827,7 +829,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get()))
|
||||
volume = OfferUtil.getRoundedFiatVolume(volume);
|
||||
|
||||
this.volume.set(btcFormatter.formatVolume(volume));
|
||||
this.volume.set(DisplayUtils.formatVolume(volume));
|
||||
}
|
||||
|
||||
ignoreVolumeStringListener = false;
|
||||
@ -856,20 +858,20 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
if (result.isValid) {
|
||||
double defaultSecurityDeposit = Restrictions.getDefaultBuyerSecurityDepositAsPercent(getPaymentAccount());
|
||||
String key = "buyerSecurityDepositIsLowerAsDefault";
|
||||
double depositAsDouble = btcFormatter.parsePercentStringToDouble(buyerSecurityDeposit.get());
|
||||
double depositAsDouble = ParsingUtils.parsePercentStringToDouble(buyerSecurityDeposit.get());
|
||||
if (preferences.showAgain(key) && depositAsDouble < defaultSecurityDeposit) {
|
||||
String postfix = dataModel.isBuyOffer() ?
|
||||
Res.get("createOffer.tooLowSecDeposit.makerIsBuyer") :
|
||||
Res.get("createOffer.tooLowSecDeposit.makerIsSeller");
|
||||
new Popup<>()
|
||||
.warning(Res.get("createOffer.tooLowSecDeposit.warning",
|
||||
btcFormatter.formatToPercentWithSymbol(defaultSecurityDeposit)) + "\n\n" + postfix)
|
||||
BSFormatter.formatToPercentWithSymbol(defaultSecurityDeposit)) + "\n\n" + postfix)
|
||||
.width(800)
|
||||
.actionButtonText(Res.get("createOffer.resetToDefault"))
|
||||
.onAction(() -> {
|
||||
dataModel.setBuyerSecurityDeposit(defaultSecurityDeposit);
|
||||
ignoreSecurityDepositStringListener = true;
|
||||
buyerSecurityDeposit.set(btcFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
|
||||
buyerSecurityDeposit.set(BSFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
|
||||
ignoreSecurityDepositStringListener = false;
|
||||
})
|
||||
.closeButtonText(Res.get("createOffer.useLowerValue"))
|
||||
@ -886,7 +888,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
private void applyBuyerSecurityDepositOnFocusOut() {
|
||||
setBuyerSecurityDepositToModel();
|
||||
ignoreSecurityDepositStringListener = true;
|
||||
buyerSecurityDeposit.set(btcFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
|
||||
buyerSecurityDeposit.set(BSFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
|
||||
ignoreSecurityDepositStringListener = false;
|
||||
}
|
||||
|
||||
@ -896,7 +898,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
public boolean isPriceInRange() {
|
||||
if (marketPriceMargin.get() != null && !marketPriceMargin.get().isEmpty()) {
|
||||
if (Math.abs(btcFormatter.parsePercentStringToDouble(marketPriceMargin.get())) > preferences.getMaxPriceDistanceInPercent()) {
|
||||
if (Math.abs(ParsingUtils.parsePercentStringToDouble(marketPriceMargin.get())) > preferences.getMaxPriceDistanceInPercent()) {
|
||||
displayPriceOutOfRangePopup();
|
||||
return false;
|
||||
} else {
|
||||
@ -910,7 +912,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
private void displayPriceOutOfRangePopup() {
|
||||
Popup popup = new Popup<>();
|
||||
popup.warning(Res.get("createOffer.priceOutSideOfDeviation",
|
||||
btcFormatter.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent())))
|
||||
BSFormatter.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent())))
|
||||
.actionButtonText(Res.get("createOffer.changePrice"))
|
||||
.onAction(popup::hide)
|
||||
.closeButtonTextWithGoTo("navigation.settings.preferences")
|
||||
@ -1042,7 +1044,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
private void setAmountToModel() {
|
||||
if (amount.get() != null && !amount.get().isEmpty()) {
|
||||
Coin amount = btcFormatter.parseToCoinWith4Decimals(this.amount.get());
|
||||
Coin amount = DisplayUtils.parseToCoinWith4Decimals(this.amount.get(), btcFormatter);
|
||||
|
||||
long maxTradeLimit = dataModel.getMaxTradeLimit();
|
||||
Price price = dataModel.getPrice().get();
|
||||
@ -1066,7 +1068,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
private void setMinAmountToModel() {
|
||||
if (minAmount.get() != null && !minAmount.get().isEmpty()) {
|
||||
Coin minAmount = btcFormatter.parseToCoinWith4Decimals(this.minAmount.get());
|
||||
Coin minAmount = DisplayUtils.parseToCoinWith4Decimals(this.minAmount.get(), btcFormatter);
|
||||
|
||||
Price price = dataModel.getPrice().get();
|
||||
long maxTradeLimit = dataModel.getMaxTradeLimit();
|
||||
@ -1109,7 +1111,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
private void setBuyerSecurityDepositToModel() {
|
||||
if (buyerSecurityDeposit.get() != null && !buyerSecurityDeposit.get().isEmpty()) {
|
||||
dataModel.setBuyerSecurityDeposit(btcFormatter.parsePercentStringToDouble(buyerSecurityDeposit.get()));
|
||||
dataModel.setBuyerSecurityDeposit(ParsingUtils.parsePercentStringToDouble(buyerSecurityDeposit.get()));
|
||||
} else {
|
||||
dataModel.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent(getPaymentAccount()));
|
||||
}
|
||||
@ -1168,7 +1170,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
dataModel.getPrice().get() != null &&
|
||||
dataModel.getPrice().get().getValue() != 0 &&
|
||||
isVolumeInputValid(volume.get()).isValid &&
|
||||
isVolumeInputValid(btcFormatter.formatVolume(dataModel.getMinVolume().get())).isValid &&
|
||||
isVolumeInputValid(DisplayUtils.formatVolume(dataModel.getMinVolume().get())).isValid &&
|
||||
dataModel.isMinAmountLessOrEqualAmount();
|
||||
|
||||
isNextButtonDisabled.set(!inputDataValid);
|
||||
@ -1187,4 +1189,5 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
private BSFormatter getFormatterForMakerFee() {
|
||||
return dataModel.isCurrencyForMakerFeeBtc() ? btcFormatter : bsqFormatter;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import bisq.desktop.main.funds.withdrawal.WithdrawalView;
|
||||
import bisq.desktop.main.offer.OfferView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.OfferDetailsWindow;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
@ -226,8 +227,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
tableView.setPlaceholder(placeholder);
|
||||
|
||||
marketColumn.setComparator((o1, o2) -> {
|
||||
String str1 = formatter.getCurrencyPair(o1.getOffer().getCurrencyCode());
|
||||
String str2 = formatter.getCurrencyPair(o2.getOffer().getCurrencyCode());
|
||||
String str1 = BSFormatter.getCurrencyPair(o1.getOffer().getCurrencyCode());
|
||||
String str2 = BSFormatter.getCurrencyPair(o2.getOffer().getCurrencyCode());
|
||||
return str1 != null && str2 != null ? str1.compareTo(str2) : 0;
|
||||
});
|
||||
priceColumn.setComparator((o1, o2) -> {
|
||||
@ -324,7 +325,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
tableView.getColumns().add(0, marketColumn);
|
||||
} else {
|
||||
volumeColumn.setTitleWithHelpText(Res.get("offerbook.volume", code), Res.get("shared.amountHelp"));
|
||||
priceColumn.setTitle(formatter.getPriceWithCurrencyCode(code));
|
||||
priceColumn.setTitle(BSFormatter.getPriceWithCurrencyCode(code));
|
||||
priceColumn.getStyleClass().add("first-column");
|
||||
|
||||
tableView.getColumns().remove(marketColumn);
|
||||
@ -570,7 +571,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
final long tradeLimit = model.accountAgeWitnessService.getMyTradeLimit(account.get(), offer.getCurrencyCode());
|
||||
new Popup<>()
|
||||
.warning(Res.get("offerbook.warning.tradeLimitNotMatching",
|
||||
formatter.formatAccountAge(model.accountAgeWitnessService.getMyAccountAge(account.get().getPaymentAccountPayload())),
|
||||
DisplayUtils.formatAccountAge(model.accountAgeWitnessService.getMyAccountAge(account.get().getPaymentAccountPayload())),
|
||||
formatter.formatCoinWithCode(Coin.valueOf(tradeLimit)),
|
||||
formatter.formatCoinWithCode(offer.getMinAmount())))
|
||||
.show();
|
||||
@ -687,7 +688,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty)
|
||||
setText(formatter.getCurrencyPair(item.getOffer().getCurrencyCode()));
|
||||
setText(BSFormatter.getCurrencyPair(item.getOffer().getCurrencyCode()));
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import bisq.desktop.common.model.ActivatableViewModel;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.settings.SettingsView;
|
||||
import bisq.desktop.main.settings.preferences.PreferencesView;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
@ -340,7 +341,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
}
|
||||
|
||||
private String formatAmount(Offer offer, boolean decimalAligned) {
|
||||
return formatter.formatAmount(offer, GUIUtil.AMOUNT_DECIMALS, decimalAligned, maxPlacesForAmount.get());
|
||||
return DisplayUtils.formatAmount(offer, GUIUtil.AMOUNT_DECIMALS, decimalAligned, maxPlacesForAmount.get(), formatter);
|
||||
}
|
||||
|
||||
|
||||
@ -358,22 +359,22 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
}
|
||||
|
||||
String getAbsolutePriceMargin(Offer offer) {
|
||||
return formatter.formatPercentagePrice(Math.abs(offer.getMarketPriceMargin()));
|
||||
return BSFormatter.formatPercentagePrice(Math.abs(offer.getMarketPriceMargin()));
|
||||
}
|
||||
|
||||
private String formatPrice(Offer offer, boolean decimalAligned) {
|
||||
return formatter.formatPrice(offer.getPrice(), decimalAligned, maxPlacesForPrice.get());
|
||||
return DisplayUtils.formatPrice(offer.getPrice(), decimalAligned, maxPlacesForPrice.get());
|
||||
}
|
||||
|
||||
private String formatMarketPriceMargin(Offer offer, boolean decimalAligned) {
|
||||
String postFix = "";
|
||||
if (offer.isUseMarketBasedPrice()) {
|
||||
postFix = " (" + formatter.formatPercentagePrice(offer.getMarketPriceMargin()) + ")";
|
||||
postFix = " (" + BSFormatter.formatPercentagePrice(offer.getMarketPriceMargin()) + ")";
|
||||
|
||||
}
|
||||
|
||||
if (decimalAligned) {
|
||||
postFix = formatter.fillUpPlacesWithEmptyStrings(postFix, maxPlacesForMarketPriceMargin.get());
|
||||
postFix = BSFormatter.fillUpPlacesWithEmptyStrings(postFix, maxPlacesForMarketPriceMargin.get());
|
||||
}
|
||||
|
||||
return postFix;
|
||||
@ -389,7 +390,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
if (offerVolume != null && minOfferVolume != null) {
|
||||
String postFix = showAllTradeCurrenciesProperty.get() ? " " + offer.getCurrencyCode() : "";
|
||||
decimalAligned = decimalAligned && !showAllTradeCurrenciesProperty.get();
|
||||
return formatter.formatVolume(offer, decimalAligned, maxPlacesForVolume.get()) + postFix;
|
||||
return DisplayUtils.formatVolume(offer, decimalAligned, maxPlacesForVolume.get()) + postFix;
|
||||
} else {
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
@ -470,7 +471,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
}
|
||||
|
||||
String getDirectionLabelTooltip(Offer offer) {
|
||||
return formatter.getDirectionWithCodeDetailed(offer.getMirroredDirection(), offer.getCurrencyCode());
|
||||
return BSFormatter.getDirectionWithCodeDetailed(offer.getMirroredDirection(), offer.getCurrencyCode());
|
||||
}
|
||||
|
||||
Optional<PaymentAccount> getMostMaturePaymentAccountForOffer(Offer offer) {
|
||||
|
@ -372,7 +372,7 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
feeTxSize = 380;
|
||||
txFeeFromFeeService = txFeePerByteFromFeeService.multiply(feeTxSize);
|
||||
log.info("We cannot do the fee estimation because there are no funds in the wallet.\nThis is expected " +
|
||||
"if the user has not funded his wallet yet.\n" +
|
||||
"if the user has not funded their wallet yet.\n" +
|
||||
"In that case we use an estimated tx size of 380 bytes.\n" +
|
||||
"txFee based on estimated size of {} bytes. feeTxSize = {} bytes. Actual tx size = {} bytes. TxFee is {} ({} sat/byte)",
|
||||
feeTxSize, feeTxSize, txSize, txFeeFromFeeService.toFriendlyString(), feeService.getTxFeePerByte());
|
||||
|
@ -278,7 +278,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
|
||||
String currencyCode = model.dataModel.getCurrencyCode();
|
||||
volumeCurrencyLabel.setText(currencyCode);
|
||||
priceDescriptionLabel.setText(formatter.getPriceWithCurrencyCode(currencyCode));
|
||||
priceDescriptionLabel.setText(BSFormatter.getPriceWithCurrencyCode(currencyCode));
|
||||
volumeDescriptionLabel.setText(model.volumeDescriptionLabel.get());
|
||||
|
||||
if (model.getPossiblePaymentAccounts().size() > 1) {
|
||||
@ -606,7 +606,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
totalToPayTextField.textProperty().bind(model.totalToPay);
|
||||
addressTextField.amountAsCoinProperty().bind(model.dataModel.getMissingCoin());
|
||||
amountTextField.validationResultProperty().bind(model.amountValidationResult);
|
||||
priceCurrencyLabel.textProperty().bind(createStringBinding(() -> formatter.getCounterCurrency(model.dataModel.getCurrencyCode())));
|
||||
priceCurrencyLabel.textProperty().bind(createStringBinding(() -> BSFormatter.getCounterCurrency(model.dataModel.getCurrencyCode())));
|
||||
priceAsPercentageLabel.prefWidthProperty().bind(priceCurrencyLabel.widthProperty());
|
||||
nextButton.disableProperty().bind(model.isNextButtonDisabled);
|
||||
tradeFeeInBtcLabel.textProperty().bind(model.tradeFeeInBtcWithFiat);
|
||||
|
@ -24,6 +24,7 @@ import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.funds.FundsView;
|
||||
import bisq.desktop.main.funds.deposit.DepositView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.validation.BtcValidator;
|
||||
|
||||
@ -205,8 +206,8 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
}
|
||||
|
||||
amountRange = btcFormatter.formatCoin(offer.getMinAmount()) + " - " + btcFormatter.formatCoin(offer.getAmount());
|
||||
price = btcFormatter.formatPrice(dataModel.tradePrice);
|
||||
marketPriceMargin = btcFormatter.formatToPercent(offer.getMarketPriceMargin());
|
||||
price = BSFormatter.formatPrice(dataModel.tradePrice);
|
||||
marketPriceMargin = BSFormatter.formatToPercent(offer.getMarketPriceMargin());
|
||||
paymentLabel = Res.get("takeOffer.fundsBox.paymentLabel", offer.getShortId());
|
||||
|
||||
checkNotNull(dataModel.getAddressEntry(), "dataModel.getAddressEntry() must not be null");
|
||||
@ -288,7 +289,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
Coin makerFeeInBtc = dataModel.getTakerFeeInBtc();
|
||||
Optional<Volume> optionalBtcFeeInFiat = OfferUtil.getFeeInUserFiatCurrency(makerFeeInBtc,
|
||||
true, preferences, priceFeedService, bsqFormatter);
|
||||
String btcFeeWithFiatAmount = OfferUtil.getFeeWithFiatAmount(makerFeeInBtc, optionalBtcFeeInFiat, btcFormatter);
|
||||
String btcFeeWithFiatAmount = DisplayUtils.getFeeWithFiatAmount(makerFeeInBtc, optionalBtcFeeInFiat, btcFormatter);
|
||||
if (DevEnv.isDaoActivated()) {
|
||||
tradeFeeInBtcWithFiat.set(btcFeeWithFiatAmount);
|
||||
} else {
|
||||
@ -298,14 +299,14 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
Coin makerFeeInBsq = dataModel.getTakerFeeInBsq();
|
||||
Optional<Volume> optionalBsqFeeInFiat = OfferUtil.getFeeInUserFiatCurrency(makerFeeInBsq,
|
||||
false, preferences, priceFeedService, bsqFormatter);
|
||||
String bsqFeeWithFiatAmount = OfferUtil.getFeeWithFiatAmount(makerFeeInBsq, optionalBsqFeeInFiat, bsqFormatter);
|
||||
String bsqFeeWithFiatAmount = DisplayUtils.getFeeWithFiatAmount(makerFeeInBsq, optionalBsqFeeInFiat, bsqFormatter);
|
||||
if (DevEnv.isDaoActivated()) {
|
||||
tradeFeeInBsqWithFiat.set(bsqFeeWithFiatAmount);
|
||||
} else {
|
||||
// Before DAO is enabled we show fee as fiat and % in second line
|
||||
String feeInFiatAsString;
|
||||
if (optionalBtcFeeInFiat != null && optionalBtcFeeInFiat.isPresent()) {
|
||||
feeInFiatAsString = btcFormatter.formatVolumeWithCode(optionalBtcFeeInFiat.get());
|
||||
feeInFiatAsString = DisplayUtils.formatVolumeWithCode(optionalBtcFeeInFiat.get());
|
||||
} else {
|
||||
feeInFiatAsString = Res.get("shared.na");
|
||||
}
|
||||
@ -316,7 +317,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
|
||||
tradeFeeInBsqWithFiat.set(Res.get("createOffer.tradeFee.fiatAndPercent",
|
||||
feeInFiatAsString,
|
||||
btcFormatter.formatToPercentWithSymbol(percent)));
|
||||
BSFormatter.formatToPercentWithSymbol(percent)));
|
||||
}
|
||||
}
|
||||
tradeFeeDescription.set(DevEnv.isDaoActivated() ? Res.get("createOffer.tradeFee.descriptionBSQEnabled") :
|
||||
@ -334,7 +335,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
InputValidator.ValidationResult result = isBtcInputValid(amount.get());
|
||||
amountValidationResult.set(result);
|
||||
if (result.isValid) {
|
||||
showWarningInvalidBtcDecimalPlaces.set(!btcFormatter.hasBtcValidDecimals(userInput));
|
||||
showWarningInvalidBtcDecimalPlaces.set(!DisplayUtils.hasBtcValidDecimals(userInput, btcFormatter));
|
||||
// only allow max 4 decimal places for btc values
|
||||
setAmountToModel();
|
||||
// reformat input
|
||||
@ -503,7 +504,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void addBindings() {
|
||||
volume.bind(createStringBinding(() -> btcFormatter.formatVolume(dataModel.volume.get()), dataModel.volume));
|
||||
volume.bind(createStringBinding(() -> DisplayUtils.formatVolume(dataModel.volume.get()), dataModel.volume));
|
||||
|
||||
if (dataModel.getDirection() == OfferPayload.Direction.SELL) {
|
||||
volumeDescriptionLabel.set(Res.get("createOffer.amountPriceBox.buy.volumeDescription", dataModel.getCurrencyCode()));
|
||||
@ -626,7 +627,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
|
||||
private void setAmountToModel() {
|
||||
if (amount.get() != null && !amount.get().isEmpty()) {
|
||||
Coin amount = btcFormatter.parseToCoinWith4Decimals(this.amount.get());
|
||||
Coin amount = DisplayUtils.parseToCoinWith4Decimals(this.amount.get(), btcFormatter);
|
||||
long maxTradeLimit = dataModel.getMaxTradeLimit();
|
||||
Price price = dataModel.tradePrice;
|
||||
if (price != null) {
|
||||
|
@ -20,6 +20,7 @@ package bisq.desktop.main.overlays.windows;
|
||||
import bisq.desktop.components.BisqTextArea;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.overlays.Overlay;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
@ -140,16 +141,16 @@ public class ContractWindow extends Overlay<ContractWindow> {
|
||||
addConfirmationLabelTextFieldWithCopyIcon(gridPane, rowIndex, Res.get("shared.offerId"), offer.getId(),
|
||||
Layout.TWICE_FIRST_ROW_DISTANCE).second.setMouseTransparent(false);
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("contractWindow.dates"),
|
||||
formatter.formatDateTime(offer.getDate()) + " / " + formatter.formatDateTime(dispute.getTradeDate()));
|
||||
DisplayUtils.formatDateTime(offer.getDate()) + " / " + DisplayUtils.formatDateTime(dispute.getTradeDate()));
|
||||
String currencyCode = offer.getCurrencyCode();
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.offerType"),
|
||||
formatter.getDirectionBothSides(offer.getDirection(), currencyCode));
|
||||
DisplayUtils.getDirectionBothSides(offer.getDirection(), currencyCode));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradePrice"),
|
||||
formatter.formatPrice(contract.getTradePrice()));
|
||||
BSFormatter.formatPrice(contract.getTradePrice()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeAmount"),
|
||||
formatter.formatCoinWithCode(contract.getTradeAmount()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, formatter.formatVolumeLabel(currencyCode, ":"),
|
||||
formatter.formatVolumeWithCode(contract.getTradeVolume()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, DisplayUtils.formatVolumeLabel(currencyCode, ":"),
|
||||
DisplayUtils.formatVolumeWithCode(contract.getTradeVolume()));
|
||||
String securityDeposit = Res.getWithColAndCap("shared.buyer") +
|
||||
" " +
|
||||
formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) +
|
||||
@ -279,7 +280,7 @@ public class ContractWindow extends Overlay<ContractWindow> {
|
||||
String currencyCode) {
|
||||
long age = accountAgeWitnessService.getAccountAge(paymentAccountPayload, pubKeyRing);
|
||||
return CurrencyUtil.isFiatCurrency(currencyCode) ?
|
||||
age > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(age)) :
|
||||
age > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(age)) :
|
||||
Res.get("peerInfoIcon.tooltip.unknownAge") :
|
||||
"";
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import bisq.desktop.components.BisqTextArea;
|
||||
import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.main.overlays.Overlay;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.btc.exceptions.TransactionVerificationException;
|
||||
@ -39,6 +40,7 @@ import bisq.core.support.dispute.arbitration.ArbitrationManager;
|
||||
import bisq.core.support.dispute.mediation.MediationManager;
|
||||
import bisq.core.trade.Contract;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.DevEnv;
|
||||
@ -259,7 +261,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||
addTitledGroupBg(gridPane, ++rowIndex, 17, Res.get("disputeSummaryWindow.title")).getStyleClass().add("last");
|
||||
addConfirmationLabelLabel(gridPane, rowIndex, Res.get("shared.tradeId"), dispute.getShortTradeId(),
|
||||
Layout.TWICE_FIRST_ROW_DISTANCE);
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.openDate"), formatter.formatDateTime(dispute.getOpeningDate()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.openDate"), DisplayUtils.formatDateTime(dispute.getOpeningDate()));
|
||||
if (dispute.isDisputeOpenerIsMaker()) {
|
||||
if (dispute.isDisputeOpenerIsBuyer())
|
||||
role = Res.get("support.buyerOfferer");
|
||||
@ -275,9 +277,9 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeAmount"),
|
||||
formatter.formatCoinWithCode(contract.getTradeAmount()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradePrice"),
|
||||
formatter.formatPrice(contract.getTradePrice()));
|
||||
BSFormatter.formatPrice(contract.getTradePrice()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeVolume"),
|
||||
formatter.formatVolumeWithCode(contract.getTradeVolume()));
|
||||
DisplayUtils.formatVolumeWithCode(contract.getTradeVolume()));
|
||||
String securityDeposit = Res.getWithColAndCap("shared.buyer") +
|
||||
" " +
|
||||
formatter.formatCoinWithCode(contract.getOfferPayload().getBuyerSecurityDeposit()) +
|
||||
@ -344,8 +346,8 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||
}
|
||||
|
||||
private boolean isPayoutAmountValid() {
|
||||
Coin buyerAmount = formatter.parseToCoin(buyerPayoutAmountInputTextField.getText());
|
||||
Coin sellerAmount = formatter.parseToCoin(sellerPayoutAmountInputTextField.getText());
|
||||
Coin buyerAmount = ParsingUtils.parseToCoin(buyerPayoutAmountInputTextField.getText(), formatter);
|
||||
Coin sellerAmount = ParsingUtils.parseToCoin(sellerPayoutAmountInputTextField.getText(), formatter);
|
||||
Contract contract = dispute.getContract();
|
||||
Coin tradeAmount = contract.getTradeAmount();
|
||||
Offer offer = new Offer(contract.getOfferPayload());
|
||||
@ -362,7 +364,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||
Coin available = contract.getTradeAmount()
|
||||
.add(offer.getBuyerSecurityDeposit())
|
||||
.add(offer.getSellerSecurityDeposit());
|
||||
Coin enteredAmount = formatter.parseToCoin(inputTextField.getText());
|
||||
Coin enteredAmount = ParsingUtils.parseToCoin(inputTextField.getText(), formatter);
|
||||
if (enteredAmount.compareTo(available) > 0) {
|
||||
enteredAmount = available;
|
||||
Coin finalEnteredAmount = enteredAmount;
|
||||
@ -551,7 +553,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||
dispute.setDisputeResult(disputeResult);
|
||||
dispute.setIsClosed(true);
|
||||
String text = Res.get("disputeSummaryWindow.close.msg",
|
||||
formatter.formatDateTime(disputeResult.getCloseDate()),
|
||||
DisplayUtils.formatDateTime(disputeResult.getCloseDate()),
|
||||
formatter.formatCoinWithCode(disputeResult.getBuyerPayoutAmount()),
|
||||
formatter.formatCoinWithCode(disputeResult.getSellerPayoutAmount()),
|
||||
disputeResult.summaryNotesProperty().get());
|
||||
|
@ -21,6 +21,7 @@ import bisq.desktop.Navigation;
|
||||
import bisq.desktop.components.AutoTooltipButton;
|
||||
import bisq.desktop.components.BusyAnimation;
|
||||
import bisq.desktop.main.overlays.Overlay;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
@ -172,49 +173,49 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
||||
double firstRowDistance = Layout.TWICE_FIRST_ROW_DISTANCE;
|
||||
if (takeOfferHandlerOptional.isPresent()) {
|
||||
addConfirmationLabelLabel(gridPane, rowIndex, offerTypeLabel,
|
||||
formatter.getDirectionForTakeOffer(direction, currencyCode), firstRowDistance);
|
||||
DisplayUtils.getDirectionForTakeOffer(direction, currencyCode), firstRowDistance);
|
||||
fiatDirectionInfo = direction == OfferPayload.Direction.BUY ? toReceive : toSpend;
|
||||
btcDirectionInfo = direction == OfferPayload.Direction.SELL ? toReceive : toSpend;
|
||||
} else if (placeOfferHandlerOptional.isPresent()) {
|
||||
addConfirmationLabelLabel(gridPane, rowIndex, offerTypeLabel,
|
||||
formatter.getOfferDirectionForCreateOffer(direction, currencyCode), firstRowDistance);
|
||||
DisplayUtils.getOfferDirectionForCreateOffer(direction, currencyCode), firstRowDistance);
|
||||
fiatDirectionInfo = direction == OfferPayload.Direction.SELL ? toReceive : toSpend;
|
||||
btcDirectionInfo = direction == OfferPayload.Direction.BUY ? toReceive : toSpend;
|
||||
} else {
|
||||
addConfirmationLabelLabel(gridPane, rowIndex, offerTypeLabel,
|
||||
formatter.getDirectionBothSides(direction, currencyCode), firstRowDistance);
|
||||
DisplayUtils.getDirectionBothSides(direction, currencyCode), firstRowDistance);
|
||||
}
|
||||
String btcAmount = Res.get("shared.btcAmount");
|
||||
if (takeOfferHandlerOptional.isPresent()) {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, btcAmount + btcDirectionInfo,
|
||||
formatter.formatCoinWithCode(tradeAmount));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, formatter.formatVolumeLabel(currencyCode) + fiatDirectionInfo,
|
||||
formatter.formatVolumeWithCode(offer.getVolumeByAmount(tradeAmount)));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, DisplayUtils.formatVolumeLabel(currencyCode) + fiatDirectionInfo,
|
||||
DisplayUtils.formatVolumeWithCode(offer.getVolumeByAmount(tradeAmount)));
|
||||
} else {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, btcAmount + btcDirectionInfo,
|
||||
formatter.formatCoinWithCode(offer.getAmount()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("offerDetailsWindow.minBtcAmount"),
|
||||
formatter.formatCoinWithCode(offer.getMinAmount()));
|
||||
String volume = formatter.formatVolumeWithCode(offer.getVolume());
|
||||
String volume = DisplayUtils.formatVolumeWithCode(offer.getVolume());
|
||||
String minVolume = "";
|
||||
if (offer.getVolume() != null && offer.getMinVolume() != null &&
|
||||
!offer.getVolume().equals(offer.getMinVolume()))
|
||||
minVolume = " " + Res.get("offerDetailsWindow.min", formatter.formatVolumeWithCode(offer.getMinVolume()));
|
||||
minVolume = " " + Res.get("offerDetailsWindow.min", DisplayUtils.formatVolumeWithCode(offer.getMinVolume()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex,
|
||||
formatter.formatVolumeLabel(currencyCode) + fiatDirectionInfo, volume + minVolume);
|
||||
DisplayUtils.formatVolumeLabel(currencyCode) + fiatDirectionInfo, volume + minVolume);
|
||||
}
|
||||
|
||||
String priceLabel = Res.get("shared.price");
|
||||
if (takeOfferHandlerOptional.isPresent()) {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, formatter.formatPrice(tradePrice));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, BSFormatter.formatPrice(tradePrice));
|
||||
} else {
|
||||
Price price = offer.getPrice();
|
||||
if (offer.isUseMarketBasedPrice()) {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, formatter.formatPrice(price) +
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, BSFormatter.formatPrice(price) +
|
||||
" " + Res.get("offerDetailsWindow.distance",
|
||||
formatter.formatPercentagePrice(offer.getMarketPriceMargin())));
|
||||
BSFormatter.formatPercentagePrice(offer.getMarketPriceMargin())));
|
||||
} else {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, formatter.formatPrice(price));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, BSFormatter.formatPrice(price));
|
||||
}
|
||||
}
|
||||
final PaymentMethod paymentMethod = offer.getPaymentMethod();
|
||||
@ -309,7 +310,7 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
||||
addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, Res.get("offerDetailsWindow.makersOnion"),
|
||||
offer.getMakerNodeAddress().getFullAddress());
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("offerDetailsWindow.creationDate"),
|
||||
formatter.formatDateTime(offer.getDate()));
|
||||
DisplayUtils.formatDateTime(offer.getDate()));
|
||||
String value = Res.getWithColAndCap("shared.buyer") +
|
||||
" " +
|
||||
formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) +
|
||||
|
@ -25,6 +25,7 @@ import bisq.desktop.components.TableGroupHeadline;
|
||||
import bisq.desktop.main.dao.governance.ProposalDisplay;
|
||||
import bisq.desktop.main.dao.governance.result.VoteListItem;
|
||||
import bisq.desktop.main.overlays.TabbedOverlay;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
@ -240,7 +241,7 @@ public class ProposalResultsWindow extends TabbedOverlay<ProposalResultsWindow>
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
setText(bsqFormatter.formatDateTime(item.getBlindVoteDate()));
|
||||
setText(DisplayUtils.formatDateTime(item.getBlindVoteDate()));
|
||||
} else {
|
||||
setText("");
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ public class TacWindow extends Overlay<TacWindow> {
|
||||
"accordance with the Bisq arbitration rules as at present in force. The arbitration is conducted online. " +
|
||||
"The language to be used in the arbitration proceedings shall be English if not otherwise stated.\n\n" +
|
||||
|
||||
"6. The user confirms that he has read and agreed to the rules regarding the dispute process:\n" +
|
||||
"6. The user confirms that they have read and agreed to the rules regarding the dispute process:\n" +
|
||||
" - You must complete trades within the maximum duration specified for each payment method.\n" +
|
||||
" - You must enter the trade ID in the \"reason for payment\" text field when doing the fiat payment transfer.\n" +
|
||||
" - If the bank of the fiat sender charges fees, the sender (" + Res.getBaseCurrencyCode() + " buyer) has to cover the fees.\n" +
|
||||
|
@ -21,6 +21,7 @@ import bisq.desktop.components.BisqTextArea;
|
||||
import bisq.desktop.components.TextFieldWithCopyIcon;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.overlays.Overlay;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
@ -138,12 +139,12 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||
String offerType = Res.get("shared.offerType");
|
||||
if (tradeManager.isBuyer(offer)) {
|
||||
addConfirmationLabelLabel(gridPane, rowIndex, offerType,
|
||||
formatter.getDirectionForBuyer(myOffer, offer.getCurrencyCode()), Layout.TWICE_FIRST_ROW_DISTANCE);
|
||||
DisplayUtils.getDirectionForBuyer(myOffer, offer.getCurrencyCode()), Layout.TWICE_FIRST_ROW_DISTANCE);
|
||||
fiatDirectionInfo = toSpend;
|
||||
btcDirectionInfo = toReceive;
|
||||
} else {
|
||||
addConfirmationLabelLabel(gridPane, rowIndex, offerType,
|
||||
formatter.getDirectionForSeller(myOffer, offer.getCurrencyCode()), Layout.TWICE_FIRST_ROW_DISTANCE);
|
||||
DisplayUtils.getDirectionForSeller(myOffer, offer.getCurrencyCode()), Layout.TWICE_FIRST_ROW_DISTANCE);
|
||||
fiatDirectionInfo = toReceive;
|
||||
btcDirectionInfo = toSpend;
|
||||
}
|
||||
@ -151,10 +152,10 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.btcAmount") + btcDirectionInfo,
|
||||
formatter.formatCoinWithCode(trade.getTradeAmount()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex,
|
||||
formatter.formatVolumeLabel(offer.getCurrencyCode()) + fiatDirectionInfo,
|
||||
formatter.formatVolumeWithCode(trade.getTradeVolume()));
|
||||
DisplayUtils.formatVolumeLabel(offer.getCurrencyCode()) + fiatDirectionInfo,
|
||||
DisplayUtils.formatVolumeWithCode(trade.getTradeVolume()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradePrice"),
|
||||
formatter.formatPrice(trade.getTradePrice()));
|
||||
BSFormatter.formatPrice(trade.getTradePrice()));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.paymentMethod"),
|
||||
Res.get(offer.getPaymentMethod().getId()));
|
||||
|
||||
@ -202,7 +203,7 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||
addConfirmationLabelTextFieldWithCopyIcon(gridPane, rowIndex, Res.get("shared.tradeId"),
|
||||
trade.getId(), Layout.TWICE_FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.tradeDate"),
|
||||
formatter.formatDateTime(trade.getDate()));
|
||||
DisplayUtils.formatDateTime(trade.getDate()));
|
||||
String securityDeposit = Res.getWithColAndCap("shared.buyer") +
|
||||
" " +
|
||||
formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) +
|
||||
@ -234,7 +235,7 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||
String paymentDetails = buyerPaymentAccountPayload.getPaymentDetails();
|
||||
long age = accountAgeWitnessService.getAccountAge(buyerPaymentAccountPayload, contract.getBuyerPubKeyRing());
|
||||
buyersAccountAge = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()) ?
|
||||
age > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(age)) :
|
||||
age > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(age)) :
|
||||
Res.get("peerInfoIcon.tooltip.unknownAge") :
|
||||
"";
|
||||
|
||||
@ -248,7 +249,7 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||
String paymentDetails = sellerPaymentAccountPayload.getPaymentDetails();
|
||||
long age = accountAgeWitnessService.getAccountAge(sellerPaymentAccountPayload, contract.getSellerPubKeyRing());
|
||||
sellersAccountAge = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()) ?
|
||||
age > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(age)) :
|
||||
age > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(age)) :
|
||||
Res.get("peerInfoIcon.tooltip.unknownAge") :
|
||||
"";
|
||||
String postFix = sellersAccountAge.isEmpty() ? "" : " / " + sellersAccountAge;
|
||||
|
@ -94,8 +94,7 @@ public class BisqInstaller {
|
||||
|
||||
public VerifyTask verify(List<FileDescriptor> fileDescriptors) {
|
||||
VerifyTask verifyTask = new VerifyTask(fileDescriptors);
|
||||
Thread th = new Thread(verifyTask);
|
||||
th.start();
|
||||
new Thread(verifyTask, "BisqInstaller VerifyTask").start();
|
||||
// TODO: check for problems when creating task
|
||||
return verifyTask;
|
||||
}
|
||||
@ -120,8 +119,7 @@ public class BisqInstaller {
|
||||
if (saveDir == null)
|
||||
saveDir = Utilities.getDownloadOfHomeDir();
|
||||
DownloadTask task = new DownloadTask(fileDescriptors, saveDir);
|
||||
Thread th = new Thread(task);
|
||||
th.start();
|
||||
new Thread(task, "BisqInstaller DownloadTask").start();
|
||||
// TODO: check for problems when creating task
|
||||
return task;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.components.PeerInfoIcon;
|
||||
import bisq.desktop.main.overlays.windows.OfferDetailsWindow;
|
||||
import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.alert.PrivateNotificationManager;
|
||||
@ -317,7 +318,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
|
||||
|
||||
Offer offer = item.getTradable().getOffer();
|
||||
boolean matchesId = offer.getId().contains(filterString);
|
||||
boolean matchesOfferDate = formatter.formatDate(offer.getDate()).contains(filterString);
|
||||
boolean matchesOfferDate = DisplayUtils.formatDate(offer.getDate()).contains(filterString);
|
||||
boolean isMakerOnion = offer.getMakerNodeAddress().getFullAddress().contains(filterString);
|
||||
|
||||
if (item.getTradable() instanceof Trade) {
|
||||
@ -327,7 +328,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
|
||||
boolean matchesSellersPaymentAccountData = false;
|
||||
|
||||
Trade trade = (Trade) item.getTradable();
|
||||
boolean matchesTradeDate = formatter.formatDate(trade.getTakeOfferDate()).contains(filterString);
|
||||
boolean matchesTradeDate = DisplayUtils.formatDate(trade.getTakeOfferDate()).contains(filterString);
|
||||
Contract contract = trade.getContract();
|
||||
if (contract != null) {
|
||||
isBuyerOnion = contract.getBuyerNodeAddress().getFullAddress().contains(filterString);
|
||||
|
@ -19,6 +19,7 @@ package bisq.desktop.main.portfolio.closedtrades;
|
||||
|
||||
import bisq.desktop.common.model.ActivatableWithDataModel;
|
||||
import bisq.desktop.common.model.ViewModel;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
import bisq.core.locale.Res;
|
||||
@ -68,14 +69,14 @@ class ClosedTradesViewModel extends ActivatableWithDataModel<ClosedTradesDataMod
|
||||
return "";
|
||||
Tradable tradable = item.getTradable();
|
||||
if (tradable instanceof Trade)
|
||||
return formatter.formatPrice(((Trade) tradable).getTradePrice());
|
||||
return BSFormatter.formatPrice(((Trade) tradable).getTradePrice());
|
||||
else
|
||||
return formatter.formatPrice(tradable.getOffer().getPrice());
|
||||
return BSFormatter.formatPrice(tradable.getOffer().getPrice());
|
||||
}
|
||||
|
||||
String getVolume(ClosedTradableListItem item) {
|
||||
if (item != null && item.getTradable() instanceof Trade)
|
||||
return formatter.formatVolumeWithCode(((Trade) item.getTradable()).getTradeVolume());
|
||||
return DisplayUtils.formatVolumeWithCode(((Trade) item.getTradable()).getTradeVolume());
|
||||
else if (item != null && item.getTradable() instanceof OpenOffer)
|
||||
return "-";
|
||||
else
|
||||
@ -123,18 +124,18 @@ class ClosedTradesViewModel extends ActivatableWithDataModel<ClosedTradesDataMod
|
||||
}
|
||||
|
||||
String getDirectionLabel(ClosedTradableListItem item) {
|
||||
return (item != null) ? formatter.getDirectionWithCode(dataModel.getDirection(item.getTradable().getOffer()), item.getTradable().getOffer().getCurrencyCode()) : "";
|
||||
return (item != null) ? DisplayUtils.getDirectionWithCode(dataModel.getDirection(item.getTradable().getOffer()), item.getTradable().getOffer().getCurrencyCode()) : "";
|
||||
}
|
||||
|
||||
String getDate(ClosedTradableListItem item) {
|
||||
return formatter.formatDateTime(item.getTradable().getDate());
|
||||
return DisplayUtils.formatDateTime(item.getTradable().getDate());
|
||||
}
|
||||
|
||||
String getMarketLabel(ClosedTradableListItem item) {
|
||||
if ((item == null))
|
||||
return "";
|
||||
|
||||
return formatter.getCurrencyPair(item.getTradable().getOffer().getCurrencyCode());
|
||||
return BSFormatter.getCurrencyPair(item.getTradable().getOffer().getCurrencyCode());
|
||||
}
|
||||
|
||||
String getState(ClosedTradableListItem item) {
|
||||
|
@ -92,12 +92,12 @@ class EditOfferViewModel extends MutableOfferViewModel<EditOfferDataModel> {
|
||||
|
||||
public void onInvalidateMarketPriceMargin() {
|
||||
marketPriceMargin.set("0.00%");
|
||||
marketPriceMargin.set(btcFormatter.formatToPercent(dataModel.getMarketPriceMargin()));
|
||||
marketPriceMargin.set(BSFormatter.formatToPercent(dataModel.getMarketPriceMargin()));
|
||||
}
|
||||
|
||||
public void onInvalidatePrice() {
|
||||
price.set(btcFormatter.formatPrice(null));
|
||||
price.set(btcFormatter.formatPrice(dataModel.getPrice().get()));
|
||||
price.set(BSFormatter.formatPrice(null));
|
||||
price.set(BSFormatter.formatPrice(dataModel.getPrice().get()));
|
||||
}
|
||||
|
||||
public boolean isSecurityDepositValid() {
|
||||
|
@ -19,6 +19,7 @@ package bisq.desktop.main.portfolio.failedtrades;
|
||||
|
||||
import bisq.desktop.common.model.ActivatableWithDataModel;
|
||||
import bisq.desktop.common.model.ViewModel;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BSFormatter;
|
||||
@ -54,29 +55,29 @@ class FailedTradesViewModel extends ActivatableWithDataModel<FailedTradesDataMod
|
||||
}
|
||||
|
||||
String getPrice(FailedTradesListItem item) {
|
||||
return (item != null) ? formatter.formatPrice(item.getTrade().getTradePrice()) : "";
|
||||
return (item != null) ? BSFormatter.formatPrice(item.getTrade().getTradePrice()) : "";
|
||||
}
|
||||
|
||||
String getVolume(FailedTradesListItem item) {
|
||||
if (item != null && item.getTrade() != null)
|
||||
return formatter.formatVolumeWithCode(item.getTrade().getTradeVolume());
|
||||
return DisplayUtils.formatVolumeWithCode(item.getTrade().getTradeVolume());
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
String getDirectionLabel(FailedTradesListItem item) {
|
||||
return (item != null) ? formatter.getDirectionWithCode(dataModel.getDirection(item.getTrade().getOffer()), item.getTrade().getOffer().getCurrencyCode()) : "";
|
||||
return (item != null) ? DisplayUtils.getDirectionWithCode(dataModel.getDirection(item.getTrade().getOffer()), item.getTrade().getOffer().getCurrencyCode()) : "";
|
||||
}
|
||||
|
||||
String getMarketLabel(FailedTradesListItem item) {
|
||||
if ((item == null))
|
||||
return "";
|
||||
|
||||
return formatter.getCurrencyPair(item.getTrade().getOffer().getCurrencyCode());
|
||||
return BSFormatter.getCurrencyPair(item.getTrade().getOffer().getCurrencyCode());
|
||||
}
|
||||
|
||||
String getDate(FailedTradesListItem item) {
|
||||
return formatter.formatDateTime(item.getTrade().getDate());
|
||||
return DisplayUtils.formatDateTime(item.getTrade().getDate());
|
||||
}
|
||||
|
||||
String getState(FailedTradesListItem item) {
|
||||
|
@ -19,6 +19,7 @@ package bisq.desktop.main.portfolio.openoffer;
|
||||
|
||||
import bisq.desktop.common.model.ActivatableWithDataModel;
|
||||
import bisq.desktop.common.model.ViewModel;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
@ -72,7 +73,7 @@ class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel>
|
||||
}
|
||||
|
||||
String getAmount(OpenOfferListItem item) {
|
||||
return (item != null) ? formatter.formatAmount(item.getOffer()) : "";
|
||||
return (item != null) ? DisplayUtils.formatAmount(item.getOffer(), formatter) : "";
|
||||
}
|
||||
|
||||
String getPrice(OpenOfferListItem item) {
|
||||
@ -84,33 +85,33 @@ class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel>
|
||||
if (price != null) {
|
||||
String postFix = "";
|
||||
if (offer.isUseMarketBasedPrice())
|
||||
postFix = " (" + formatter.formatPercentagePrice(offer.getMarketPriceMargin()) + ")";
|
||||
return formatter.formatPrice(price) + postFix;
|
||||
postFix = " (" + BSFormatter.formatPercentagePrice(offer.getMarketPriceMargin()) + ")";
|
||||
return BSFormatter.formatPrice(price) + postFix;
|
||||
} else {
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
String getVolume(OpenOfferListItem item) {
|
||||
return (item != null) ? formatter.formatVolume(item.getOffer(), false, 0) + " " + item.getOffer().getCurrencyCode() : "";
|
||||
return (item != null) ? DisplayUtils.formatVolume(item.getOffer(), false, 0) + " " + item.getOffer().getCurrencyCode() : "";
|
||||
}
|
||||
|
||||
String getDirectionLabel(OpenOfferListItem item) {
|
||||
if ((item == null))
|
||||
return "";
|
||||
|
||||
return formatter.getDirectionWithCode(dataModel.getDirection(item.getOffer()), item.getOffer().getCurrencyCode());
|
||||
return DisplayUtils.getDirectionWithCode(dataModel.getDirection(item.getOffer()), item.getOffer().getCurrencyCode());
|
||||
}
|
||||
|
||||
String getMarketLabel(OpenOfferListItem item) {
|
||||
if ((item == null))
|
||||
return "";
|
||||
|
||||
return formatter.getCurrencyPair(item.getOffer().getCurrencyCode());
|
||||
return BSFormatter.getCurrencyPair(item.getOffer().getCurrencyCode());
|
||||
}
|
||||
|
||||
String getDate(OpenOfferListItem item) {
|
||||
return formatter.formatDateTime(item.getOffer().getDate());
|
||||
return DisplayUtils.formatDateTime(item.getOffer().getDate());
|
||||
}
|
||||
|
||||
boolean isDeactivated(OpenOfferListItem item) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user