Merge branch 'master' into release/v1.9.12

This commit is contained in:
Alejandro García 2023-07-13 15:11:38 +00:00 committed by GitHub
commit 85a457c6f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 512 additions and 161 deletions

View File

@ -26,6 +26,28 @@ jobs:
distribution: 'zulu'
- name: Build with Gradle
uses: gradle/gradle-build-action@v2.4.2
uses: gradle/gradle-build-action@v2.5.1
with:
arguments: build --scan
arguments: build jacocoTestReport testCodeCoverageReport --scan
- name: Upload coverage report
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: code-coverage-report/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml
publish_coverage:
name: Publish coverage
runs-on: ubuntu-latest
needs: build
steps:
- name: Download coverage report
uses: actions/download-artifact@v3
with:
name: coverage-report
path: code-coverage-report/build/reports/jacoco/testCodeCoverageReport
- name: Run codacy-coverage-reporter
uses: codacy/codacy-coverage-reporter-action@v1.3.0
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
coverage-reports: ${{ github.workspace }}/code-coverage-report/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml

View File

@ -11,14 +11,14 @@
//
// The :apitest subproject will not run on Windows, and these tasks have not been
// tested on Windows.
def buildResourcesDir = project(":apitest").buildDir.path + '/resources/main'
def buildResourcesDir = project(":apitest").sourceSets.main.resources.srcDirs.first().path
// This task requires ant in the system $PATH.
task installDaoSetup(dependsOn: 'cleanDaoSetup') {
doLast {
println "Installing dao-setup directories in build dir $buildResourcesDir ..."
def src = 'https://github.com/bisq-network/bisq/raw/master/docs/dao-setup.zip'
def destfile = project.rootDir.path + '/apitest/src/main/resources/dao-setup.zip'
def destfile = buildResourcesDir + '/dao-setup.zip'
def url = new URL(src)
def f = new File(destfile)
if (f.exists()) {
@ -48,21 +48,14 @@ task installDaoSetup(dependsOn: 'cleanDaoSetup') {
}
// Copy files from unzip target dir 'dao-setup' to build/resources/main.
def daoSetupSrc = project.rootDir.path + '/apitest/src/main/resources/dao-setup'
def daoSetupDest = buildResourcesDir + '/dao-setup'
def daoSetupSrc = buildResourcesDir + '/dao-setup'
def daoSetupDest = buildResourcesDir
println "Copying $daoSetupSrc to $daoSetupDest ..."
copy {
from daoSetupSrc
into daoSetupDest
}
// Move dao-setup files from build/resources/main/dao-setup to build/resources/main
file(buildResourcesDir + '/dao-setup/Bitcoin-regtest')
.renameTo(file(buildResourcesDir + '/Bitcoin-regtest'))
file(buildResourcesDir + '/dao-setup/bisq-BTC_REGTEST_Alice_dao')
.renameTo(file(buildResourcesDir + '/bisq-BTC_REGTEST_Alice_dao'))
file(buildResourcesDir + '/dao-setup/bisq-BTC_REGTEST_Bob_dao')
.renameTo(file(buildResourcesDir + '/bisq-BTC_REGTEST_Bob_dao'))
delete file(buildResourcesDir + '/dao-setup')
}
}

View File

@ -242,28 +242,37 @@ public class Scaffold {
log.info("Copied all dao-setup files to {}", buildDataDir);
// Try to avoid confusion about which 'bisq.properties' file is or was loaded
// by a Bisq instance: delete the 'bisq.properties' file automatically copied
// to the 'apitest/build/resources/main' directory during IDE or Gradle build.
// Note: there is no way to prevent this deleted file from being re-copied
// from 'src/main/resources' to the buildDataDir each time you hit the build
// button in the IDE.
BashCommand rmRedundantBisqPropertiesFile =
new BashCommand("rm -rf " + buildDataDir + "/bisq.properties");
if (rmRedundantBisqPropertiesFile.run().getExitStatus() != 0)
throw new IllegalStateException("Could not delete redundant bisq.properties file");
// Copy 'bisq.properties' file from 'src/main/resources' to each
// Bisq instance's DataDir
copyBisqPropertiesFileToAppDataDir();
// Copy the blocknotify script from the src resources dir to the build
// resources dir. Users may want to edit comment out some lines when all
// the default block notifcation ports being will not be used (to avoid
// seeing rpc notifcation warnings in log files).
installBitcoinBlocknotify();
} catch (IOException | InterruptedException ex) {
throw new IllegalStateException("Could not install dao-setup files from " + daoSetupDir, ex);
}
}
private void copyBisqPropertiesFileToAppDataDir() throws IOException, InterruptedException {
copyBisqPropertiesFileToAppDataDir(alicedaemon);
copyBisqPropertiesFileToAppDataDir(bobdaemon);
}
private void copyBisqPropertiesFileToAppDataDir(BisqAppConfig bisqAppConfig) throws IOException, InterruptedException {
if (!new File(config.baseSrcResourcesDir + "/bisq.properties").exists()) return;
String instanceDataDir = config.rootAppDataDir + "/" + bisqAppConfig.appName;
BashCommand moveToDataDir =
new BashCommand("cp " + config.baseSrcResourcesDir + "/bisq.properties " + instanceDataDir);
if (moveToDataDir.run().getExitStatus() != 0)
throw new IllegalStateException("Could not copy bisq.properties to " + instanceDataDir);
log.debug("bisq.properties copied to " + instanceDataDir);
}
private void cleanDaoSetupDirectories() {
String buildDataDir = config.rootAppDataDir.getAbsolutePath();
log.info("Cleaning dao-setup data in {}", buildDataDir);

View File

@ -85,6 +85,8 @@ public class ApiTestConfig {
static final String ENABLE_BISQ_DEBUGGING = "enableBisqDebugging";
static final String REGISTER_DISPUTE_AGENTS = "registerDisputeAgents";
static final String SUSPEND_INSTANCE = "suspendInstance";
// Default values for certain options
static final String DEFAULT_CONFIG_FILE_NAME = "apitest.properties";
@ -126,6 +128,8 @@ public class ApiTestConfig {
public final String baseBuildResourcesDir;
public final String baseSrcResourcesDir;
public final String suspendedInstances;
// The parser that will be used to parse both cmd line and config file options
private final OptionParser parser = new OptionParser();
@ -261,6 +265,12 @@ public class ApiTestConfig {
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(true);
ArgumentAcceptingOptionSpec<String> suspendInstancesOpt =
parser.accepts(SUSPEND_INSTANCE, "Suspended the given instances when debugging")
.withRequiredArg()
.ofType(String.class)
.defaultsTo(EMPTY);
try {
CompositeOptionSet options = new CompositeOptionSet();
@ -319,6 +329,7 @@ public class ApiTestConfig {
this.callRateMeteringConfigPath = options.valueOf(callRateMeteringConfigPathOpt);
this.enableBisqDebugging = options.valueOf(enableBisqDebuggingOpt);
this.registerDisputeAgents = options.valueOf(registerDisputeAgentsOpt);
this.suspendedInstances = options.valueOf(suspendInstancesOpt);
// Assign values to special-case static fields.
BASH_PATH_VALUE = bashPath;

View File

@ -23,6 +23,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
@ -66,8 +67,9 @@ public class BisqProcess 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
this.debugOpts = config.enableBisqDebugging ? " -agentlib:jdwp=transport=dt_socket,server=y,"
+ "suspend=" + (Arrays.asList(config.suspendedInstances.split(",")).contains(bisqAppConfig.name()) ? "y" : "n")
+ ",address=*:" + bisqAppConfig.remoteDebugPort
: "";
}

View File

@ -87,8 +87,7 @@ public class ApiTestCase {
throws InterruptedException, ExecutionException, IOException {
String[] params = new String[]{
"--supportingApps", stream(supportingApps).map(Enum::name).collect(Collectors.joining(",")),
"--callRateMeteringConfigPath", getTestRateMeterInterceptorConfig().getAbsolutePath(),
"--enableBisqDebugging", "false"
"--callRateMeteringConfigPath", getTestRateMeterInterceptorConfig().getAbsolutePath()
};
setUpScaffold(params);
}

View File

@ -45,7 +45,6 @@ public class CallRateMeteringInterceptorTest extends MethodTest {
@BeforeAll
public static void setUp() {
startSupportingApps(false,
false,
bitcoind, alicedaemon);
}

View File

@ -70,13 +70,11 @@ public class MethodTest extends ApiTestCase {
public static void startSupportingApps(File callRateMeteringConfigFile,
boolean generateBtcBlock,
boolean startSupportingAppsInDebugMode,
Enum<?>... supportingApps) {
try {
setUpScaffold(new String[]{
"--supportingApps", toNameList.apply(supportingApps),
"--callRateMeteringConfigPath", callRateMeteringConfigFile.getAbsolutePath(),
"--enableBisqDebugging", startSupportingAppsInDebugMode ? "true" : "false"
});
doPostStartup(generateBtcBlock);
} catch (Exception ex) {
@ -84,16 +82,13 @@ public class MethodTest extends ApiTestCase {
}
}
public static void startSupportingApps(boolean generateBtcBlock,
boolean startSupportingAppsInDebugMode,
Enum<?>... supportingApps) {
public static void startSupportingApps(boolean generateBtcBlock, Enum<?>... supportingApps) {
try {
// Disable call rate metering where there is no callRateMeteringConfigFile.
File callRateMeteringConfigFile = getTestRateMeterInterceptorConfig();
setUpScaffold(new String[]{
"--supportingApps", toNameList.apply(supportingApps),
"--callRateMeteringConfigPath", callRateMeteringConfigFile.getAbsolutePath(),
"--enableBisqDebugging", startSupportingAppsInDebugMode ? "true" : "false"
"--callRateMeteringConfigPath", callRateMeteringConfigFile.getAbsolutePath()
});
doPostStartup(generateBtcBlock);
} catch (Exception ex) {

View File

@ -77,12 +77,7 @@ public abstract class AbstractOfferTest extends MethodTest {
@BeforeAll
public static void setUp() {
setUp(false);
}
public static void setUp(boolean startSupportingAppsInDebugMode) {
startSupportingApps(true,
startSupportingAppsInDebugMode,
bitcoind,
seednode,
arbdaemon,

View File

@ -44,10 +44,6 @@ import static protobuf.OfferDirection.BUY;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BsqSwapOfferTest extends AbstractOfferTest {
@BeforeAll
public static void setUp() {
AbstractOfferTest.setUp(false);
}
@BeforeEach
public void generateBtcBlock() {

View File

@ -19,8 +19,13 @@ package bisq.apitest.method.trade;
import bisq.core.payment.PaymentAccount;
import bisq.proto.grpc.OfferInfo;
import io.grpc.StatusRuntimeException;
import java.util.List;
import java.util.concurrent.TimeoutException;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Disabled;
@ -59,8 +64,8 @@ public class TakeBuyBTCOfferTest extends AbstractTradeTest {
PaymentAccount alicesUsdAccount = createDummyF2FAccount(aliceClient, "US");
var alicesOffer = aliceClient.createMarketBasedPricedOffer(BUY.name(),
USD,
12_500_000L,
12_500_000L, // min-amount = amount
10_000_000L,
10_000_000L, // min-amount = amount
0.00,
defaultBuyerSecurityDepositPct.get(),
alicesUsdAccount.getId(),
@ -71,19 +76,34 @@ public class TakeBuyBTCOfferTest extends AbstractTradeTest {
// Wait for Alice's AddToOfferBook task.
// Wait times vary; my logs show >= 2-second delay.
sleep(3_000); // TODO loop instead of hard code a wait time
var alicesUsdOffers = aliceClient.getMyOffersSortedByDate(BUY.name(), USD);
var timeout = System.currentTimeMillis() + 3000;
while (bobClient.getOffersSortedByDate(USD, true).size() < 1) {
sleep(100);
if (System.currentTimeMillis() > timeout)
fail(new TimeoutException("Timed out waiting for Offer to be added to OfferBook"));
}
List<OfferInfo> alicesUsdOffers = aliceClient.getMyOffersSortedByDate(BUY.name(), USD);
assertEquals(1, alicesUsdOffers.size());
PaymentAccount bobsUsdAccount = createDummyF2FAccount(bobClient, "US");
var ignoredTakeOfferAmountParam = 0L;
var trade = takeAlicesOffer(offerId,
bobsUsdAccount.getId(),
TRADE_FEE_CURRENCY_CODE,
ignoredTakeOfferAmountParam,
false);
sleep(2_500); // Allow available offer to be removed from offer book.
// Allow available offer to be removed from offer book.
timeout = System.currentTimeMillis() + 2500;
do {
alicesUsdOffers = aliceClient.getMyOffersSortedByDate(BUY.name(), USD);
sleep(100);
if (System.currentTimeMillis() > timeout)
fail(new TimeoutException("Timed out waiting for Offer to be removed from OfferBook"));
} while (alicesUsdOffers.size() > 0);
assertEquals(0, alicesUsdOffers.size());
trade = bobClient.getTrade(tradeId);

View File

@ -78,10 +78,6 @@ public class TakeBuyBTCOfferWithNationalBankAcctTest extends AbstractTradeTest {
private static PaymentAccount alicesPaymentAccount;
private static PaymentAccount bobsPaymentAccount;
@BeforeAll
public static void setUp() {
setUp(false);
}
@Test
@Order(1)

View File

@ -60,7 +60,7 @@ public class TakeSellXMROfferTest extends AbstractTradeTest {
@BeforeAll
public static void setUp() {
AbstractOfferTest.setUp(false);
AbstractOfferTest.setUp();
createXmrPaymentAccounts();
EXPECTED_PROTOCOL_STATUS.init();
}

View File

@ -48,7 +48,6 @@ public class BsqWalletTest extends MethodTest {
@BeforeAll
public static void setUp() {
startSupportingApps(true,
false,
bitcoind,
seednode,
arbdaemon,

View File

@ -36,7 +36,6 @@ public class BtcTxFeeRateTest extends MethodTest {
@BeforeAll
public static void setUp() {
startSupportingApps(false,
true,
bitcoind,
seednode,
alicedaemon);

View File

@ -41,7 +41,6 @@ public class BtcWalletTest extends MethodTest {
@BeforeAll
public static void setUp() {
startSupportingApps(false,
false,
bitcoind,
seednode,
alicedaemon,

View File

@ -43,11 +43,6 @@ import bisq.apitest.method.offer.ValidateCreateOfferTest;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class OfferTest extends AbstractOfferTest {
@BeforeAll
public static void setUp() {
setUp(false); // Use setUp(true) for running API daemons in remote debug mode.
}
@Test
@Order(1)
public void testCreateOfferValidation() {

View File

@ -57,7 +57,6 @@ public class StartupTest extends MethodTest {
try {
callRateMeteringConfigFile = getTestRateMeterInterceptorConfig();
startSupportingApps(callRateMeteringConfigFile,
false,
false,
bitcoind, seednode, arbdaemon, alicedaemon);
} catch (Exception ex) {

View File

@ -53,7 +53,6 @@ public class WalletTest extends MethodTest {
@BeforeAll
public static void setUp() {
startSupportingApps(true,
false,
bitcoind,
seednode,
arbdaemon,

View File

@ -1,5 +1,6 @@
plugins {
id 'java'
id 'jacoco'
}
repositories {
@ -10,11 +11,6 @@ repositories {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
@ -31,3 +27,10 @@ dependencies {
test {
useJUnitPlatform()
}
jacocoTestReport {
reports {
html.required = false
xml.required = true
}
}

View File

@ -26,9 +26,7 @@ configure(subprojects) {
apply plugin: 'com.google.osdetector'
ext { // in alphabetical order
grpcVersion = '1.42.1'
javafxVersion = '16'
protocVersion = '3.19.1'
os = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
}
@ -130,6 +128,7 @@ configure(project(':common')) {
"Implementation-Version": getHash())
dependencies {
implementation enforcedPlatform(project(':platform'))
implementation project(':proto')
annotationProcessor libs.lombok
compileOnly libs.javax.annotation
@ -142,7 +141,6 @@ configure(project(':common')) {
exclude(module: 'jsr305')
exclude(module: 'okhttp')
exclude(module: 'okio')
exclude(module: 'protobuf-java')
exclude(module: 'slf4j-api')
}
implementation libs.google.findbugs
@ -151,7 +149,6 @@ configure(project(':common')) {
implementation(libs.google.guice) {
exclude(module: 'guava')
}
implementation libs.protobuf.java
implementation libs.commons.io
implementation libs.jopt
implementation libs.apache.commons.lang3
@ -176,12 +173,12 @@ configure(project(':p2p')) {
}
dependencies {
implementation enforcedPlatform(project(':platform'))
implementation project(':proto')
implementation project(':common')
annotationProcessor libs.lombok
compileOnly libs.lombok
implementation libs.google.guava
implementation libs.protobuf.java
implementation libs.fxmisc.easybind
implementation libs.slf4j.api
implementation(libs.netlayer.tor.external) {
@ -196,7 +193,6 @@ configure(project(':p2p')) {
exclude(module: 'jsr305')
exclude(module: 'okhttp')
exclude(module: 'okio')
exclude(module: 'protobuf-java')
exclude(module: 'slf4j-api')
}
implementation(libs.google.guice) {
@ -223,6 +219,7 @@ configure(project(':core')) {
}
dependencies {
implementation enforcedPlatform(project(':platform'))
implementation project(':proto')
implementation project(':assets')
implementation project(':common')
@ -237,7 +234,6 @@ configure(project(':core')) {
implementation libs.google.findbugs
implementation libs.google.gson
implementation libs.google.guava
implementation libs.protobuf.java
implementation libs.commons.codec
implementation libs.commons.io
implementation libs.jopt
@ -261,7 +257,6 @@ configure(project(':core')) {
exclude(module: 'jsr305')
exclude(module: 'okhttp')
exclude(module: 'okio')
exclude(module: 'protobuf-java')
exclude(module: 'slf4j-api')
}
implementation(libs.jsonrpc4j) {
@ -313,6 +308,7 @@ configure(project(':desktop')) {
sourceSets.main.resources.srcDirs += ['src/main/java'] // to copy fxml and css files
dependencies {
implementation enforcedPlatform(project(':platform'))
implementation project(':assets')
implementation project(':common')
implementation project(':proto')
@ -324,7 +320,6 @@ configure(project(':desktop')) {
implementation libs.logback.core
implementation libs.google.gson
implementation libs.google.guava
implementation libs.protobuf.java
implementation libs.jcsv
implementation libs.jfoenix
implementation libs.commons.io
@ -343,7 +338,6 @@ configure(project(':desktop')) {
exclude(module: 'jsr305')
exclude(module: 'okhttp')
exclude(module: 'okio')
exclude(module: 'protobuf-java')
exclude(module: 'slf4j-api')
}
implementation(libs.google.guice) {
@ -373,6 +367,7 @@ configure(project(':seednode')) {
mainClassName = 'bisq.seednode.SeedNodeMain'
dependencies {
implementation enforcedPlatform(project(':platform'))
implementation project(':common')
implementation project(':proto')
implementation project(':p2p')
@ -465,6 +460,7 @@ configure(project(':apitest')) {
}
dependencies {
implementation enforcedPlatform(project(':platform'))
implementation project(':proto')
implementation project(':common')
implementation project(':core')
@ -479,7 +475,6 @@ configure(project(':apitest')) {
implementation libs.logback.core
implementation libs.google.gson
implementation libs.google.guava
implementation libs.protobuf.java
implementation libs.jopt
implementation libs.apache.commons.lang3
implementation libs.slf4j.api
@ -489,7 +484,6 @@ configure(project(':apitest')) {
exclude(module: 'jsr305')
exclude(module: 'okhttp')
exclude(module: 'okio')
exclude(module: 'protobuf-java')
exclude(module: 'slf4j-api')
}
implementation(libs.grpc.protobuf) {

View File

@ -0,0 +1,26 @@
plugins {
id 'base'
id 'jacoco-report-aggregation'
}
repositories {
mavenCentral()
maven { url "https://jitpack.io" }
}
dependencies {
jacocoAggregation project(':apitest')
jacocoAggregation project(':cli')
jacocoAggregation project(':daemon')
jacocoAggregation project(':desktop')
jacocoAggregation project(':seednode')
jacocoAggregation project(':statsnode')
}
reporting {
reports {
testCodeCoverageReport(JacocoCoverageReport) {
testType = TestSuiteType.UNIT_TEST
}
}
}

View File

@ -45,12 +45,14 @@ import javax.inject.Singleton;
import com.google.common.annotations.VisibleForTesting;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import lombok.extern.slf4j.Slf4j;
@ -359,6 +361,17 @@ public class BurningManPresentationService implements DaoStateListener {
.sum();
}
public long getBsqBurnedByMonth(Date dateFilter) {
Set<BurnOutputModel> defaultZeroBurn = new HashSet<>();
defaultZeroBurn.add(new BurnOutputModel(0, 0, 0, "", 0L, 0));
Map<String, BurningManCandidate> burningMen = getBurningManCandidatesByName();
return burningMen.values().stream()
.map(burningMan -> burningMan.getBurnOutputModelsByMonth().getOrDefault(dateFilter, defaultZeroBurn).stream()
.mapToLong(BurnOutputModel::getAmount))
.mapToLong(LongStream::sum)
.sum();
}
public String getGenesisTxId() {
return daoStateService.getGenesisTxId();
}

View File

@ -271,6 +271,15 @@ public class BurningManAccountingService implements DaoSetupService, DaoStateLis
}
public void resyncAccountingDataFromScratch(Runnable resultHandler) {
burningManAccountingStoreService.removeAllBlocks(resultHandler);
}
public void resyncAccountingDataFromResources() {
burningManAccountingStoreService.deleteStorageFile();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Delegates
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -38,15 +38,16 @@ public class AccountingNodeProvider {
@Inject
public AccountingNodeProvider(AccountingLiteNode liteNode,
AccountingFullNode fullNode,
@Named(Config.IS_BM_FULL_NODE) boolean isBmFullNode,
@Named(Config.IS_BM_FULL_NODE) boolean isBmFullNodeFromOptions,
Preferences preferences) {
boolean rpcDataSet = preferences.getRpcUser() != null &&
!preferences.getRpcUser().isEmpty()
&& preferences.getRpcPw() != null &&
!preferences.getRpcPw().isEmpty() &&
String rpcUser = preferences.getRpcUser();
String rpcPw = preferences.getRpcPw();
boolean rpcDataSet = rpcUser != null && !rpcUser.isEmpty() &&
rpcPw != null && !rpcPw.isEmpty() &&
preferences.getBlockNotifyPort() > 0;
if (isBmFullNode && rpcDataSet) {
boolean fullBMAccountingNode = preferences.isFullBMAccountingNode();
if ((fullBMAccountingNode || isBmFullNodeFromOptions) && rpcDataSet) {
accountingNode = fullNode;
} else {
accountingNode = liteNode;

View File

@ -81,6 +81,16 @@ public class BurningManAccountingStore implements PersistableEnvelope {
}
}
public void removeAllBlocks() {
Lock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
blocks.clear();
} finally {
writeLock.unlock();
}
}
public Optional<AccountingBlock> getLastBlock() {
Lock readLock = readWriteLock.readLock();
readLock.lock();

View File

@ -49,6 +49,7 @@ import lombok.extern.slf4j.Slf4j;
@Singleton
public class BurningManAccountingStoreService extends StoreService<BurningManAccountingStore> {
private static final String FILE_NAME = "BurningManAccountingStore_v3";
private volatile boolean removeAllBlocksCalled;
@Inject
public BurningManAccountingStoreService(ResourceDataStoreService resourceDataStoreService,
@ -83,6 +84,9 @@ public class BurningManAccountingStoreService extends StoreService<BurningManAcc
}
public void addIfNewBlock(AccountingBlock block) throws BlockHashNotConnectingException, BlockHeightNotConnectingException {
if (removeAllBlocksCalled) {
return;
}
store.addIfNewBlock(block);
requestPersistence();
}
@ -92,10 +96,27 @@ public class BurningManAccountingStoreService extends StoreService<BurningManAcc
}
public void purgeLastTenBlocks() {
if (removeAllBlocksCalled) {
return;
}
store.purgeLastTenBlocks();
requestPersistence();
}
public void removeAllBlocks(Runnable resultHandler) {
removeAllBlocksCalled = true;
store.removeAllBlocks();
persistenceManager.persistNow(resultHandler);
}
public void deleteStorageFile() {
try {
FileUtil.deleteFileIfExists(Path.of(absolutePathOfStorageDir, FILE_NAME).toFile());
} catch (IOException e) {
e.printStackTrace();
}
}
public Optional<AccountingBlock> getLastBlock() {
return store.getLastBlock();
}

View File

@ -772,7 +772,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
public void setDaoFullNode(boolean value) {
// We only persist if we have not set the program argument
if (config.fullDaoNodeOptionSetExplicitly) {
if (!config.fullDaoNodeOptionSetExplicitly) {
prefPayload.setDaoFullNode(value);
requestPersistence();
}
@ -853,6 +853,11 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
requestPersistence();
}
public void setFullBMAccountingNode(boolean isFullBMAccountingNode) {
prefPayload.setFullBMAccountingNode(isFullBMAccountingNode);
requestPersistence();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter
@ -1023,6 +1028,10 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
return fullAccountingNodeFromOptions || prefPayload.isProcessBurningManAccountingData();
}
public boolean isFullBMAccountingNode() {
return prefPayload.isFullBMAccountingNode();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
@ -1145,6 +1154,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
boolean isProcessBurningManAccountingData();
boolean isFullBMAccountingNode();
void setDaoFullNode(boolean value);
void setRpcUser(String value);
@ -1190,5 +1201,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
void setUserHasRaisedTradeLimit(boolean userHasRaisedTradeLimit);
void setProcessBurningManAccountingData(boolean processBurningManAccountingData);
void setFullBMAccountingNode(boolean isFullBMAccountingNode);
}
}

View File

@ -148,6 +148,10 @@ public final class PreferencesPayload implements PersistableEnvelope {
// Added at 1.9.11
private boolean processBurningManAccountingData = false;
// Added at 1.9.11
private boolean isFullBMAccountingNode = false;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@ -220,7 +224,8 @@ public final class PreferencesPayload implements PersistableEnvelope {
.setUseBitcoinUrisInQrCodes(useBitcoinUrisInQrCodes)
.setUserDefinedTradeLimit(userDefinedTradeLimit)
.setUserHasRaisedTradeLimit(userHasRaisedTradeLimit)
.setProcessBurningManAccountingData(processBurningManAccountingData);
.setProcessBurningManAccountingData(processBurningManAccountingData)
.setIsFullBMAccountingNode(isFullBMAccountingNode);
Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory);
Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((protobuf.TradeCurrency) e.toProtoMessage()));
@ -328,7 +333,8 @@ public final class PreferencesPayload implements PersistableEnvelope {
proto.getUseBitcoinUrisInQrCodes(),
proto.getUserHasRaisedTradeLimit() ? proto.getUserDefinedTradeLimit() : Preferences.INITIAL_TRADE_LIMIT,
proto.getUserHasRaisedTradeLimit(),
proto.getProcessBurningManAccountingData()
proto.getProcessBurningManAccountingData(),
proto.getIsFullBMAccountingNode()
);
}
}

View File

@ -1427,6 +1427,28 @@ setting.preferences.resetAllFlags=Reset all \"Don't show again\" flags
settings.preferences.languageChange=To apply the language change to all screens requires a restart.
settings.preferences.supportLanguageWarning=In case of a dispute, please note that mediation is handled in {0} and arbitration in {1}.
setting.preferences.daoOptions=DAO options
setting.preferences.dao.resyncBMAccFromScratch=Resync from scratch
setting.preferences.dao.resyncBMAccFromScratch.popup=To resync the Burningmen accounting data from scratch you need to run a full Bitcoin node.\n\
It will take considerable time and CPU resources as it resyncs from 2020 when legacy BM started. Depending on your CPU resources that can take 20-40 hours.\n\n\
Are you sure you want to do that?\n\n\
Mostly a resync from latest resource files is sufficient and much faster.\n\n\
If you proceed, after an application restart the Burningmen accounting data will be rebuild from the transactions requested from your Bitcoin node.
setting.preferences.dao.resyncBMAccFromScratch.resync=Resync from scratch and shutdown
setting.preferences.dao.isFullBMAccountingNode=Full BM accounting node
setting.preferences.dao.resyncBMAccFromResources=Resync from resources
setting.preferences.dao.resyncBMAccFromResources.popup=To resync the Burningmen accounting data from resources you \
will reapply the data from resources of your last downloaded Bisq version and load the missing data from the network.\n\
Depending on the age of your last Bisq download that might take a while.\n\n\
Are you sure you want to do that?
setting.preferences.dao.resyncBMAccFromResources.resync=Resync from resources and shutdown
setting.preferences.dao.useFullBMAccountingNode.noDaoMode.popup=To run as full Burningmen accounting node you need to run as full DAO node as well.\n\n\
Please enable first the Full-DAO mode option and config RPC.
setting.preferences.dao.useFullBMAccountingNode.enabledDaoMode.popup=To run as full Burningmen accounting node can take considerable time and CPU resources.\n\n\
A restart is required to enable that change.\n\n\
Do you want to enable full Burningmen accounting mode?.
setting.preferences.dao.resyncFromGenesis.label=Rebuild DAO state from genesis tx
setting.preferences.dao.resyncFromResources.label=Rebuild DAO state from resources
setting.preferences.dao.resyncFromResources.popup=After an application restart the Bisq network governance data will be reloaded from \

View File

@ -675,7 +675,7 @@ public class BurningManView extends ActivatableView<ScrollPane, Void> implements
private void exportToCSV() {
List<String> result = new ArrayList<>();
String separator = "~";
String tableColumns = "Month~BTC Fees~Fees as BSQ~DPT as BTC~DPT as BSQ~Distributed BTC~Distributed BTC as BSQ";
String tableColumns = "Month~BTC Fees~Fees as BSQ~DPT as BTC~DPT as BSQ~Distributed BTC~Distributed BTC as BSQ~BSQ burned";
CSVEntryConverter<String> headerConverter = item -> tableColumns.split(separator);
CSVEntryConverter<String> contentConverter = item -> item.split(separator);
Date now = new Date();
@ -686,6 +686,7 @@ public class BurningManView extends ActivatableView<ScrollPane, Void> implements
long feeAsBsqSum = 0;
long dptAsBsqSum = 0;
long distributedBtcAsBsqSum = 0;
long bsqBurnedSum = 0;
long feeAsBsq, dptAsBsq, distributedBtcAsBsq;
int year = 2023;
int month = 0;
@ -697,7 +698,7 @@ public class BurningManView extends ActivatableView<ScrollPane, Void> implements
Map<Date, Price> averageBsqPriceByMonth = burningManAccountingService.getAverageBsqPriceByMonth();
Optional<Price> price = Optional.ofNullable(averageBsqPriceByMonth.get(date));
long bsqBurned = burningManPresentationService.getBsqBurnedByMonth(date);
List<ReceivedBtcBalanceEntry> distributedBtcBalanceByMonth = burningManAccountingService.getDistributedBtcBalanceByMonth(date)
.collect(Collectors.toList());
long feeAsBtc = distributedBtcBalanceByMonth.stream()
@ -726,7 +727,7 @@ public class BurningManView extends ActivatableView<ScrollPane, Void> implements
feeAsBsqSum += feeAsBsq;
dptAsBsqSum += dptAsBsq;
distributedBtcAsBsqSum += distributedBtcAsBsq;
bsqBurnedSum += bsqBurned;
line = new SimpleDateFormat("MMM yyyy", Locale.ENGLISH).format(date)
+ separator + btcFormatter.formatCoin(Coin.valueOf(feeAsBtc))
@ -734,7 +735,8 @@ public class BurningManView extends ActivatableView<ScrollPane, Void> implements
+ separator + btcFormatter.formatCoin(Coin.valueOf(dptAsBtc))
+ separator + bsqFormatter.formatCoin(Coin.valueOf(dptAsBsq))
+ separator + btcFormatter.formatCoin(Coin.valueOf(distributedBtc))
+ separator + bsqFormatter.formatCoin(Coin.valueOf(distributedBtcAsBsq));
+ separator + bsqFormatter.formatCoin(Coin.valueOf(distributedBtcAsBsq))
+ separator + bsqFormatter.formatCoin(Coin.valueOf(bsqBurned));
result.add(line);
if (++month > 11) {
month = 0;
@ -750,7 +752,8 @@ public class BurningManView extends ActivatableView<ScrollPane, Void> implements
+ separator + btcFormatter.formatCoin(Coin.valueOf(dptAsBtcSum))
+ separator + bsqFormatter.formatCoin(Coin.valueOf(dptAsBsqSum))
+ separator + btcFormatter.formatCoin(Coin.valueOf(distributedBtcSum))
+ separator + bsqFormatter.formatCoin(Coin.valueOf(distributedBtcAsBsqSum));
+ separator + bsqFormatter.formatCoin(Coin.valueOf(distributedBtcAsBsqSum))
+ separator + bsqFormatter.formatCoin(Coin.valueOf(bsqBurnedSum));
result.add(line);
GUIUtil.exportCSV("Burningman_dao_revenue.csv", headerConverter, contentConverter,

View File

@ -51,10 +51,15 @@ import org.bitcoinj.core.Coin;
import org.bitcoinj.core.InsufficientMoneyException;
import org.bitcoinj.core.Transaction;
import com.googlecode.jcsv.writer.CSVEntryConverter;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
@ -62,6 +67,9 @@ import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.beans.InvalidationListener;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
@ -72,7 +80,10 @@ import javafx.collections.transformation.SortedList;
import javafx.util.Callback;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import static bisq.desktop.util.FormBuilder.addButtonAfterGroup;
@ -95,6 +106,7 @@ public class ProofOfBurnView extends ActivatableView<GridPane, Void> implements
private Button burnButton;
private TableView<MyProofOfBurnListItem> myItemsTableView;
private TableView<ProofOfBurnListItem> allTxsTableView;
private Hyperlink exportAsCSVHyperlink;
private final ObservableList<MyProofOfBurnListItem> myItemsObservableList = FXCollections.observableArrayList();
private final SortedList<MyProofOfBurnListItem> myItemsSortedList = new SortedList<>(myItemsObservableList);
@ -153,6 +165,14 @@ public class ProofOfBurnView extends ActivatableView<GridPane, Void> implements
createColumnsForAllTxs();
allTxsTableView.setItems(allItemsSortedList);
exportAsCSVHyperlink = new Hyperlink(Res.get("shared.exportCSV"));
GridPane.setRowIndex(exportAsCSVHyperlink, ++gridRow);
GridPane.setColumnIndex(exportAsCSVHyperlink, 0);
GridPane.setMargin(exportAsCSVHyperlink, new Insets(-5, 0, 0, 0));
GridPane.setHalignment(exportAsCSVHyperlink, HPos.RIGHT);
root.getChildren().add(exportAsCSVHyperlink);
exportAsCSVHyperlink.setOnAction(e -> exportToCSV());
createListeners();
}
@ -301,6 +321,27 @@ public class ProofOfBurnView extends ActivatableView<GridPane, Void> implements
preImageTextField.resetValidation();
}
private void exportToCSV() {
List<String> result = new ArrayList<>();
String separator = "~";
String tableColumns = "Amount~Date~Hash~TxId~Pubkey";
CSVEntryConverter<String> headerConverter = item -> tableColumns.split(separator);
CSVEntryConverter<String> contentConverter = item -> item.split(separator);
for (ProofOfBurnListItem item: allItemsSortedList) {
String line = bsqFormatter.formatCoin(item.getAmount())
+ separator + item.getDateAsString()
+ separator + item.getHashAsHex()
+ separator + item.getTxId()
+ separator + item.getPubKey();
result.add(line);
}
GUIUtil.exportCSV("proofOfBurnTransactions.csv",
headerConverter,
contentConverter,
"",
result,
(Stage) root.getScene().getWindow());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Table columns

View File

@ -24,7 +24,6 @@ import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.ExternalHyperlink;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.components.InputTextField;
import bisq.desktop.components.TitledGroupBg;
import bisq.desktop.components.list.FilterBox;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.overlays.windows.TxDetails;
@ -53,6 +52,7 @@ import bisq.core.util.validation.BtcAddressValidator;
import bisq.network.p2p.P2PService;
import bisq.common.UserThread;
import bisq.common.util.Tuple2;
import bisq.common.util.Tuple3;
import bisq.common.util.Tuple4;
@ -130,7 +130,8 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
private RadioButton useAllInputsRadioButton, useCustomInputsRadioButton, feeExcludedRadioButton, feeIncludedRadioButton;
private Label amountLabel;
private TextField amountTextField, withdrawFromTextField, withdrawToTextField, withdrawMemoTextField, transactionFeeInputTextField;
private TextField amountTextField, withdrawToTextField, withdrawMemoTextField, transactionFeeInputTextField;
private String withdrawFromAddresses = "";
private final BtcWalletService btcWalletService;
private final TradeManager tradeManager;
@ -188,8 +189,6 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
@Override
public void initialize() {
filterBox.initialize(filteredList, tableView);
final TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, rowIndex, 4, Res.get("funds.deposit.withdrawFromWallet"));
titledGroupBg.getStyleClass().add("last");
inputsToggleGroup = new ToggleGroup();
inputsToggleGroupListener = (observable, oldValue, newValue) -> {
@ -202,7 +201,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
Res.get("funds.withdrawal.inputs"),
Res.get("funds.withdrawal.useAllInputs"),
Res.get("funds.withdrawal.useCustomInputs"),
Layout.FIRST_ROW_DISTANCE);
0);
useAllInputsRadioButton = labelRadioButtonRadioButtonTuple3.second;
useCustomInputsRadioButton = labelRadioButtonRadioButtonTuple3.third;
@ -222,14 +221,13 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
feeExcludedRadioButton = feeTuple3.third;
feeIncludedRadioButton = feeTuple3.fourth;
withdrawFromTextField = addTopLabelTextField(gridPane, ++rowIndex,
Res.get("funds.withdrawal.fromLabel", Res.getBaseCurrencyCode())).second;
withdrawToTextField = addTopLabelInputTextField(gridPane, ++rowIndex,
Res.get("funds.withdrawal.toLabel", Res.getBaseCurrencyCode())).second;
withdrawMemoTextField = addTopLabelInputTextField(gridPane, ++rowIndex,
Res.get("funds.withdrawal.memoLabel", Res.getBaseCurrencyCode())).second;
Tuple2<InputTextField, InputTextField> x = addInputTextFieldInputTextField(gridPane, ++rowIndex,
Res.get("funds.withdrawal.toLabel", Res.getBaseCurrencyCode()),
Res.get("funds.withdrawal.memoLabel", Res.getBaseCurrencyCode()));
withdrawToTextField = x.first;
withdrawMemoTextField = x.second;
withdrawToTextField.setPrefWidth(Layout.MIN_WINDOW_WIDTH);
withdrawMemoTextField.setPrefWidth(Layout.MIN_WINDOW_WIDTH);
Tuple3<Label, InputTextField, ToggleButton> customFeeTuple = addTopLabelInputTextFieldSlideToggleButtonRight(gridPane, ++rowIndex,
Res.get("funds.withdrawal.txFee"), Res.get("funds.withdrawal.useCustomFeeValue"));
@ -442,7 +440,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
String messageText = Res.get("shared.sendFundsDetailsWithFee",
formatter.formatCoinWithCode(sendersAmount),
withdrawFromTextField.getText(),
withdrawFromAddresses,
withdrawToAddress,
formatter.formatCoinWithCode(fee),
(double) fee.longValue() / txVsize, // no risk of div/0 since txVsize is always positive
@ -522,25 +520,17 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
amountAsCoin = Coin.ZERO;
totalAvailableAmountOfSelectedItems = Coin.ZERO;
amountTextField.setText("");
withdrawFromTextField.setText("");
withdrawFromAddresses = "";
}
if (selectedItems.size() == 1) {
withdrawFromTextField.setText(selectedItems.stream().findAny().get().getAddressEntry().getAddressString());
withdrawFromTextField.setTooltip(null);
withdrawFromAddresses = selectedItems.stream().findAny().get().getAddressEntry().getAddressString();
} else {
int abbr = Math.max(10, 66 / selectedItems.size());
String addressesShortened = selectedItems.stream()
.map(e -> StringUtils.abbreviate(e.getAddressString(), abbr))
.collect(Collectors.joining(", "));
String text = Res.get("funds.withdrawal.withdrawMultipleAddresses", addressesShortened);
withdrawFromTextField.setText(text);
String addresses = selectedItems.stream()
.map(WithdrawalListItem::getAddressString)
.collect(Collectors.joining(",\n"));
String tooltipText = Res.get("funds.withdrawal.withdrawMultipleAddresses.tooltip", addresses);
withdrawFromTextField.setTooltip(new Tooltip(tooltipText));
withdrawFromAddresses = Res.get("funds.withdrawal.withdrawMultipleAddresses", addressesShortened);
}
} else {
reset();
@ -605,9 +595,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
}
private void reset() {
withdrawFromTextField.setText("");
withdrawFromTextField.setPromptText(Res.get("funds.withdrawal.selectAddress"));
withdrawFromTextField.setTooltip(null);
withdrawFromAddresses = "";
totalAvailableAmountOfSelectedItems = Coin.ZERO;
amountAsCoin = Coin.ZERO;
@ -752,5 +740,3 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
});
}
}

View File

@ -1169,6 +1169,10 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
button.setStyle(CssTheme.isDarkTheme() ? "-fx-text-fill: white" : "-fx-text-fill: #444444");
button.setOnAction(e -> onRemoveOpenOffer(offer));
if (offer.isBsqSwapOffer()) {
button2.setManaged(false);
button2.setVisible(false);
} else {
iconView2.setId("image-edit");
button2.updateText(Res.get("shared.edit"));
button2.setId(null);
@ -1176,6 +1180,7 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
button2.setOnAction(e -> onEditOpenOffer(offer));
button2.setManaged(true);
button2.setVisible(true);
}
} else {
boolean isSellOffer = OfferViewUtil.isShownAsSellOffer(offer);
iconView.setId(isSellOffer ? "image-buy-white" : "image-sell-white");

View File

@ -35,6 +35,7 @@ import bisq.desktop.util.validation.BtcValidator;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.dao.DaoFacade;
import bisq.core.dao.burningman.accounting.BurningManAccountingService;
import bisq.core.dao.governance.asset.AssetService;
import bisq.core.filter.Filter;
import bisq.core.filter.FilterManager;
@ -122,6 +123,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
@FxmlView
public class PreferencesView extends ActivatableViewAndModel<GridPane, PreferencesViewModel> {
private final User user;
private final BurningManAccountingService burningManAccountingService;
private final CoinFormatter formatter;
private TextField btcExplorerTextField, bsqExplorerTextField;
private ComboBox<String> userLanguageComboBox;
@ -131,7 +133,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private ToggleButton showOwnOffersInOfferBook, useAnimations, useDarkMode, sortMarketCurrenciesNumerically,
avoidStandbyMode, useCustomFee, autoConfirmXmrToggle, hideNonAccountPaymentMethodsToggle, denyApiTakerToggle,
notifyOnPreReleaseToggle, isDaoFullNodeToggleButton,
fullModeDaoMonitorToggleButton, useBitcoinUrisToggle, tradeLimitToggle, processBurningManAccountingDataToggleButton;
fullModeDaoMonitorToggleButton, useBitcoinUrisToggle, tradeLimitToggle, processBurningManAccountingDataToggleButton,
isFullBMAccountingDataNodeToggleButton;
private int gridRow = 0;
private int displayCurrenciesGridRowIndex = 0;
private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, ignoreDustThresholdInputTextField,
@ -147,6 +150,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private final OfferFilterService offerFilterService;
private final FilterManager filterManager;
private final DaoFacade daoFacade;
private final boolean isBmFullNodeFromOptions;
private final File storageDir;
private ListView<FiatCurrency> fiatCurrenciesListView;
@ -154,6 +158,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private ListView<CryptoCurrency> cryptoCurrenciesListView;
private ComboBox<CryptoCurrency> cryptoCurrenciesComboBox;
private Button resetDontShowAgainButton, resyncDaoFromGenesisButton, resyncDaoFromResourcesButton,
resyncBMAccFromScratchButton, resyncBMAccFromResourcesButton,
editCustomBtcExplorer, editCustomBsqExplorer;
private ObservableList<String> languageCodes;
private ObservableList<Country> countries;
@ -169,7 +174,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private ChangeListener<Boolean> deviationFocusedListener, bsqAverageTrimThresholdFocusedListener;
private ChangeListener<Boolean> useCustomFeeCheckboxListener;
private ChangeListener<Number> transactionFeeChangeListener;
private final boolean daoOptionsSet;
private final boolean daoFullModeFromOptionsSet;
private final boolean displayStandbyModeFeature;
private ChangeListener<Filter> filterChangeListener;
@ -188,13 +193,16 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
DaoFacade daoFacade,
Config config,
User user,
BurningManAccountingService burningManAccountingService,
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
@Named(Config.IS_BM_FULL_NODE) boolean isBmFullNodeFromOptions,
@Named(Config.RPC_USER) String rpcUser,
@Named(Config.RPC_PASSWORD) String rpcPassword,
@Named(Config.RPC_BLOCK_NOTIFICATION_PORT) int rpcBlockNotificationPort,
@Named(Config.STORAGE_DIR) File storageDir) {
super(model);
this.user = user;
this.burningManAccountingService = burningManAccountingService;
this.formatter = formatter;
this.preferences = preferences;
this.feeService = feeService;
@ -202,11 +210,12 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
this.offerFilterService = offerFilterService;
this.filterManager = filterManager;
this.daoFacade = daoFacade;
this.isBmFullNodeFromOptions = isBmFullNodeFromOptions;
this.storageDir = storageDir;
daoOptionsSet = config.fullDaoNodeOptionSetExplicitly &&
!rpcUser.isEmpty() &&
!rpcPassword.isEmpty() &&
rpcBlockNotificationPort != Config.UNSPECIFIED_PORT;
daoFullModeFromOptionsSet = config.fullDaoNodeOptionSetExplicitly &&
rpcUser != null && !rpcUser.isEmpty() &&
rpcPassword != null && !rpcPassword.isEmpty() &&
rpcBlockNotificationPort > Config.UNSPECIFIED_PORT;
this.displayStandbyModeFeature = Utilities.isLinux() || Utilities.isOSX() || Utilities.isWindows();
}
@ -676,12 +685,27 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
}
private void initializeDaoOptions() {
int rowSpan = 6;
daoOptionsTitledGroupBg = addTitledGroupBg(root, ++gridRow, rowSpan,
daoOptionsTitledGroupBg = addTitledGroupBg(root, ++gridRow, 8,
Res.get("setting.preferences.daoOptions"), Layout.GROUP_DISTANCE);
processBurningManAccountingDataToggleButton = addSlideToggleButton(root, gridRow, Res.get("setting.preferences.dao.processBurningManAccountingData"), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
isFullBMAccountingDataNodeToggleButton = addSlideToggleButton(root, ++gridRow, Res.get("setting.preferences.dao.isFullBMAccountingNode"));
isFullBMAccountingDataNodeToggleButton.setManaged(preferences.isProcessBurningManAccountingData());
isFullBMAccountingDataNodeToggleButton.setVisible(preferences.isProcessBurningManAccountingData());
resyncBMAccFromScratchButton = addButton(root, ++gridRow, Res.get("setting.preferences.dao.resyncBMAccFromScratch"));
resyncBMAccFromScratchButton.setMaxWidth(Double.MAX_VALUE);
GridPane.setHgrow(resyncBMAccFromScratchButton, Priority.ALWAYS);
resyncBMAccFromScratchButton.setManaged(preferences.isProcessBurningManAccountingData());
resyncBMAccFromScratchButton.setVisible(preferences.isProcessBurningManAccountingData());
resyncBMAccFromResourcesButton = addButton(root, ++gridRow, Res.get("setting.preferences.dao.resyncBMAccFromResources"));
resyncBMAccFromResourcesButton.setMaxWidth(Double.MAX_VALUE);
GridPane.setHgrow(resyncBMAccFromResourcesButton, Priority.ALWAYS);
resyncBMAccFromResourcesButton.setManaged(preferences.isProcessBurningManAccountingData());
resyncBMAccFromResourcesButton.setVisible(preferences.isProcessBurningManAccountingData());
fullModeDaoMonitorToggleButton = addSlideToggleButton(root, ++gridRow,
Res.get("setting.preferences.dao.fullModeDaoMonitor"));
@ -1118,6 +1142,36 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
}
});
boolean isDaoModeEnabled = isDaoModeEnabled();
boolean isFullBMAccountingNode = (isBmFullNodeFromOptions || preferences.isFullBMAccountingNode()) && isDaoModeEnabled;
preferences.setFullBMAccountingNode(isFullBMAccountingNode);
isFullBMAccountingDataNodeToggleButton.setSelected(isFullBMAccountingNode);
isFullBMAccountingDataNodeToggleButton.setOnAction(e -> {
if (isFullBMAccountingDataNodeToggleButton.isSelected()) {
if (isDaoModeEnabled()) {
new Popup().attention(Res.get("setting.preferences.dao.useFullBMAccountingNode.enabledDaoMode.popup"))
.actionButtonText(Res.get("shared.yes"))
.onAction(() -> {
preferences.setFullBMAccountingNode(true);
UserThread.runAfter(BisqApp.getShutDownHandler(), 500, TimeUnit.MILLISECONDS);
})
.closeButtonText(Res.get("shared.cancel"))
.onClose(() -> isFullBMAccountingDataNodeToggleButton.setSelected(false))
.show();
} else {
new Popup().attention(Res.get("setting.preferences.dao.useFullBMAccountingNode.noDaoMode.popup"))
.actionButtonText(Res.get("shared.ok"))
.onAction(() -> isFullBMAccountingDataNodeToggleButton.setSelected(false))
.onClose(() -> isFullBMAccountingDataNodeToggleButton.setSelected(false))
.show();
}
} else {
preferences.setFullBMAccountingNode(false);
}
});
fullModeDaoMonitorToggleButton.setSelected(preferences.isUseFullModeDaoMonitor());
fullModeDaoMonitorToggleButton.setOnAction(e -> {
preferences.setUseFullModeDaoMonitor(fullModeDaoMonitorToggleButton.isSelected());
@ -1133,8 +1187,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
}
});
boolean daoFullNode = preferences.isDaoFullNode();
isDaoFullNodeToggleButton.setSelected(daoFullNode);
isDaoFullNodeToggleButton.setSelected(isDaoModeEnabled);
bsqAverageTrimThresholdTextField.textProperty().addListener(bsqAverageTrimThresholdListener);
bsqAverageTrimThresholdTextField.focusedProperty().addListener(bsqAverageTrimThresholdFocusedListener);
@ -1142,9 +1195,10 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
String rpcUser = preferences.getRpcUser();
String rpcPw = preferences.getRpcPw();
int blockNotifyPort = preferences.getBlockNotifyPort();
if (daoFullNode && (rpcUser == null || rpcUser.isEmpty() ||
rpcPw == null || rpcPw.isEmpty() ||
blockNotifyPort <= 0)) {
boolean rpcDataFromPrefSet = rpcUser != null && !rpcUser.isEmpty() &&
rpcPw != null && !rpcPw.isEmpty() &&
blockNotifyPort > 0;
if (!daoFullModeFromOptionsSet && !rpcDataFromPrefSet) {
log.warn("You have full DAO node selected but have not provided the rpc username, password and " +
"block notify port. We reset daoFullNode to false");
isDaoFullNodeToggleButton.setSelected(false);
@ -1175,6 +1229,23 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
.closeButtonText(Res.get("shared.cancel"))
.show());
resyncBMAccFromScratchButton.setOnAction(e ->
new Popup().attention(Res.get("setting.preferences.dao.resyncBMAccFromScratch.popup"))
.actionButtonText(Res.get("setting.preferences.dao.resyncBMAccFromScratch.resync"))
.onAction(() -> burningManAccountingService.resyncAccountingDataFromScratch(BisqApp::getShutDownHandler))
.closeButtonText(Res.get("shared.cancel"))
.show());
resyncBMAccFromResourcesButton.setOnAction(e ->
new Popup().attention(Res.get("setting.preferences.dao.resyncBMAccFromResources.popup"))
.actionButtonText(Res.get("setting.preferences.dao.resyncBMAccFromResources.resync"))
.onAction(() -> {
burningManAccountingService.resyncAccountingDataFromResources();
UserThread.runAfter(BisqApp.getShutDownHandler(), 500, TimeUnit.MILLISECONDS);
})
.closeButtonText(Res.get("shared.cancel"))
.show());
isDaoFullNodeToggleButton.setOnAction(e -> {
String key = "daoFullModeInfoShown";
if (isDaoFullNodeToggleButton.isSelected() && preferences.showAgain(key)) {
@ -1191,7 +1262,6 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
.width(800)
.show();
}
updateDaoFields();
});
@ -1200,6 +1270,17 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
blockNotifyPortTextField.textProperty().addListener(blockNotifyPortListener);
}
private boolean isDaoModeEnabled() {
String rpcUser = preferences.getRpcUser();
String rpcPw = preferences.getRpcPw();
int blockNotifyPort = preferences.getBlockNotifyPort();
boolean rpcDataFromPrefSet = rpcUser != null && !rpcUser.isEmpty() &&
rpcPw != null && !rpcPw.isEmpty() &&
blockNotifyPort > 0;
boolean daoFullModeFromPrefSet = rpcDataFromPrefSet && preferences.isDaoFullNode();
return daoFullModeFromPrefSet || daoFullModeFromOptionsSet;
}
private void activateAutoConfirmPreferences() {
preferences.findAutoConfirmSettings("XMR").ifPresent(autoConfirmSettings -> {
autoConfirmXmrToggle.setSelected(autoConfirmSettings.isEnabled());
@ -1240,7 +1321,14 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private void updateDaoFields() {
boolean isDaoFullNode = isDaoFullNodeToggleButton.isSelected();
GridPane.setRowSpan(daoOptionsTitledGroupBg, isDaoFullNode ? 9 : 6);
int rowSpan = 9;
if (isDaoFullNode) {
rowSpan += 3;
}
if (preferences.isProcessBurningManAccountingData()) {
rowSpan += 3;
}
GridPane.setRowSpan(daoOptionsTitledGroupBg, rowSpan);
rpcUserTextField.setVisible(isDaoFullNode);
rpcUserTextField.setManaged(isDaoFullNode);
rpcPwTextField.setVisible(isDaoFullNode);
@ -1252,12 +1340,14 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
rpcUserTextField.clear();
rpcPwTextField.clear();
blockNotifyPortTextField.clear();
preferences.setFullBMAccountingNode(false);
isFullBMAccountingDataNodeToggleButton.setSelected(false);
}
isDaoFullNodeToggleButton.setDisable(daoOptionsSet);
rpcUserTextField.setDisable(daoOptionsSet);
rpcPwTextField.setDisable(daoOptionsSet);
blockNotifyPortTextField.setDisable(daoOptionsSet);
isDaoFullNodeToggleButton.setDisable(daoFullModeFromOptionsSet);
rpcUserTextField.setDisable(daoFullModeFromOptionsSet);
rpcPwTextField.setDisable(daoFullModeFromOptionsSet);
blockNotifyPortTextField.setDisable(daoFullModeFromOptionsSet);
}
@ -1304,9 +1394,12 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
private void deactivateDaoPreferences() {
processBurningManAccountingDataToggleButton.setOnAction(null);
isFullBMAccountingDataNodeToggleButton.setOnAction(null);
fullModeDaoMonitorToggleButton.setOnAction(null);
resyncDaoFromResourcesButton.setOnAction(null);
resyncDaoFromGenesisButton.setOnAction(null);
resyncBMAccFromScratchButton.setOnAction(null);
resyncBMAccFromResourcesButton.setOnAction(null);
bsqAverageTrimThresholdTextField.textProperty().removeListener(bsqAverageTrimThresholdListener);
bsqAverageTrimThresholdTextField.focusedProperty().removeListener(bsqAverageTrimThresholdFocusedListener);
isDaoFullNodeToggleButton.setOnAction(null);

View File

@ -1197,6 +1197,43 @@
<sha256 value="b36137376c4b3fcf76dc337e2a1bc5b691a2ac1aa966ab5d26209a93812fa57d" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jacoco" name="org.jacoco.agent" version="0.8.8">
<artifact name="org.jacoco.agent-0.8.8.jar">
<sha256 value="072ecbd496896623899a696fff12c01c1615f737616d2792e6d0e10cdf8a610d" origin="Generated by Gradle"/>
</artifact>
<artifact name="org.jacoco.agent-0.8.8.pom">
<sha256 value="7dd13c80aff315032983357c650a887d6fdb4c8a8870b207bb4802c49809e7b4" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jacoco" name="org.jacoco.ant" version="0.8.8">
<artifact name="org.jacoco.ant-0.8.8.jar">
<sha256 value="02e33bd2c48dc0be67c2fea84d43beececfd400da6797c58153253d4c30aca15" origin="Generated by Gradle"/>
</artifact>
<artifact name="org.jacoco.ant-0.8.8.pom">
<sha256 value="fafff75819609030f4626509313c0861428c2c26c8d36e9a8938334a04478909" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jacoco" name="org.jacoco.build" version="0.8.8">
<artifact name="org.jacoco.build-0.8.8.pom">
<sha256 value="f4ce0b1285fd24fc6c772f42857298315904dde8fd5677267a0fad5ff9ce2aef" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jacoco" name="org.jacoco.core" version="0.8.8">
<artifact name="org.jacoco.core-0.8.8.jar">
<sha256 value="474c782f809d88924713dfdbf0acb79d330f904be576484803463d0465611643" origin="Generated by Gradle"/>
</artifact>
<artifact name="org.jacoco.core-0.8.8.pom">
<sha256 value="f5fab5a48df823b83c0ea35026032368cc9b81800efb257cc7a5928298fee225" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jacoco" name="org.jacoco.report" version="0.8.8">
<artifact name="org.jacoco.report-0.8.8.jar">
<sha256 value="2c129110f3e3fcaa1f8179578ea3894586199cb0826be5c7790278084c9622a9" origin="Generated by Gradle"/>
</artifact>
<artifact name="org.jacoco.report-0.8.8.pom">
<sha256 value="5213af2916bb2690be871917d82a0f9c2ba1e88b796a59343fc03df8ae138716" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.javamodularity" name="moduleplugin" version="1.8.2">
<artifact name="moduleplugin-1.8.2.jar">
<sha256 value="f079128b30745db5392c555cf186a97b7face40471ddfce1a0930d1a0400d696" origin="Generated by Gradle"/>
@ -1717,6 +1754,14 @@
<sha256 value="2d85484e0c0dd935e38edec52a33267ea1d50eb06d4c2ffb90d444c089571f86" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.ow2.asm" name="asm" version="9.2">
<artifact name="asm-9.2.jar">
<sha256 value="b9d4fe4d71938df38839f0eca42aaaa64cf8b313d678da036f0cb3ca199b47f5" origin="Generated by Gradle"/>
</artifact>
<artifact name="asm-9.2.pom">
<sha256 value="dfb12a1b224bf01be1fd604020466f894241bcb645dcce395edd8cd6f8a50df4" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.ow2.asm" name="asm-analysis" version="7.0-beta">
<artifact name="asm-analysis-7.0-beta.jar">
<sha256 value="4d2b20a1fb44acb33b0ddb80be58b2ad7838c1fb520282a655a1217b3c6acf19" origin="Generated by Gradle"/>
@ -1725,6 +1770,14 @@
<sha256 value="7a068ba0c921fe69824731f6a1b14f86ff0828a0c5941e5c24b6b501e2f6e69f" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.ow2.asm" name="asm-analysis" version="9.2">
<artifact name="asm-analysis-9.2.jar">
<sha256 value="878fbe521731c072d14d2d65b983b1beae6ad06fda0007b6a8bae81f73f433c4" origin="Generated by Gradle"/>
</artifact>
<artifact name="asm-analysis-9.2.pom">
<sha256 value="773cc1a2bfc14c6c4a979c51a075c0234a0bf694fc3abe4facf454f37a145f1b" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.ow2.asm" name="asm-commons" version="7.0-beta">
<artifact name="asm-commons-7.0-beta.jar">
<sha256 value="3d8ec2534b883541b966e6dde9004967d34f7311789028afc92e2e066867dac4" origin="Generated by Gradle"/>
@ -1733,6 +1786,14 @@
<sha256 value="2b30b9d132f43dfba6ebced3c9661b1b5c60187dfc4d5cb7e759224fea7a279e" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.ow2.asm" name="asm-commons" version="9.2">
<artifact name="asm-commons-9.2.jar">
<sha256 value="be4ce53138a238bb522cd781cf91f3ba5ce2f6ca93ec62d46a162a127225e0a6" origin="Generated by Gradle"/>
</artifact>
<artifact name="asm-commons-9.2.pom">
<sha256 value="02824e839f2a2f0e72959fdd30b4897240f05afc43de42d7ba0b18437601c070" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.ow2.asm" name="asm-tree" version="7.0-beta">
<artifact name="asm-tree-7.0-beta.jar">
<sha256 value="a2ec5b55ceb359c324ad48b15e912e33c75889237413976d1505fe32ecde82f2" origin="Generated by Gradle"/>
@ -1741,6 +1802,14 @@
<sha256 value="56e37d6b54903ca842eef8fe6c8863bc7f405186bc43e74a21575a3f2428ba70" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.ow2.asm" name="asm-tree" version="9.2">
<artifact name="asm-tree-9.2.jar">
<sha256 value="aabf9bd23091a4ebfc109c1f3ee7cf3e4b89f6ba2d3f51c5243f16b3cffae011" origin="Generated by Gradle"/>
</artifact>
<artifact name="asm-tree-9.2.pom">
<sha256 value="f61f3ebea5520ddf19f452b03c426c7231bdd8a81d7ac28765cb5271225ac378" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.pcollections" name="pcollections" version="2.1.2">
<artifact name="pcollections-2.1.2.jar">
<sha256 value="29c8ffcc5c6a97f059941148593ad00fe2cdf78af1d88d46bcf0d1bb703606c2" origin="Generated by Gradle"/>

9
platform/build.gradle Normal file
View File

@ -0,0 +1,9 @@
plugins {
id 'java-platform'
}
dependencies {
constraints {
api libs.protobuf.java
}
}

View File

@ -3,8 +3,10 @@ plugins {
}
apply plugin: 'com.google.protobuf'
apply plugin: 'idea'
dependencies {
implementation enforcedPlatform(project(':platform'))
annotationProcessor libs.lombok
compileOnly libs.javax.annotation
compileOnly libs.lombok
@ -23,21 +25,16 @@ dependencies {
}
}
sourceSets.main.java.srcDirs += [
'build/generated/source/proto/main/grpc',
'build/generated/source/proto/main/java'
]
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:${protocVersion}"
artifact = "com.google.protobuf:protoc:3.19.1"
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
artifact = "io.grpc:protoc-gen-grpc-java:1.42.1"
}
}
generateProtoTasks {
all()*.plugins { grpc {} }
ofSourceSet('main')*.plugins { grpc {} }
}
}

View File

@ -1972,6 +1972,7 @@ message PreferencesPayload {
int64 user_defined_trade_limit = 67;
bool user_has_raised_trade_limit = 68;
bool process_burning_man_accounting_data = 69;
bool is_full_b_m_accounting_node = 70;
}
message AutoConfirmSettings {

View File

@ -16,5 +16,7 @@ include 'desktop'
include 'seednode'
include 'statsnode'
include 'apitest'
include 'platform'
include 'code-coverage-report'
rootProject.name = 'bisq'