Show changes in BSQ Supply over time

This commit is contained in:
xyzmaker123 2022-03-14 17:24:08 +01:00 committed by Christoph Atteneder
parent 72b56a2dcf
commit 5fb1167a28
No known key found for this signature in database
GPG Key ID: CD5DC1C529CDFD3B
7 changed files with 112 additions and 3 deletions

View File

@ -39,6 +39,8 @@ import bisq.core.dao.state.model.governance.ParamChange;
import bisq.core.util.ParsingUtils;
import bisq.core.util.coin.BsqFormatter;
import bisq.common.util.Tuple2;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
@ -1044,6 +1046,44 @@ public class DaoStateService implements DaoSetupService {
return getTxOutputsByTxOutputType(TxOutputType.PROOF_OF_BURN_OP_RETURN_OUTPUT);
}
public Set<Tuple2<Long, Long>> getTotalBsqSupply() {
return new HashSet<>() {{
add(new Tuple2<>(1555340856L, 372540100L)); // Cycle 01 - 15 APR 2019
add(new Tuple2<>(1558083590L, 374541600L)); // Cycle 02 - 17 MAY 2019
add(new Tuple2<>(1560771266L, 375464400L)); // Cycle 03 - 17 JUN 2019
add(new Tuple2<>(1563347672L, 374153300L)); // Cycle 04 - 17 JUL 2019
add(new Tuple2<>(1566009595L, 378733200L)); // Cycle 05 - 16 AUG 2019
add(new Tuple2<>(1568643566L, 385347900L)); // Cycle 06 - 16 SEP 2019
add(new Tuple2<>(1571349571L, 391167400L)); // Cycle 07 - 17 OCT 2019
add(new Tuple2<>(1574180991L, 398324900L)); // Cycle 08 - 19 NOV 2019
add(new Tuple2<>(1576966522L, 394719900L)); // Cycle 09 - 21 DEC 2019
add(new Tuple2<>(1579613568L, 397643900L)); // Cycle 10 - 21 JAN 2020
add(new Tuple2<>(1582399054L, 401189100L)); // Cycle 11 - 22 FEB 2020
add(new Tuple2<>(1585342220L, 403141900L)); // Cycle 12 - 27 MAR 2020
add(new Tuple2<>(1588025030L, 399991400L)); // Cycle 13
add(new Tuple2<>(1591004931L, 411136400L)); // Cycle 14
add(new Tuple2<>(1593654027L, 420908500L)); // Cycle 15
add(new Tuple2<>(1596407074L, 421255800L)); // Cycle 16
add(new Tuple2<>(1599175867L, 430737100L)); // Cycle 17
add(new Tuple2<>(1601861442L, 429305600L)); // Cycle 18
add(new Tuple2<>(1604845863L, 431446100L)); // Cycle 19 - 8 NOV 2020
add(new Tuple2<>(1610233200L, 422663200L)); // Cycle 20
add(new Tuple2<>(1612911600L, 449935500L)); // Cycle 21
add(new Tuple2<>(1615762800L, 446547000L)); // Cycle 22
add(new Tuple2<>(1618437600L, 441126800L)); // Cycle 23
add(new Tuple2<>(1621288800L, 442629900L)); // Cycle 24
add(new Tuple2<>(1624572000L, 434999300L)); // Cycle 25
add(new Tuple2<>(1627596000L, 437237400L)); // Cycle 26
add(new Tuple2<>(1630188000L, 431897700L)); // Cycle 27
add(new Tuple2<>(1632952800L, 433282600L)); // Cycle 28
add(new Tuple2<>(1635544800L, 431026400L)); // Cycle 29 - 29 SEP 2021
add(new Tuple2<>(1638399600L, 424954400L)); // Cycle 30
add(new Tuple2<>(1641078000L, 438560500L)); // Cycle 31
add(new Tuple2<>(1643756400L, 433806200L)); // Cycle 32
add(new Tuple2<>(1646555748L, 431667800L)); // Cycle 33
}};
}
///////////////////////////////////////////////////////////////////////////////////////////
// Listeners

View File

@ -2600,6 +2600,7 @@ dao.factsAndFigures.supply.compRequestIssueAmount=BSQ issued for compensation re
dao.factsAndFigures.supply.reimbursementAmount=BSQ issued for reimbursement requests
dao.factsAndFigures.supply.totalIssued=Total issued BSQ
dao.factsAndFigures.supply.totalBurned=Total burned BSQ
dao.factsAndFigures.supply.totalBsqSupply=Total BSQ supply
dao.factsAndFigures.supply.chart.tradeFee.toolTip={0}\n{1}
dao.factsAndFigures.supply.burnt=BSQ burnt

View File

@ -22,6 +22,7 @@ import bisq.desktop.common.model.ActivatableDataModel;
import java.time.Instant;
import java.time.temporal.TemporalAdjuster;
import java.util.Comparator;
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.function.Predicate;

View File

@ -87,7 +87,7 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
private SplitPane timelineNavigation;
protected NumberAxis xAxis, yAxis;
protected LineChart<Number, Number> chart;
private HBox timelineLabels, legendBox2;
private HBox timelineLabels, legendBox2, legendBox3;
private final ToggleGroup timeIntervalToggleGroup = new ToggleGroup();
protected final Set<XYChart.Series<Number, Number>> activeSeries = new HashSet<>();
@ -157,6 +157,11 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
legendBox2 = initLegendsAndGetLegendBox(seriesForLegend2);
}
Collection<XYChart.Series<Number, Number>> seriesForLegend3 = getSeriesForLegend3();
if (seriesForLegend3 != null && !seriesForLegend3.isEmpty()) {
legendBox3 = initLegendsAndGetLegendBox(seriesForLegend3);
}
// Set active series/legends
defineAndAddActiveSeries();
@ -176,6 +181,9 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
if (legendBox2 != null) {
VBox.setMargin(legendBox2, new Insets(-20, rightPadding, 0, paddingLeft));
}
if (legendBox3 != null) {
VBox.setMargin(legendBox3, new Insets(-20, rightPadding, 0, paddingLeft));
}
if (model.getDividerPositions()[0] == 0 && model.getDividerPositions()[1] == 1) {
resetTimeNavigation();
@ -192,6 +200,10 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
VBox.setMargin(legendBox2, new Insets(-20, paddingRight, 0, paddingLeft));
timelineNavigationBox.getChildren().add(legendBox2);
}
if (legendBox3 != null) {
VBox.setMargin(legendBox3, new Insets(-20, paddingRight, 0, paddingLeft));
timelineNavigationBox.getChildren().add(legendBox3);
}
root.getChildren().addAll(timeIntervalBox, chart, timelineNavigationBox);
// Listeners
@ -241,6 +253,7 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
addLegendToggleActionHandlers(getSeriesForLegend1());
addLegendToggleActionHandlers(getSeriesForLegend2());
addLegendToggleActionHandlers(getSeriesForLegend3());
addActionHandlersToDividers();
}
@ -258,6 +271,7 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
removeLegendToggleActionHandlers(getSeriesForLegend1());
removeLegendToggleActionHandlers(getSeriesForLegend2());
removeLegendToggleActionHandlers(getSeriesForLegend3());
removeActionHandlersToDividers();
// clear data, reset states. We keep timeInterval state though
@ -541,6 +555,10 @@ public abstract class ChartView<T extends ChartViewModel<? extends ChartDataMode
return null;
}
protected Collection<XYChart.Series<Number, Number>> getSeriesForLegend3() {
return null;
}
protected abstract void defineAndAddActiveSeries();
protected void activateSeries(XYChart.Series<Number, Number> series) {

View File

@ -24,6 +24,8 @@ import bisq.core.dao.state.model.blockchain.Tx;
import bisq.core.dao.state.model.governance.Issuance;
import bisq.core.dao.state.model.governance.IssuanceType;
import bisq.common.util.Tuple2;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -45,7 +47,7 @@ import lombok.extern.slf4j.Slf4j;
public class DaoChartDataModel extends ChartDataModel {
private final DaoStateService daoStateService;
private final Function<Issuance, Long> blockTimeOfIssuanceFunction;
private Map<Long, Long> totalIssuedByInterval, compensationByInterval, reimbursementByInterval,
private Map<Long, Long> totalSupplyByInterval, totalIssuedByInterval, compensationByInterval, reimbursementByInterval,
totalBurnedByInterval, bsqTradeFeeByInterval, proofOfBurnByInterval;
@ -68,6 +70,7 @@ public class DaoChartDataModel extends ChartDataModel {
@Override
protected void invalidateCache() {
totalSupplyByInterval = null;
totalIssuedByInterval = null;
compensationByInterval = null;
reimbursementByInterval = null;
@ -111,6 +114,19 @@ public class DaoChartDataModel extends ChartDataModel {
// Data for chart
///////////////////////////////////////////////////////////////////////////////////////////
Map<Long, Long> getTotalSupplyByInterval() {
if (totalSupplyByInterval != null) {
return totalSupplyByInterval;
}
totalSupplyByInterval = getTotalBsqSupplyByInterval(
daoStateService.getTotalBsqSupply(),
getDateFilter()
);
return totalSupplyByInterval;
}
Map<Long, Long> getTotalIssuedByInterval() {
if (totalIssuedByInterval != null) {
return totalIssuedByInterval;
@ -179,6 +195,12 @@ public class DaoChartDataModel extends ChartDataModel {
// Aggregated collection data by interval
///////////////////////////////////////////////////////////////////////////////////////////
private Map<Long, Long> getTotalBsqSupplyByInterval(Set<Tuple2<Long, Long>> bsqSupply, Predicate<Long> dateFilter) {
return bsqSupply.stream()
.filter(i -> dateFilter.test(i.first))
.collect(Collectors.toMap(i -> i.first, i -> i.second));
}
private Map<Long, Long> getIssuedBsqByInterval(Set<Issuance> issuanceSet, Predicate<Long> dateFilter) {
return issuanceSet.stream()
.collect(Collectors.groupingBy(issuance ->

View File

@ -46,7 +46,7 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
private final LongProperty proofOfBurnAmountProperty = new SimpleLongProperty();
private XYChart.Series<Number, Number> seriesBsqTradeFee, seriesProofOfBurn, seriesCompensation,
seriesReimbursement, seriesTotalIssued, seriesTotalBurned;
seriesReimbursement, seriesTotalSupply, seriesTotalIssued, seriesTotalBurned;
@Inject
@ -90,6 +90,11 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
return List.of(seriesTotalBurned, seriesBsqTradeFee, seriesProofOfBurn);
}
@Override
protected Collection<XYChart.Series<Number, Number>> getSeriesForLegend3() {
return List.of(seriesTotalSupply);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Timeline navigation
@ -130,6 +135,10 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
seriesProofOfBurn = new XYChart.Series<>();
seriesProofOfBurn.setName(Res.get("dao.factsAndFigures.supply.proofOfBurn"));
seriesIndexMap.put(getSeriesId(seriesProofOfBurn), 5);
seriesTotalSupply = new XYChart.Series<>();
seriesTotalSupply.setName(Res.get("dao.factsAndFigures.supply.totalBsqSupply"));
seriesIndexMap.put(getSeriesId(seriesTotalSupply), 6);
}
@Override
@ -176,6 +185,11 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
allFutures.add(task6Done);
applyProofOfBurn(task6Done);
}
if (activeSeries.contains(seriesTotalSupply)) {
CompletableFuture<Boolean> task6ADone = new CompletableFuture<>();
allFutures.add(task6ADone);
applyTotalSupply(task6ADone);
}
CompletableFuture<Boolean> task7Done = new CompletableFuture<>();
allFutures.add(task7Done);
@ -216,6 +230,15 @@ public class DaoChartView extends ChartView<DaoChartViewModel> {
return CompletableFutureUtils.allOf(allFutures).thenApply(e -> true);
}
private void applyTotalSupply(CompletableFuture<Boolean> completeFuture) {
model.getTotalSupplyChartData()
.whenComplete((data, t) ->
mapToUserThread(() -> {
seriesTotalSupply.getData().setAll(data);
completeFuture.complete(true);
}));
}
private void applyTotalIssued(CompletableFuture<Boolean> completeFuture) {
model.getTotalIssuedChartData()
.whenComplete((data, t) ->

View File

@ -54,6 +54,10 @@ public class DaoChartViewModel extends ChartViewModel<DaoChartDataModel> {
// Chart data
///////////////////////////////////////////////////////////////////////////////////////////
CompletableFuture<List<XYChart.Data<Number, Number>>> getTotalSupplyChartData() {
return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getTotalSupplyByInterval()));
}
CompletableFuture<List<XYChart.Data<Number, Number>>> getTotalIssuedChartData() {
return CompletableFuture.supplyAsync(() -> toChartData(dataModel.getTotalIssuedByInterval()));
}