Add supply change series.

Remove BsqSupplyChange. Use existing methods for supply calculation
(existing method was incorrect as far I understand).
This commit is contained in:
chimp1984 2022-06-29 18:50:43 +02:00 committed by Christoph Atteneder
parent e08f7b6c09
commit 70e2f7c53b
No known key found for this signature in database
GPG Key ID: CD5DC1C529CDFD3B
11 changed files with 76 additions and 93 deletions

View File

@ -30,7 +30,6 @@ import bisq.core.dao.state.model.blockchain.TxOutput;
import bisq.core.dao.state.model.blockchain.TxOutputKey;
import bisq.core.dao.state.model.blockchain.TxOutputType;
import bisq.core.dao.state.model.blockchain.TxType;
import bisq.core.dao.state.model.governance.BsqSupplyChange;
import bisq.core.dao.state.model.governance.Cycle;
import bisq.core.dao.state.model.governance.DecryptedBallotsWithMerits;
import bisq.core.dao.state.model.governance.EvaluatedProposal;
@ -1050,18 +1049,6 @@ public class DaoStateService implements DaoSetupService {
return getTxOutputsByTxOutputType(TxOutputType.PROOF_OF_BURN_OP_RETURN_OUTPUT);
}
public Stream<BsqSupplyChange> getBsqSupplyChanges() {
Stream<BsqSupplyChange> issued = getIssuanceItems()
.stream()
.map(issuance -> new BsqSupplyChange(getBlockTime(issuance.getChainHeight()), issuance.getAmount()));
Stream<BsqSupplyChange> burned = getUnorderedTxStream()
.filter(tx -> tx.getTxType() == TxType.PROOF_OF_BURN || tx.getTxType() == TxType.PAY_TRADE_FEE)
.map(tx -> new BsqSupplyChange(tx.getTime(), -tx.getBurntBsq()));
return Stream.concat(issued, burned);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Listeners

View File

@ -1,30 +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.core.dao.state.model.governance;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public class BsqSupplyChange {
@Getter
long time;
@Getter
long value;
}

View File

@ -2624,7 +2624,10 @@ dao.factsAndFigures.supply.totalBurned=Total burned BSQ
dao.factsAndFigures.supply.totalBurned.tooltip=Total burned BSQ is the sum of BSQ trade fees and all 'Proof of Burn' transactions.\n\
'Proof of Burn' transactions started in Dec 2019.
dao.factsAndFigures.supply.totalSupply=Total BSQ supply
dao.factsAndFigures.supply.totalSupply.tooltip=Total BSQ supply is the sum of all issues BSQ on top of the Genesis issuance and the total burned BSQ.
dao.factsAndFigures.supply.totalSupply.tooltip=Total BSQ supply is 'Change of BSQ supply' + genesis issuance
dao.factsAndFigures.supply.supplyChange=Change of BSQ supply
dao.factsAndFigures.supply.supplyChange.tooltip=Change of BSQ supply reflects the change of all issued BSQ (compensation requests + reimbursement requests)\n\
minus all burned BSQ (BSQ trade fees, Burned BSQ from BTC trade fees, burned BSQ from arbitration cases).
dao.factsAndFigures.supply.chart.tradeFee.toolTip={0}\n{1}
dao.factsAndFigures.supply.burnt=BSQ burnt

View File

@ -1877,6 +1877,16 @@ textfield */
-fx-background-color: -bs-chart-dao-line13, -bs-chart-dao-line13;
}
#charts-dao .default-color13.chart-series-line {
-fx-stroke: -bs-chart-dao-line14;
}
#charts-dao .default-color13.chart-line-symbol {
-fx-background-color: -bs-chart-dao-line14, -bs-chart-dao-line14;
}
#charts-legend-toggle0 {
-jfx-toggle-color: -bs-chart-dao-line1
}
@ -1929,6 +1939,10 @@ textfield */
-jfx-toggle-color: -bs-chart-dao-line13;
}
#charts-legend-toggle13 {
-jfx-toggle-color: -bs-chart-dao-line14;
}
#charts-dao .chart-series-line {
-fx-stroke-width: 2px;
}

View File

@ -400,7 +400,7 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
hBox.setSpacing(10);
collection.forEach(series -> {
AutoTooltipSlideToggleButton toggle = new AutoTooltipSlideToggleButton();
toggle.setMinWidth(220);
toggle.setMinWidth(300);
toggle.setAlignment(Pos.TOP_LEFT);
String seriesId = getSeriesId(series);
legendToggleBySeriesName.put(seriesId, toggle);

View File

@ -81,7 +81,7 @@ public class TemporalAdjusterModel {
}
}
protected TemporalAdjuster temporalAdjuster = Interval.DAY.getAdjuster();
protected TemporalAdjuster temporalAdjuster = Interval.MONTH.getAdjuster();
public void setTemporalAdjuster(TemporalAdjuster temporalAdjuster) {
this.temporalAdjuster = temporalAdjuster;

View File

@ -21,7 +21,6 @@ import bisq.desktop.components.chart.ChartDataModel;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.model.blockchain.Tx;
import bisq.core.dao.state.model.governance.BsqSupplyChange;
import bisq.core.dao.state.model.governance.Issuance;
import bisq.core.dao.state.model.governance.IssuanceType;
@ -33,18 +32,15 @@ import javax.inject.Singleton;
import java.time.Instant;
import java.util.Collection;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
@ -56,7 +52,7 @@ public class DaoChartDataModel extends ChartDataModel {
private final DaoStateService daoStateService;
private final Function<Issuance, Long> blockTimeOfIssuanceFunction;
private Map<Long, Long> totalSupplyByInterval, totalIssuedByInterval, compensationByInterval,
private Map<Long, Long> totalSupplyByInterval, supplyChangeByInterval, totalIssuedByInterval, compensationByInterval,
reimbursementByInterval, reimbursementByIntervalAfterTagging,
totalBurnedByInterval, bsqTradeFeeByInterval, bsqTradeFeeByIntervalAfterTagging,
proofOfBurnByInterval, proofOfBurnFromBtcFeesByInterval, proofOfBurnFromArbitrationByInterval,
@ -86,6 +82,7 @@ public class DaoChartDataModel extends ChartDataModel {
@Override
protected void invalidateCache() {
totalSupplyByInterval = null;
supplyChangeByInterval = null;
totalIssuedByInterval = null;
compensationByInterval = null;
reimbursementByInterval = null;
@ -134,18 +131,6 @@ public class DaoChartDataModel extends ChartDataModel {
// Data for chart
///////////////////////////////////////////////////////////////////////////////////////////
Map<Long, Long> getTotalSupplyByInterval() {
if (totalSupplyByInterval != null) {
return totalSupplyByInterval;
}
totalSupplyByInterval = getTotalSupplyByInterval(
daoStateService.getBsqSupplyChanges(),
getDateFilter()
);
return totalSupplyByInterval;
}
Map<Long, Long> getArbitrationDiffByInterval() {
if (arbitrationDiffByInterval != null) {
return arbitrationDiffByInterval;
@ -294,33 +279,32 @@ public class DaoChartDataModel extends ChartDataModel {
return proofOfBurnFromArbitrationByInterval;
}
Map<Long, Long> getTotalSupplyByInterval() {
if (totalSupplyByInterval != null) {
return totalSupplyByInterval;
}
long genesisValue = daoStateService.getGenesisTotalSupply().value;
totalSupplyByInterval = getSupplyChangeByInterval().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> genesisValue + e.getValue()));
return totalSupplyByInterval;
}
Map<Long, Long> getSupplyChangeByInterval() {
if (supplyChangeByInterval != null) {
return supplyChangeByInterval;
}
Map<Long, Long> issued = getTotalIssuedByInterval();
Map<Long, Long> burned = getTotalBurnedByInterval();
supplyChangeByInterval = getMergedMap(issued, burned, (a, b) -> a - b);
return supplyChangeByInterval;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Aggregated collection data by interval
///////////////////////////////////////////////////////////////////////////////////////////
private Map<Long, Long> getTotalSupplyByInterval(Stream<BsqSupplyChange> bsqSupplyChanges,
Predicate<Long> dateFilter) {
AtomicLong supply = new AtomicLong(DaoEconomyHistoricalData.TOTAL_SUPPLY_BY_CYCLE_DATE.get(1555340856L));
return bsqSupplyChanges
.collect(Collectors.groupingBy(tx -> toTimeInterval(Instant.ofEpochMilli(tx.getTime()))))
.entrySet()
.stream()
.sorted(Comparator.comparingLong(Map.Entry::getKey))
.map(e -> new BsqSupplyChange(
e.getKey(),
supply.addAndGet(e
.getValue()
.stream()
.mapToLong(BsqSupplyChange::getValue)
.sum()
))
)
.filter(t -> dateFilter.test(t.getTime()))
.collect(Collectors.toMap(BsqSupplyChange::getTime, BsqSupplyChange::getValue));
}
private Map<Long, Long> getIssuedBsqByInterval(Set<Issuance> issuanceSet, Predicate<Long> dateFilter) {
return issuanceSet.stream()
.collect(Collectors.groupingBy(issuance ->
@ -377,14 +361,13 @@ public class DaoChartDataModel extends ChartDataModel {
///////////////////////////////////////////////////////////////////////////////////////////
// We did not use the reimbursement requests initially (but the compensation requests) because the limits
// have been too low. Over time it got mixed in compensation requests and reimbursement requests.
// To reflect that we use static data derived from the Github data. For new data we do not need that anymore
// have been too low. Over time, it got mixed in compensation requests and reimbursement requests.
// To reflect that we use static data derived from the GitHub data. For new data we do not need that anymore
// as we have clearly separated that now. In case we have duplicate data for a months we use the static data.
private static class DaoEconomyHistoricalData {
// Key is start date of the cycle in epoch seconds, value is reimbursement amount
public final static Map<Long, Long> REIMBURSEMENTS_BY_CYCLE_DATE = new HashMap<>();
public final static Map<Long, Long> COMPENSATIONS_BY_CYCLE_DATE = new HashMap<>();
public final static Map<Long, Long> TOTAL_SUPPLY_BY_CYCLE_DATE = new HashMap<>();
static {
REIMBURSEMENTS_BY_CYCLE_DATE.put(1571349571L, 60760L);
@ -420,8 +403,6 @@ public class DaoChartDataModel extends ChartDataModel {
COMPENSATIONS_BY_CYCLE_DATE.put(1599175867L, 6086442L);
COMPENSATIONS_BY_CYCLE_DATE.put(1601861442L, 5615973L);
COMPENSATIONS_BY_CYCLE_DATE.put(1604845863L, 7782667L);
TOTAL_SUPPLY_BY_CYCLE_DATE.put(1555340856L, 372540100L);
}
}
}

View File

@ -50,7 +50,7 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
private final LongProperty proofOfBurnAmountProperty = new SimpleLongProperty();
private XYChart.Series<Number, Number> seriesBsqTradeFee, seriesProofOfBurn, seriesCompensation,
seriesReimbursement, seriesTotalSupply, seriesTotalIssued, seriesTotalBurned,
seriesReimbursement, seriesTotalSupply, seriesSupplyChange, seriesTotalIssued, seriesTotalBurned,
seriesTotalTradeFees, seriesProofOfBurnFromBtcFees,
seriesProofOfBurnFromArbitration, seriesArbitrationDiff,
seriesReimbursementAfterTagging, seriesBsqTradeFeeAfterTagging;
@ -111,7 +111,7 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
}
protected Collection<XYChart.Series<Number, Number>> getSeriesForLegend5() {
return List.of(seriesTotalSupply);
return List.of(seriesSupplyChange, seriesTotalSupply);
}
@ -182,6 +182,10 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
seriesBsqTradeFeeAfterTagging = new XYChart.Series<>();
seriesBsqTradeFeeAfterTagging.setName(Res.get("dao.factsAndFigures.supply.bsqTradeFeeAfterTagging"));
seriesIndexMap.put(getSeriesId(seriesBsqTradeFeeAfterTagging), 12);
seriesSupplyChange = new XYChart.Series<>();
seriesSupplyChange.setName(Res.get("dao.factsAndFigures.supply.supplyChange"));
seriesIndexMap.put(getSeriesId(seriesSupplyChange), 13);
}
@Override
@ -209,7 +213,11 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
tooltip.setShowDelay(Duration.millis(100));
Tooltip.install(toggle, tooltip);
} else if (series.equals(seriesTotalSupply)) {
Tooltip tooltip = new Tooltip(Res.get("dao.factsAndFigures.supply.totalSupply.tooltip"));
Tooltip tooltip = new Tooltip(Res.get("dao.factsAndFigures.supply.supplyChange.tooltip"));
tooltip.setShowDelay(Duration.millis(100));
Tooltip.install(toggle, tooltip);
} else if (series.equals(seriesSupplyChange)) {
Tooltip tooltip = new Tooltip(Res.get("dao.factsAndFigures.supply.supplyChange.tooltip"));
tooltip.setShowDelay(Duration.millis(100));
Tooltip.install(toggle, tooltip);
}
@ -258,6 +266,11 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
allFutures.add(future);
applyTotalSupply(future);
}
if (activeSeries.contains(seriesSupplyChange)) {
CompletableFuture<Boolean> future = new CompletableFuture<>();
allFutures.add(future);
applySupplyChange(future);
}
if (activeSeries.contains(seriesTotalTradeFees)) {
CompletableFuture<Boolean> future = new CompletableFuture<>();
allFutures.add(future);
@ -338,6 +351,15 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
}));
}
private void applySupplyChange(CompletableFuture<Boolean> completeFuture) {
model.getSupplyChangeChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesSupplyChange.getData().setAll(data);
completeFuture.complete(true);
}));
}
private void applyTotalTradeFees(CompletableFuture<Boolean> completeFuture) {
model.getTotalTradeFeesChartData()
.whenComplete((data, t) ->

View File

@ -58,6 +58,10 @@ public class DaoChartViewModel extends ChartViewModel<DaoChartDataModel> {
return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getTotalSupplyByInterval()));
}
CompletableFuture<List<XYChart.Data<Number, Number>>> getSupplyChangeChartData() {
return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getSupplyChangeByInterval()));
}
CompletableFuture<List<XYChart.Data<Number, Number>>> getTotalTradeFeesChartData() {
return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getTotalTradeFeesByInterval()));
}

View File

@ -152,6 +152,7 @@
-bs-chart-dao-line11: #ff3939;
-bs-chart-dao-line12: #1a6b66;
-bs-chart-dao-line13: #b6239c;
-bs-chart-dao-line14: #0052ff;
/* Monero orange color code */
-xmr-orange: #f26822;

View File

@ -119,6 +119,7 @@
-bs-chart-dao-line11: #ff3939;
-bs-chart-dao-line12: #1a6b66;
-bs-chart-dao-line13: #b6239c;
-bs-chart-dao-line14: #0052ff;
/* Monero orange color code */
-xmr-orange: #f26822;