Merge branch 'master_upstream' into refactor-filter

This commit is contained in:
chimp1984 2020-08-31 10:15:42 -05:00
commit 5555c43ea9
No known key found for this signature in database
GPG key ID: 9801B4EC591F90E3
17 changed files with 166 additions and 230 deletions

View file

@ -1,11 +1,11 @@
#!/usr/bin/env bats
#
# Integration tests for bisq-cli running against a live bisq-daemon
# Smoke tests for bisq-cli running against a live bisq-daemon (on mainnet)
#
# Prerequisites:
#
# - bats v0.4.0 must be installed (brew install bats on macOS)
# see https://github.com/sstephenson/bats/tree/v0.4.0
# - bats-core 1.2.0+ must be installed (brew install bats-core on macOS)
# see https://github.com/bats-core/bats-core
#
# - Run `./bisq-daemon --apiPassword=xyz --appDataDir=$TESTDIR` where $TESTDIR
# is empty or otherwise contains an unencrypted wallet with a 0 BTC balance
@ -48,14 +48,14 @@
run ./bisq-cli --password="xyz" getversion
[ "$status" -eq 0 ]
echo "actual output: $output" >&2
[ "$output" = "1.3.5" ]
[ "$output" = "1.3.7" ]
}
@test "test getversion" {
run ./bisq-cli --password=xyz getversion
[ "$status" -eq 0 ]
echo "actual output: $output" >&2
[ "$output" = "1.3.5" ]
[ "$output" = "1.3.7" ]
}
@test "test setwalletpassword \"a b c\"" {
@ -190,8 +190,8 @@
[ "$output" = "Error: incorrect parameter count, expecting direction (buy|sell), currency code" ]
}
@test "test getoffers buy eur check return status" {
run ./bisq-cli --password=xyz getoffers buy eur
@test "test getoffers sell eur check return status" {
run ./bisq-cli --password=xyz getoffers sell eur
[ "$status" -eq 0 ]
}

View file

@ -311,17 +311,25 @@ public class Scaffold {
bitcoinDaemon.verifyBitcoindRunning();
}
// Start Bisq apps defined by the supportingApps option, in the in proper order.
if (config.hasSupportingApp(seednode.name()))
startBisqApp(seednode, executor, countdownLatch);
if (config.hasSupportingApp(arbdaemon.name(), arbdesktop.name()))
startBisqApp(config.runArbNodeAsDesktop ? arbdesktop : arbdaemon, executor, countdownLatch);
if (config.hasSupportingApp(arbdaemon.name()))
startBisqApp(arbdaemon, executor, countdownLatch);
else if (config.hasSupportingApp(arbdesktop.name()))
startBisqApp(arbdesktop, executor, countdownLatch);
if (config.hasSupportingApp(alicedaemon.name(), alicedesktop.name()))
startBisqApp(config.runAliceNodeAsDesktop ? alicedesktop : alicedaemon, executor, countdownLatch);
if (config.hasSupportingApp(alicedaemon.name()))
startBisqApp(alicedaemon, executor, countdownLatch);
else if (config.hasSupportingApp(alicedesktop.name()))
startBisqApp(alicedesktop, executor, countdownLatch);
if (config.hasSupportingApp(bobdaemon.name(), bobdesktop.name()))
startBisqApp(config.runBobNodeAsDesktop ? bobdesktop : bobdaemon, executor, countdownLatch);
if (config.hasSupportingApp(bobdaemon.name()))
startBisqApp(bobdaemon, executor, countdownLatch);
else if (config.hasSupportingApp(bobdesktop.name()))
startBisqApp(bobdesktop, executor, countdownLatch);
}
private void startBisqApp(BisqAppConfig bisqAppConfig,
@ -329,28 +337,24 @@ public class Scaffold {
CountDownLatch countdownLatch)
throws IOException, InterruptedException {
BisqApp bisqApp;
BisqApp bisqApp = createBisqApp(bisqAppConfig);
switch (bisqAppConfig) {
case seednode:
bisqApp = createBisqApp(seednode);
seedNodeTask = new SetupTask(bisqApp, countdownLatch);
seedNodeTaskFuture = executor.submit(seedNodeTask);
break;
case arbdaemon:
case arbdesktop:
bisqApp = createBisqApp(config.runArbNodeAsDesktop ? arbdesktop : arbdaemon);
arbNodeTask = new SetupTask(bisqApp, countdownLatch);
arbNodeTaskFuture = executor.submit(arbNodeTask);
break;
case alicedaemon:
case alicedesktop:
bisqApp = createBisqApp(config.runAliceNodeAsDesktop ? alicedesktop : alicedaemon);
aliceNodeTask = new SetupTask(bisqApp, countdownLatch);
aliceNodeTaskFuture = executor.submit(aliceNodeTask);
break;
case bobdaemon:
case bobdesktop:
bisqApp = createBisqApp(config.runBobNodeAsDesktop ? bobdesktop : bobdaemon);
bobNodeTask = new SetupTask(bisqApp, countdownLatch);
bobNodeTaskFuture = executor.submit(bobNodeTask);
break;

View file

@ -65,13 +65,11 @@ public class ApiTestConfig {
static final String ROOT_APP_DATA_DIR = "rootAppDataDir";
static final String API_PASSWORD = "apiPassword";
static final String RUN_SUBPROJECT_JARS = "runSubprojectJars";
static final String RUN_ARB_NODE_AS_DESKTOP = "runArbNodeAsDesktop";
static final String RUN_ALICE_NODE_AS_DESKTOP = "runAliceNodeAsDesktop";
static final String RUN_BOB_NODE_AS_DESKTOP = "runBobNodeAsDesktop";
static final String BISQ_APP_INIT_TIME = "bisqAppInitTime";
static final String SKIP_TESTS = "skipTests";
static final String SHUTDOWN_AFTER_TESTS = "shutdownAfterTests";
static final String SUPPORTING_APPS = "supportingApps";
static final String ENABLE_BISQ_DEBUGGING = "enableBisqDebugging";
// Default values for certain options
static final String DEFAULT_CONFIG_FILE_NAME = "apitest.properties";
@ -98,13 +96,11 @@ public class ApiTestConfig {
// Daemon instances can use same gRPC password, but each needs a different apiPort.
public final String apiPassword;
public final boolean runSubprojectJars;
public final boolean runArbNodeAsDesktop;
public final boolean runAliceNodeAsDesktop;
public final boolean runBobNodeAsDesktop;
public final long bisqAppInitTime;
public final boolean skipTests;
public final boolean shutdownAfterTests;
public final List<String> supportingApps;
public final boolean enableBisqDebugging;
// Immutable system configurations set in the constructor.
public final String bitcoinDatadir;
@ -202,27 +198,6 @@ public class ApiTestConfig {
.ofType(Boolean.class)
.defaultsTo(false);
ArgumentAcceptingOptionSpec<Boolean> runArbNodeAsDesktopOpt =
parser.accepts(RUN_ARB_NODE_AS_DESKTOP,
"Run Arbitration node as desktop")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(false); // TODO how do I register mediator?
ArgumentAcceptingOptionSpec<Boolean> runAliceNodeAsDesktopOpt =
parser.accepts(RUN_ALICE_NODE_AS_DESKTOP,
"Run Alice node as desktop")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(false);
ArgumentAcceptingOptionSpec<Boolean> runBobNodeAsDesktopOpt =
parser.accepts(RUN_BOB_NODE_AS_DESKTOP,
"Run Bob node as desktop")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(false);
ArgumentAcceptingOptionSpec<Long> bisqAppInitTimeOpt =
parser.accepts(BISQ_APP_INIT_TIME,
"Amount of time (ms) to wait on a Bisq instance's initialization")
@ -251,6 +226,12 @@ public class ApiTestConfig {
.ofType(String.class)
.defaultsTo("bitcoind,seednode,arbdaemon,alicedaemon,bobdaemon");
ArgumentAcceptingOptionSpec<Boolean> enableBisqDebuggingOpt =
parser.accepts(ENABLE_BISQ_DEBUGGING,
"Start Bisq apps with remote debug options")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(false);
try {
CompositeOptionSet options = new CompositeOptionSet();
@ -302,13 +283,11 @@ public class ApiTestConfig {
this.bitcoinRpcPassword = options.valueOf(bitcoinRpcPasswordOpt);
this.apiPassword = options.valueOf(apiPasswordOpt);
this.runSubprojectJars = options.valueOf(runSubprojectJarsOpt);
this.runArbNodeAsDesktop = options.valueOf(runArbNodeAsDesktopOpt);
this.runAliceNodeAsDesktop = options.valueOf(runAliceNodeAsDesktopOpt);
this.runBobNodeAsDesktop = options.valueOf(runBobNodeAsDesktopOpt);
this.bisqAppInitTime = options.valueOf(bisqAppInitTimeOpt);
this.skipTests = options.valueOf(skipTestsOpt);
this.shutdownAfterTests = options.valueOf(shutdownAfterTestsOpt);
this.supportingApps = asList(options.valueOf(supportingAppsOpt).split(","));
this.enableBisqDebugging = options.valueOf(enableBisqDebuggingOpt);
// Assign values to special-case static fields.
BASH_PATH_VALUE = bashPath;

View file

@ -30,58 +30,64 @@ import bisq.daemon.app.BisqDaemonMain;
@see <a href="https://github.com/bisq-network/bisq/blob/master/docs/dev-setup.md">dev-setup.md</a>
@see <a href="https://github.com/bisq-network/bisq/blob/master/docs/dao-setup.md">dao-setup.md</a>
*/
@SuppressWarnings("unused")
public enum BisqAppConfig {
seednode("bisq-BTC_REGTEST_Seed_2002",
"bisq-seednode",
"\"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
SeedNodeMain.class.getName(),
2002,
5120,
-1),
-1,
49996),
arbdaemon("bisq-BTC_REGTEST_Arb_dao",
"bisq-daemon",
"\"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqDaemonMain.class.getName(),
4444,
5121,
9997),
9997,
49997),
arbdesktop("bisq-BTC_REGTEST_Arb_dao",
"bisq-desktop",
"\"-XX:MaxRAM=3g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=3g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqAppMain.class.getName(),
4444,
5121,
-1),
-1,
49997),
alicedaemon("bisq-BTC_REGTEST_Alice_dao",
"bisq-daemon",
"\"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqDaemonMain.class.getName(),
7777,
5122,
9998),
9998,
49998),
alicedesktop("bisq-BTC_REGTEST_Alice_dao",
"bisq-desktop",
"\"-XX:MaxRAM=4g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=4g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqAppMain.class.getName(),
7777,
5122,
-1),
-1,
49998),
bobdaemon("bisq-BTC_REGTEST_Bob_dao",
"bisq-daemon",
"\"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqDaemonMain.class.getName(),
8888,
5123,
9999),
9999,
49999),
bobdesktop("bisq-BTC_REGTEST_Bob_dao",
"bisq-desktop",
"\"-XX:MaxRAM=4g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=4g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqAppMain.class.getName(),
8888,
5123,
-1);
-1,
49999);
public final String appName;
public final String startupScript;
@ -91,6 +97,7 @@ public enum BisqAppConfig {
public final int rpcBlockNotificationPort;
// Daemons can use a global gRPC password, but each needs a unique apiPort.
public final int apiPort;
public final int remoteDebugPort;
BisqAppConfig(String appName,
String startupScript,
@ -98,7 +105,8 @@ public enum BisqAppConfig {
String mainClassName,
int nodePort,
int rpcBlockNotificationPort,
int apiPort) {
int apiPort,
int remoteDebugPort) {
this.appName = appName;
this.startupScript = startupScript;
this.javaOpts = javaOpts;
@ -106,6 +114,7 @@ public enum BisqAppConfig {
this.nodePort = nodePort;
this.rpcBlockNotificationPort = rpcBlockNotificationPort;
this.apiPort = apiPort;
this.remoteDebugPort = remoteDebugPort;
}
@Override
@ -118,6 +127,7 @@ public enum BisqAppConfig {
", nodePort=" + nodePort + "\n" +
", rpcBlockNotificationPort=" + rpcBlockNotificationPort + "\n" +
", apiPort=" + apiPort + "\n" +
", remoteDebugPort=" + remoteDebugPort + "\n" +
'}';
}
}

View file

@ -53,6 +53,7 @@ public class BisqApp extends AbstractLinuxProcess implements LinuxProcess {
private final boolean useLocalhostForP2P;
public final boolean useDevPrivilegeKeys;
private final String findBisqPidScript;
private final String debugOpts;
public BisqApp(BisqAppConfig bisqAppConfig, ApiTestConfig config) {
super(bisqAppConfig.appName, config);
@ -67,6 +68,9 @@ public class BisqApp extends AbstractLinuxProcess implements LinuxProcess {
this.useDevPrivilegeKeys = true;
this.findBisqPidScript = (config.isRunningTest ? "." : "./apitest")
+ "/scripts/get-bisq-pid.sh";
this.debugOpts = config.enableBisqDebugging
? " -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:" + bisqAppConfig.remoteDebugPort
: "";
}
@Override
@ -112,7 +116,6 @@ public class BisqApp extends AbstractLinuxProcess implements LinuxProcess {
if (isAlive(pid)) {
this.shutdownExceptions.add(new IllegalStateException(format("%s shutdown did not work", bisqAppConfig.appName)));
return;
}
} catch (Exception e) {
@ -209,7 +212,7 @@ public class BisqApp extends AbstractLinuxProcess implements LinuxProcess {
}
private String getJavaOptsSpec() {
return "export JAVA_OPTS=" + bisqAppConfig.javaOpts + "; ";
return "export JAVA_OPTS=\"" + bisqAppConfig.javaOpts + debugOpts + "\"; ";
}
private List<String> getOptsList() {

View file

@ -28,6 +28,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import bisq.apitest.config.ApiTestConfig;
import bisq.apitest.method.BitcoinCliHelper;
import bisq.cli.GrpcStubs;
/**
* Base class for all test types: 'method', 'scenario' and 'e2e'.
@ -65,19 +66,19 @@ public class ApiTestCase {
public static void setUpScaffold(String supportingApps)
throws InterruptedException, ExecutionException, IOException {
// The supportingApps argument is a comma delimited string of supporting app
// names, e.g. "bitcoind,seednode,arbdaemon,alicedaemon,bobdaemon"
scaffold = new Scaffold(supportingApps).setUp();
config = scaffold.config;
bitcoinCli = new BitcoinCliHelper((config));
grpcStubs = new GrpcStubs(alicedaemon, config).init();
// For now, all grpc requests are sent to the alicedaemon, but this will need to
// be made configurable for new test cases that call arb or bob node daemons.
grpcStubs = new GrpcStubs("localhost", alicedaemon.apiPort, config.apiPassword);
}
public static void setUpScaffold()
public static void setUpScaffold(String[] params)
throws InterruptedException, ExecutionException, IOException {
scaffold = new Scaffold(new String[]{}).setUp();
scaffold = new Scaffold(params).setUp();
config = scaffold.config;
grpcStubs = new GrpcStubs(alicedaemon, config).init();
grpcStubs = new GrpcStubs("localhost", alicedaemon.apiPort, config.apiPassword);
}
public static void tearDownScaffold() {

View file

@ -1,109 +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.apitest;
import bisq.proto.grpc.GetVersionGrpc;
import bisq.proto.grpc.OffersGrpc;
import bisq.proto.grpc.PaymentAccountsGrpc;
import bisq.proto.grpc.WalletsGrpc;
import io.grpc.CallCredentials;
import io.grpc.ManagedChannelBuilder;
import io.grpc.Metadata;
import java.util.concurrent.Executor;
import static io.grpc.Metadata.ASCII_STRING_MARSHALLER;
import static io.grpc.Status.UNAUTHENTICATED;
import static java.lang.String.format;
import static java.util.concurrent.TimeUnit.SECONDS;
import bisq.apitest.config.ApiTestConfig;
import bisq.apitest.config.BisqAppConfig;
public class GrpcStubs {
public final CallCredentials credentials;
public final String host;
public final int port;
public GetVersionGrpc.GetVersionBlockingStub versionService;
public OffersGrpc.OffersBlockingStub offersService;
public PaymentAccountsGrpc.PaymentAccountsBlockingStub paymentAccountsService;
public WalletsGrpc.WalletsBlockingStub walletsService;
public GrpcStubs(BisqAppConfig bisqAppConfig, ApiTestConfig config) {
this.credentials = new PasswordCallCredentials(config.apiPassword);
this.host = "localhost";
this.port = bisqAppConfig.apiPort;
}
public GrpcStubs init() {
var channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
channel.shutdown().awaitTermination(1, SECONDS);
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
}));
this.versionService = GetVersionGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.offersService = OffersGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.paymentAccountsService = PaymentAccountsGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.walletsService = WalletsGrpc.newBlockingStub(channel).withCallCredentials(credentials);
return this;
}
static class PasswordCallCredentials extends CallCredentials {
public static final String PASSWORD_KEY = "password";
private final String passwordValue;
public PasswordCallCredentials(String passwordValue) {
if (passwordValue == null)
throw new IllegalArgumentException(format("'%s' value must not be null", PASSWORD_KEY));
this.passwordValue = passwordValue;
}
@Override
public void applyRequestMetadata(RequestInfo requestInfo,
Executor appExecutor,
MetadataApplier metadataApplier) {
appExecutor.execute(() -> {
try {
var headers = new Metadata();
var passwordKey = Metadata.Key.of(PASSWORD_KEY, ASCII_STRING_MARSHALLER);
headers.put(passwordKey, passwordValue);
metadataApplier.apply(headers);
} catch (Throwable ex) {
metadataApplier.fail(UNAUTHENTICATED.withCause(ex));
}
});
}
@Override
public void thisUsesUnstableApi() {
// An experimental api. A noop but never called; tries to make it clearer to
// implementors that they may break in the future.
}
}
}

View file

@ -51,7 +51,7 @@ configure(subprojects) {
javaxAnnotationVersion = '1.2'
jcsvVersion = '1.4.0'
jetbrainsAnnotationsVersion = '13.0'
jfoenixVersion = '9.0.6'
jfoenixVersion = '9.0.10'
joptVersion = '5.0.4'
jsonsimpleVersion = '1.1.1'
junitVersion = '4.12'

View file

@ -133,21 +133,11 @@ public class CliMain {
if (password == null)
throw new IllegalArgumentException("missing required 'password' option");
var credentials = new PasswordCallCredentials(password);
var channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}));
var versionService = GetVersionGrpc.newBlockingStub(channel).withCallCredentials(credentials);
var offersService = OffersGrpc.newBlockingStub(channel).withCallCredentials(credentials);
var paymentAccountsService = PaymentAccountsGrpc.newBlockingStub(channel).withCallCredentials(credentials);
var walletsService = WalletsGrpc.newBlockingStub(channel).withCallCredentials(credentials);
GrpcStubs grpcStubs = new GrpcStubs(host, port, password);
var versionService = grpcStubs.versionService;
var offersService = grpcStubs.offersService;
var paymentAccountsService = grpcStubs.paymentAccountsService;
var walletsService = grpcStubs.walletsService;
try {
switch (method) {

View file

@ -0,0 +1,54 @@
/*
* 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.cli;
import bisq.proto.grpc.GetVersionGrpc;
import bisq.proto.grpc.OffersGrpc;
import bisq.proto.grpc.PaymentAccountsGrpc;
import bisq.proto.grpc.WalletsGrpc;
import io.grpc.CallCredentials;
import io.grpc.ManagedChannelBuilder;
import static java.util.concurrent.TimeUnit.SECONDS;
public class GrpcStubs {
public final GetVersionGrpc.GetVersionBlockingStub versionService;
public final OffersGrpc.OffersBlockingStub offersService;
public final PaymentAccountsGrpc.PaymentAccountsBlockingStub paymentAccountsService;
public final WalletsGrpc.WalletsBlockingStub walletsService;
public GrpcStubs(String apiHost, int apiPort, String apiPassword) {
CallCredentials credentials = new PasswordCallCredentials(apiPassword);
var channel = ManagedChannelBuilder.forAddress(apiHost, apiPort).usePlaintext().build();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
channel.shutdown().awaitTermination(1, SECONDS);
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
}));
this.versionService = GetVersionGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.offersService = OffersGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.paymentAccountsService = PaymentAccountsGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.walletsService = WalletsGrpc.newBlockingStub(channel).withCallCredentials(credentials);
}
}

View file

@ -84,7 +84,7 @@ public class Restrictions {
return SELLER_SECURITY_DEPOSIT;
}
// This value must not be lower than MIN_BUYER_SECURITY_DEPOSIT or SELLER_SECURITY_DEPOSIT
// This value must be lower than MIN_BUYER_SECURITY_DEPOSIT and SELLER_SECURITY_DEPOSIT
public static Coin getMinRefundAtMediatedDispute() {
if (MIN_REFUND_AT_MEDIATED_DISPUTE == null)
MIN_REFUND_AT_MEDIATED_DISPUTE = Coin.parseCoin("0.003"); // 0.003 BTC about 21 USD @ 7000 USD/BTC

View file

@ -2627,9 +2627,10 @@ popup.warning.btcChangeBelowDustException=This transaction creates a change outp
You need to add the dust amount to your sending amount to avoid to generate a dust output.\n\n\
The dust output is {0}.
popup.warning.insufficientBsqFundsForBtcFeePayment=You don''t have sufficient BSQ funds for paying the trade fee in BSQ. \
You can pay the fee in BTC or you need to fund your BSQ wallet. You can buy BSQ in Bisq.\n\n\
Missing BSQ funds: {0}
popup.warning.insufficientBsqFundsForBtcFeePayment=You''ll need more BSQ to do this transaction—the last \
5.46 BSQ in your wallet cannot be used to pay trade fees because of dust limits in the Bitcoin protocol.\n\n\
You can either buy more BSQ or pay trade fees with BTC.\n\n\
Missing funds: {0}
popup.warning.noBsqFundsForBtcFeePayment=Your BSQ wallet does not have sufficient funds for paying the trade fee in BSQ.
popup.warning.messageTooLong=Your message exceeds the max. allowed size. Please send it in several parts or upload it to a service like https://pastebin.com.
popup.warning.lockedUpFunds=You have locked up funds from a failed trade.\n\

View file

@ -642,8 +642,8 @@ tree-table-view:focused {
}
.top-navigation .separator:vertical .line {
-fx-border-color: transparent transparent transparent transparent;
-fx-border-width: 3;
-fx-border-color: transparent transparent transparent -bs-rd-nav-border-color;
-fx-border-width: 1;
-fx-border-insets: 0 0 0 1;
}
@ -661,6 +661,7 @@ tree-table-view:focused {
.nav-price-balance {
-fx-background-color: -bs-color-gray-background;
-fx-background-radius: 3;
-fx-effect: innershadow(gaussian, -bs-text-color-transparent, 3, 0, 0, 1);
-fx-pref-height: 41;
-fx-padding: 0 10 0 0;
}
@ -2119,3 +2120,4 @@ textfield */
-fx-stroke: linear-gradient(to bottom, -bs-text-color-transparent, -bs-text-color-transparent-dark) !important;
-fx-fill: -bs-background-color !important;
}

View file

@ -43,12 +43,12 @@ import bisq.desktop.util.DisplayUtils;
import bisq.desktop.util.Transitions;
import bisq.core.dao.monitoring.DaoStateMonitoringService;
import bisq.common.BisqException;
import bisq.core.locale.GlobalSettings;
import bisq.core.locale.LanguageUtil;
import bisq.core.locale.Res;
import bisq.core.provider.price.MarketPrice;
import bisq.common.BisqException;
import bisq.common.Timer;
import bisq.common.UserThread;
import bisq.common.app.Version;
@ -318,17 +318,15 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
}
});
HBox primaryNav = new HBox(marketButton, getNavigationSeparator(), buyButton,
getNavigationSeparator(), sellButton, getNavigationSeparator(),
portfolioButtonWithBadge, getNavigationSeparator(), fundsButton);
HBox primaryNav = new HBox(marketButton, getNavigationSeparator(), buyButton, getNavigationSeparator(),
sellButton, getNavigationSeparator(), portfolioButtonWithBadge, getNavigationSeparator(), fundsButton);
primaryNav.setAlignment(Pos.CENTER);
primaryNav.setAlignment(Pos.CENTER_LEFT);
primaryNav.getStyleClass().add("nav-primary");
HBox.setHgrow(primaryNav, Priority.SOMETIMES);
HBox secondaryNav = new HBox(supportButtonWithBadge, getNavigationSeparator(),
settingsButton, getNavigationSeparator(), accountButtonWithBadge,
getNavigationSeparator(), daoButtonWithBadge);
HBox secondaryNav = new HBox(supportButtonWithBadge, getNavigationSpacer(), settingsButton,
getNavigationSpacer(), accountButtonWithBadge, getNavigationSpacer(), daoButtonWithBadge);
secondaryNav.getStyleClass().add("nav-secondary");
HBox.setHgrow(secondaryNav, Priority.SOMETIMES);
@ -343,14 +341,14 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
priceAndBalance.getStyleClass().add("nav-price-balance");
HBox navPane = new HBox(primaryNav, secondaryNav,
getNavigationSpacer(), priceAndBalance) {{
priceAndBalance) {{
setLeftAnchor(this, 0d);
setRightAnchor(this, 0d);
setTopAnchor(this, 0d);
setPadding(new Insets(0, 0, 0, 0));
getStyleClass().add("top-navigation");
}};
navPane.setAlignment(Pos.CENTER_LEFT);
navPane.setAlignment(Pos.CENTER);
AnchorPane contentContainer = new AnchorPane() {{
getStyleClass().add("content-pane");
@ -383,15 +381,15 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
contentContainer.getChildren().setAll(view.getRoot());
try {
navButtons.getToggles().stream()
.filter(toggle -> toggle instanceof NavButton)
.filter(button -> viewClass == ((NavButton) button).viewClass)
.findFirst()
.orElseThrow(() -> new BisqException("No button matching %s found", viewClass))
.setSelected(true);
navButtons.getToggles().stream()
.filter(toggle -> toggle instanceof NavButton)
.filter(button -> viewClass == ((NavButton) button).viewClass)
.findFirst()
.orElseThrow(() -> new BisqException("No button matching %s found", viewClass))
.setSelected(true);
} catch (BisqException e) {
navigation.navigateTo(MainView.class, MarketView.class, OfferBookChartView.class);
}
}
});
VBox splashScreen = createSplashScreen();
@ -538,7 +536,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
return Res.get("mainView.marketPrice.tooltip",
"Bisq Price Index for " + selectedCurrencyCode,
"",
DisplayUtils.formatTime(new Date(selectedMarketPrice.getTimestampSec())),
selectedMarketPrice != null ? DisplayUtils.formatTime(new Date(selectedMarketPrice.getTimestampSec())) : Res.get("shared.na"),
model.getPriceFeedService().getProviderNodeAddress());
}

View file

@ -524,8 +524,3 @@
.jfx-date-picker .left-button, .jfx-date-picker .right-button{
-fx-background-color: derive(-bs-color-gray-0, -10%);
}
.popup-bg, .notification-popup-bg, .peer-info-popup-bg {
-fx-effect: dropshadow(gaussian, -bs-color-gray-fafa, 44, 0, 0, 0);
}

View file

@ -42,7 +42,7 @@ dependencyVerification {
'com.google.zxing:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729',
'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9',
'com.googlecode.jcsv:jcsv:73ca7d715e90c8d2c2635cc284543b038245a34f70790660ed590e157b8714a2',
'com.jfoenix:jfoenix:4739e37a05e67c3bc9d5b391a1b93717b5a48fa872992616b0964d3f827f8fe6',
'com.jfoenix:jfoenix:8060235fec5eb49617ec8d81d379e8c945f6cc722d0645e97190045100de2084',
'com.lambdaworks:scrypt:9a82d218099fb14c10c0e86e7eefeebd8c104de920acdc47b8b4b7a686fb73b4',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'com.nativelibs4java:bridj:101bcd9b6637e6bc16e56deb3daefba62b1f5e8e9e37e1b3e56e3b5860d659cf',

View file

@ -1,13 +1,21 @@
server=1
daemon=1
listen=1
discover=1
txindex=1
dbcache=1337
maxconnections=1337
timeout=30000
listen=1
discover=1
peerbloomfilters=1
onion=127.0.0.1:9050
rpcallowip=127.0.0.1
rpcuser=__BITCOIN_RPC_USER__
rpcpassword=__BITCOIN_RPC_PASS__
blocknotify=/bitcoin/blocknotify.sh %s
[main]
bind=127.0.0.1:8333
rpcbind=127.0.0.1:8332
[test]
bind=127.0.0.1:18333
rpcbind=127.0.0.1:18332