mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 18:03:12 +01:00
Add supply and transactions sections
This commit is contained in:
parent
b00f96d06e
commit
44764d1fb7
@ -421,6 +421,10 @@ public class BSFormatter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String formatPrice(Price price, boolean appendCurrencyCode) {
|
||||||
|
return formatPrice(price, fiatPriceFormat, true);
|
||||||
|
}
|
||||||
|
|
||||||
public String formatPrice(Price price) {
|
public String formatPrice(Price price) {
|
||||||
return formatPrice(price, fiatPriceFormat, false);
|
return formatPrice(price, fiatPriceFormat, false);
|
||||||
}
|
}
|
||||||
|
@ -124,6 +124,10 @@ public class BsqFormatter extends BSFormatter {
|
|||||||
return super.formatCoin(satoshi, coinFormat);
|
return super.formatCoin(satoshi, coinFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String formatBSQSatoshisWithCode(long satoshi) {
|
||||||
|
return super.formatCoinWithCode(satoshi, coinFormat);
|
||||||
|
}
|
||||||
|
|
||||||
public String formatBTCSatoshis(long satoshi) {
|
public String formatBTCSatoshis(long satoshi) {
|
||||||
return super.formatCoin(satoshi, btcCoinFormat);
|
return super.formatCoin(satoshi, btcCoinFormat);
|
||||||
}
|
}
|
||||||
|
@ -198,6 +198,7 @@ shared.actions=Actions
|
|||||||
shared.buyerUpperCase=Buyer
|
shared.buyerUpperCase=Buyer
|
||||||
shared.sellerUpperCase=Seller
|
shared.sellerUpperCase=Seller
|
||||||
shared.new=NEW
|
shared.new=NEW
|
||||||
|
shared.new=NEW
|
||||||
|
|
||||||
####################################################################
|
####################################################################
|
||||||
# UI views
|
# UI views
|
||||||
@ -1756,29 +1757,6 @@ dao.wallet.menuItem.receive=Receive
|
|||||||
dao.wallet.menuItem.transactions=Transactions
|
dao.wallet.menuItem.transactions=Transactions
|
||||||
|
|
||||||
dao.wallet.dashboard.myBalance=My wallet balance
|
dao.wallet.dashboard.myBalance=My wallet balance
|
||||||
dao.wallet.dashboard.distribution=Distribution of all BSQ
|
|
||||||
dao.wallet.dashboard.locked=Global state of locked BSQ
|
|
||||||
dao.wallet.dashboard.market=Market data
|
|
||||||
dao.wallet.dashboard.genesis=Genesis transaction
|
|
||||||
dao.wallet.dashboard.txDetails=BSQ transactions statistics
|
|
||||||
dao.wallet.dashboard.genesisBlockHeight=Genesis block height
|
|
||||||
dao.wallet.dashboard.genesisTxId=Genesis transaction ID
|
|
||||||
dao.wallet.dashboard.genesisIssueAmount=BSQ issued at genesis transaction
|
|
||||||
dao.wallet.dashboard.compRequestIssueAmount=BSQ issued for compensation requests
|
|
||||||
dao.wallet.dashboard.reimbursementAmount=BSQ issued for reimbursement requests
|
|
||||||
dao.wallet.dashboard.availableAmount=Total available BSQ
|
|
||||||
dao.wallet.dashboard.burntAmount=Burned BSQ (fees)
|
|
||||||
dao.wallet.dashboard.totalLockedUpAmount=Locked up in bonds
|
|
||||||
dao.wallet.dashboard.totalUnlockingAmount=Unlocking BSQ from bonds
|
|
||||||
dao.wallet.dashboard.totalUnlockedAmount=Unlocked BSQ from bonds
|
|
||||||
dao.wallet.dashboard.totalConfiscatedAmount=Confiscated BSQ from bonds
|
|
||||||
dao.wallet.dashboard.allTx=No. of all BSQ transactions
|
|
||||||
dao.wallet.dashboard.utxo=No. of all unspent transaction outputs
|
|
||||||
dao.wallet.dashboard.compensationIssuanceTx=No. of all compensation request issuance transactions
|
|
||||||
dao.wallet.dashboard.reimbursementIssuanceTx=No. of all reimbursement request issuance transactions
|
|
||||||
dao.wallet.dashboard.burntTx=No. of all fee payments transactions
|
|
||||||
dao.wallet.dashboard.price=Latest BSQ/BTC trade price (in Bisq)
|
|
||||||
dao.wallet.dashboard.marketCap=Market capitalisation (based on trade price)
|
|
||||||
|
|
||||||
dao.wallet.receive.fundYourWallet=Your BSQ receive address
|
dao.wallet.receive.fundYourWallet=Your BSQ receive address
|
||||||
dao.wallet.receive.bsqAddress=BSQ wallet address (Fresh unused address)
|
dao.wallet.receive.bsqAddress=BSQ wallet address (Fresh unused address)
|
||||||
@ -1940,6 +1918,37 @@ dao.monitor.blindVote.table.hash=Hash of blind vote state
|
|||||||
dao.monitor.blindVote.table.prev=Previous hash
|
dao.monitor.blindVote.table.prev=Previous hash
|
||||||
dao.monitor.blindVote.table.numBlindVotes=No. blind votes
|
dao.monitor.blindVote.table.numBlindVotes=No. blind votes
|
||||||
|
|
||||||
|
dao.factsAndFigures.menuItem.supply=Supply
|
||||||
|
dao.factsAndFigures.menuItem.transactions=Transactions
|
||||||
|
|
||||||
|
dao.factsAndFigures.dashboard.marketPrice=Market data
|
||||||
|
dao.factsAndFigures.dashboard.price=Latest BSQ/BTC trade price (in Bisq)
|
||||||
|
dao.factsAndFigures.dashboard.marketCap=Market capitalisation (based on trade price)
|
||||||
|
dao.factsAndFigures.dashboard.availableAmount=Total available BSQ
|
||||||
|
|
||||||
|
dao.factsAndFigures.supply.issued=BSQ issued
|
||||||
|
dao.factsAndFigures.supply.genesisIssueAmount=BSQ issued at genesis transaction
|
||||||
|
dao.factsAndFigures.supply.compRequestIssueAmount=BSQ issued for compensation requests
|
||||||
|
dao.factsAndFigures.supply.reimbursementAmount=BSQ issued for reimbursement requests
|
||||||
|
|
||||||
|
dao.factsAndFigures.supply.burnt=BSQ burnt
|
||||||
|
|
||||||
|
dao.factsAndFigures.supply.locked=Global state of locked BSQ
|
||||||
|
dao.factsAndFigures.supply.totalLockedUpAmount=Locked up in bonds
|
||||||
|
dao.factsAndFigures.supply.totalUnlockingAmount=Unlocking BSQ from bonds
|
||||||
|
dao.factsAndFigures.supply.totalUnlockedAmount=Unlocked BSQ from bonds
|
||||||
|
dao.factsAndFigures.supply.totalConfiscatedAmount=Confiscated BSQ from bonds
|
||||||
|
dao.factsAndFigures.supply.burntAmount=Burned BSQ (fees)
|
||||||
|
|
||||||
|
dao.factsAndFigures.transactions.genesis=Genesis transaction
|
||||||
|
dao.factsAndFigures.transactions.genesisBlockHeight=Genesis block height
|
||||||
|
dao.factsAndFigures.transactions.genesisTxId=Genesis transaction ID
|
||||||
|
dao.factsAndFigures.transactions.txDetails=BSQ transactions statistics
|
||||||
|
dao.factsAndFigures.transactions.allTx=No. of all BSQ transactions
|
||||||
|
dao.factsAndFigures.transactions.utxo=No. of all unspent transaction outputs
|
||||||
|
dao.factsAndFigures.transactions.compensationIssuanceTx=No. of all compensation request issuance transactions
|
||||||
|
dao.factsAndFigures.transactions.reimbursementIssuanceTx=No. of all reimbursement request issuance transactions
|
||||||
|
dao.factsAndFigures.transactions.burntTx=No. of all fee payments transactions
|
||||||
|
|
||||||
####################################################################
|
####################################################################
|
||||||
# Windows
|
# Windows
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||||
* License for more details.
|
* License for more supply.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
@ -28,7 +28,8 @@ import bisq.desktop.components.MenuItem;
|
|||||||
import bisq.desktop.main.MainView;
|
import bisq.desktop.main.MainView;
|
||||||
import bisq.desktop.main.dao.DaoView;
|
import bisq.desktop.main.dao.DaoView;
|
||||||
import bisq.desktop.main.dao.economy.dashboard.BsqDashboardView;
|
import bisq.desktop.main.dao.economy.dashboard.BsqDashboardView;
|
||||||
import bisq.desktop.main.dao.economy.details.DetailsView;
|
import bisq.desktop.main.dao.economy.supply.SupplyView;
|
||||||
|
import bisq.desktop.main.dao.economy.transactions.BSQTransactionsView;
|
||||||
|
|
||||||
import bisq.core.locale.Res;
|
import bisq.core.locale.Res;
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ public class EconomyView extends ActivatableViewAndModel {
|
|||||||
private final ViewLoader viewLoader;
|
private final ViewLoader viewLoader;
|
||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
|
|
||||||
private MenuItem dashboard, details;
|
private MenuItem dashboard, supply, transactions;
|
||||||
private Navigation.Listener listener;
|
private Navigation.Listener listener;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@ -81,20 +82,24 @@ public class EconomyView extends ActivatableViewAndModel {
|
|||||||
toggleGroup = new ToggleGroup();
|
toggleGroup = new ToggleGroup();
|
||||||
List<Class<? extends View>> baseNavPath = Arrays.asList(MainView.class, DaoView.class, EconomyView.class);
|
List<Class<? extends View>> baseNavPath = Arrays.asList(MainView.class, DaoView.class, EconomyView.class);
|
||||||
dashboard = new MenuItem(navigation, toggleGroup, Res.get("shared.dashboard"), BsqDashboardView.class, baseNavPath);
|
dashboard = new MenuItem(navigation, toggleGroup, Res.get("shared.dashboard"), BsqDashboardView.class, baseNavPath);
|
||||||
details = new MenuItem(navigation, toggleGroup, Res.get("shared.details"), DetailsView.class, baseNavPath);
|
supply = new MenuItem(navigation, toggleGroup, Res.get("dao.factsAndFigures.menuItem.supply"), SupplyView.class, baseNavPath);
|
||||||
leftVBox.getChildren().addAll(dashboard, details);
|
transactions = new MenuItem(navigation, toggleGroup, Res.get("dao.factsAndFigures.menuItem.transactions"), BSQTransactionsView.class, baseNavPath);
|
||||||
|
|
||||||
|
leftVBox.getChildren().addAll(dashboard, supply, transactions);
|
||||||
|
|
||||||
// TODO just until DAO is enabled
|
// TODO just until DAO is enabled
|
||||||
if (!DevEnv.isDaoActivated()) {
|
if (!DevEnv.isDaoActivated()) {
|
||||||
dashboard.setDisable(true);
|
dashboard.setDisable(true);
|
||||||
details.setDisable(true);
|
supply.setDisable(true);
|
||||||
|
transactions.setDisable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
dashboard.activate();
|
dashboard.activate();
|
||||||
details.activate();
|
supply.activate();
|
||||||
|
transactions.activate();
|
||||||
|
|
||||||
navigation.addListener(listener);
|
navigation.addListener(listener);
|
||||||
ViewPath viewPath = navigation.getCurrentPath();
|
ViewPath viewPath = navigation.getCurrentPath();
|
||||||
@ -116,6 +121,8 @@ public class EconomyView extends ActivatableViewAndModel {
|
|||||||
navigation.removeListener(listener);
|
navigation.removeListener(listener);
|
||||||
|
|
||||||
dashboard.deactivate();
|
dashboard.deactivate();
|
||||||
|
supply.deactivate();
|
||||||
|
transactions.deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadView(Class<? extends View> viewClass) {
|
private void loadView(Class<? extends View> viewClass) {
|
||||||
@ -123,6 +130,7 @@ public class EconomyView extends ActivatableViewAndModel {
|
|||||||
content.getChildren().setAll(view.getRoot());
|
content.getChildren().setAll(view.getRoot());
|
||||||
|
|
||||||
if (view instanceof BsqDashboardView) toggleGroup.selectToggle(dashboard);
|
if (view instanceof BsqDashboardView) toggleGroup.selectToggle(dashboard);
|
||||||
else if (view instanceof DetailsView) toggleGroup.selectToggle(details);
|
else if (view instanceof SupplyView) toggleGroup.selectToggle(supply);
|
||||||
|
else if (view instanceof BSQTransactionsView) toggleGroup.selectToggle(transactions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
xmlns:fx="http://javafx.com/fxml">
|
xmlns:fx="http://javafx.com/fxml">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints percentWidth="50"/>
|
<ColumnConstraints percentWidth="50"/>
|
||||||
<ColumnConstraints minWidth="10" maxWidth="5"/>
|
|
||||||
<ColumnConstraints percentWidth="50"/>
|
<ColumnConstraints percentWidth="50"/>
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
|
@ -19,30 +19,94 @@ package bisq.desktop.main.dao.economy.dashboard;
|
|||||||
|
|
||||||
import bisq.desktop.common.view.ActivatableView;
|
import bisq.desktop.common.view.ActivatableView;
|
||||||
import bisq.desktop.common.view.FxmlView;
|
import bisq.desktop.common.view.FxmlView;
|
||||||
|
import bisq.desktop.components.TitledGroupBg;
|
||||||
|
import bisq.desktop.util.FormBuilder;
|
||||||
|
|
||||||
import bisq.core.dao.DaoFacade;
|
import bisq.core.dao.DaoFacade;
|
||||||
import bisq.core.dao.state.DaoStateListener;
|
import bisq.core.dao.state.DaoStateListener;
|
||||||
|
import bisq.core.dao.state.DaoStateService;
|
||||||
import bisq.core.dao.state.model.blockchain.Block;
|
import bisq.core.dao.state.model.blockchain.Block;
|
||||||
|
import bisq.core.dao.state.model.governance.IssuanceType;
|
||||||
|
import bisq.core.locale.Res;
|
||||||
|
import bisq.core.monetary.Price;
|
||||||
import bisq.core.provider.price.PriceFeedService;
|
import bisq.core.provider.price.PriceFeedService;
|
||||||
|
import bisq.core.trade.statistics.TradeStatistics2;
|
||||||
|
import bisq.core.trade.statistics.TradeStatisticsManager;
|
||||||
import bisq.core.user.Preferences;
|
import bisq.core.user.Preferences;
|
||||||
|
import bisq.core.util.BSFormatter;
|
||||||
import bisq.core.util.BsqFormatter;
|
import bisq.core.util.BsqFormatter;
|
||||||
|
|
||||||
|
import bisq.common.util.Tuple3;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.Coin;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import javafx.scene.chart.AreaChart;
|
||||||
|
import javafx.scene.chart.NumberAxis;
|
||||||
|
import javafx.scene.chart.XYChart;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Side;
|
||||||
|
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
|
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.FormatStyle;
|
||||||
|
import java.time.temporal.TemporalAdjuster;
|
||||||
|
import java.time.temporal.TemporalAdjusters;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||||
|
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
|
||||||
|
import static bisq.desktop.util.Layout.FIRST_ROW_DISTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import java.sql.Date;
|
||||||
|
|
||||||
@FxmlView
|
@FxmlView
|
||||||
public class BsqDashboardView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
public class BsqDashboardView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||||
|
|
||||||
|
private static final String DAY = "day";
|
||||||
|
private static final Map<String, TemporalAdjuster> ADJUSTERS = new HashMap<>();
|
||||||
|
|
||||||
private final DaoFacade daoFacade;
|
private final DaoFacade daoFacade;
|
||||||
|
private final TradeStatisticsManager tradeStatisticsManager;
|
||||||
private final PriceFeedService priceFeedService;
|
private final PriceFeedService priceFeedService;
|
||||||
|
private final DaoStateService daoStateService;
|
||||||
private final Preferences preferences;
|
private final Preferences preferences;
|
||||||
private final BsqFormatter bsqFormatter;
|
private final BsqFormatter bsqFormatter;
|
||||||
|
private final BSFormatter btcFormatter;
|
||||||
|
|
||||||
private ChangeListener<Number> priceChangeListener;
|
private ChangeListener<Number> priceChangeListener;
|
||||||
|
|
||||||
|
private AreaChart bsqPriceChart;
|
||||||
|
private XYChart.Series<Number, Number> seriesBSQAdded, seriesBSQBurnt;
|
||||||
|
private XYChart.Series<Number, Number> seriesBSQPrice;
|
||||||
|
|
||||||
|
private TextField marketCapTextField, priceTextField, availableAmountTextField;
|
||||||
|
|
||||||
|
private Coin availableAmount;
|
||||||
|
|
||||||
|
private int gridRow = 0;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor, lifecycle
|
// Constructor, lifecycle
|
||||||
@ -50,20 +114,52 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BsqDashboardView(DaoFacade daoFacade,
|
private BsqDashboardView(DaoFacade daoFacade,
|
||||||
|
TradeStatisticsManager tradeStatisticsManager,
|
||||||
PriceFeedService priceFeedService,
|
PriceFeedService priceFeedService,
|
||||||
|
DaoStateService daoStateService,
|
||||||
Preferences preferences,
|
Preferences preferences,
|
||||||
BsqFormatter bsqFormatter) {
|
BsqFormatter bsqFormatter,
|
||||||
|
BSFormatter btcFormatter) {
|
||||||
this.daoFacade = daoFacade;
|
this.daoFacade = daoFacade;
|
||||||
|
this.tradeStatisticsManager = tradeStatisticsManager;
|
||||||
this.priceFeedService = priceFeedService;
|
this.priceFeedService = priceFeedService;
|
||||||
|
this.daoStateService = daoStateService;
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
this.bsqFormatter = bsqFormatter;
|
this.bsqFormatter = bsqFormatter;
|
||||||
|
this.btcFormatter = btcFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
|
||||||
|
ADJUSTERS.put(DAY, TemporalAdjusters.ofDateAdjuster(d -> d));
|
||||||
|
|
||||||
|
createKPIs();
|
||||||
|
createChart();
|
||||||
|
|
||||||
priceChangeListener = (observable, oldValue, newValue) -> updatePrice();
|
priceChangeListener = (observable, oldValue, newValue) -> updatePrice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createKPIs() {
|
||||||
|
|
||||||
|
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, 5, Res.get("dao.factsAndFigures.dashboard.marketPrice"));
|
||||||
|
titledGroupBg.getStyleClass().add("last");
|
||||||
|
|
||||||
|
Tuple3<Label, TextField, VBox> marketPriceTuple = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.factsAndFigures.dashboard.price"),
|
||||||
|
FIRST_ROW_DISTANCE);
|
||||||
|
priceTextField = marketPriceTuple.second;
|
||||||
|
|
||||||
|
GridPane.setColumnSpan(marketPriceTuple.third, 2);
|
||||||
|
|
||||||
|
marketCapTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||||
|
Res.get("dao.factsAndFigures.dashboard.marketCap")).second;
|
||||||
|
|
||||||
|
availableAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, 1,
|
||||||
|
Res.get("dao.factsAndFigures.dashboard.availableAmount")).second;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
daoFacade.addBsqStateListener(this);
|
daoFacade.addBsqStateListener(this);
|
||||||
@ -71,15 +167,16 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||||||
|
|
||||||
updateWithBsqBlockChainData();
|
updateWithBsqBlockChainData();
|
||||||
updatePrice();
|
updatePrice();
|
||||||
|
updateChartData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void deactivate() {
|
protected void deactivate() {
|
||||||
daoFacade.removeBsqStateListener(this);
|
daoFacade.removeBsqStateListener(this);
|
||||||
priceFeedService.updateCounterProperty().removeListener(priceChangeListener);
|
priceFeedService.updateCounterProperty().removeListener(priceChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// DaoStateListener
|
// DaoStateListener
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -94,10 +191,123 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||||||
// Private
|
// Private
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void createChart() {
|
||||||
|
NumberAxis xAxis = new NumberAxis();
|
||||||
|
xAxis.setForceZeroInRange(false);
|
||||||
|
xAxis.setAutoRanging(true);
|
||||||
|
xAxis.setTickLabelGap(6);
|
||||||
|
xAxis.setTickMarkVisible(false);
|
||||||
|
xAxis.setMinorTickVisible(false);
|
||||||
|
|
||||||
|
xAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||||
|
@Override
|
||||||
|
public String toString(Number timestamp) {
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timestamp.longValue(),
|
||||||
|
0, OffsetDateTime.now(ZoneId.systemDefault()).getOffset());
|
||||||
|
return localDateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Number fromString(String string) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
NumberAxis yAxis = new NumberAxis();
|
||||||
|
yAxis.setForceZeroInRange(false);
|
||||||
|
yAxis.setSide(Side.RIGHT);
|
||||||
|
yAxis.setAutoRanging(true);
|
||||||
|
yAxis.setTickMarkVisible(false);
|
||||||
|
yAxis.setMinorTickVisible(false);
|
||||||
|
yAxis.setTickLabelGap(5);
|
||||||
|
yAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||||
|
@Override
|
||||||
|
public String toString(Number marketPrice) {
|
||||||
|
return bsqFormatter.formatBTCWithCode(marketPrice.longValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Number fromString(String string) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
seriesBSQPrice = new XYChart.Series<>();
|
||||||
|
seriesBSQPrice.setName("Price in BTC for 1 BSQ");
|
||||||
|
|
||||||
|
bsqPriceChart = new AreaChart<>(xAxis, yAxis);
|
||||||
|
bsqPriceChart.setLegendVisible(true);
|
||||||
|
bsqPriceChart.setAnimated(false);
|
||||||
|
bsqPriceChart.setId("charts");
|
||||||
|
bsqPriceChart.setMinHeight(250);
|
||||||
|
bsqPriceChart.setPrefHeight(250);
|
||||||
|
bsqPriceChart.setCreateSymbols(true);
|
||||||
|
bsqPriceChart.setPadding(new Insets(0));
|
||||||
|
bsqPriceChart.getData().addAll(seriesBSQPrice);
|
||||||
|
|
||||||
|
GridPane.setRowIndex(bsqPriceChart, ++gridRow);
|
||||||
|
GridPane.setColumnSpan(bsqPriceChart, 2);
|
||||||
|
|
||||||
|
root.getChildren().addAll(bsqPriceChart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateChartData() {
|
||||||
|
updateBSQPriceData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBSQPriceData() {
|
||||||
|
seriesBSQPrice.getData().clear();
|
||||||
|
|
||||||
|
Map<LocalDate, List<TradeStatistics2>> bsqPriceByDate = tradeStatisticsManager.getObservableTradeStatisticsSet().stream()
|
||||||
|
.filter(e -> e.getCurrencyCode().equals("BSQ"))
|
||||||
|
.sorted(Comparator.comparing(TradeStatistics2::getTradeDate))
|
||||||
|
.collect(Collectors.groupingBy(item -> new Date(item.getTradeDate().getTime()).toLocalDate()
|
||||||
|
.with(ADJUSTERS.get(DAY))));
|
||||||
|
|
||||||
|
List<XYChart.Data<Number, Number>> updatedBSQPrice = bsqPriceByDate.keySet().stream()
|
||||||
|
.map(e -> {
|
||||||
|
ZonedDateTime zonedDateTime = e.atStartOfDay(ZoneId.systemDefault());
|
||||||
|
return new XYChart.Data<Number, Number>(zonedDateTime.toInstant().getEpochSecond(), bsqPriceByDate.get(e).stream()
|
||||||
|
.map(TradeStatistics2::getTradePrice)
|
||||||
|
.mapToDouble(Price::getValue)
|
||||||
|
.average()
|
||||||
|
.orElse(Double.NaN)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
seriesBSQPrice.getData().setAll(updatedBSQPrice);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateWithBsqBlockChainData() {
|
private void updateWithBsqBlockChainData() {
|
||||||
|
Coin issuedAmountFromGenesis = daoFacade.getGenesisTotalSupply();
|
||||||
|
Coin issuedAmountFromCompRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.COMPENSATION));
|
||||||
|
Coin issuedAmountFromReimbursementRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.REIMBURSEMENT));
|
||||||
|
Coin burntFee = Coin.valueOf(daoFacade.getTotalBurntFee());
|
||||||
|
Coin totalConfiscatedAmount = Coin.valueOf(daoFacade.getTotalAmountOfConfiscatedTxOutputs());
|
||||||
|
|
||||||
|
availableAmount = issuedAmountFromGenesis
|
||||||
|
.add(issuedAmountFromCompRequests)
|
||||||
|
.add(issuedAmountFromReimbursementRequests)
|
||||||
|
.subtract(burntFee)
|
||||||
|
.subtract(totalConfiscatedAmount);
|
||||||
|
|
||||||
|
availableAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(availableAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePrice() {
|
private void updatePrice() {
|
||||||
|
Optional<Price> optionalBsqPrice = priceFeedService.getBsqPrice();
|
||||||
|
if (optionalBsqPrice.isPresent()) {
|
||||||
|
Price bsqPrice = optionalBsqPrice.get();
|
||||||
|
priceTextField.setText(bsqFormatter.formatPrice(bsqPrice) + " BSQ/BTC");
|
||||||
|
|
||||||
|
marketCapTextField.setText(bsqFormatter.formatMarketCap(priceFeedService.getMarketPrice("BSQ"),
|
||||||
|
priceFeedService.getMarketPrice(preferences.getPreferredTradeCurrency().getCode()),
|
||||||
|
availableAmount));
|
||||||
|
} else {
|
||||||
|
priceTextField.setText(Res.get("shared.na"));
|
||||||
|
marketCapTextField.setText(Res.get("shared.na"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,225 +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.desktop.main.dao.economy.details;
|
|
||||||
|
|
||||||
import bisq.desktop.common.view.ActivatableView;
|
|
||||||
import bisq.desktop.common.view.FxmlView;
|
|
||||||
import bisq.desktop.components.HyperlinkWithIcon;
|
|
||||||
import bisq.desktop.util.FormBuilder;
|
|
||||||
import bisq.desktop.util.Layout;
|
|
||||||
|
|
||||||
import bisq.core.dao.DaoFacade;
|
|
||||||
import bisq.core.dao.state.DaoStateListener;
|
|
||||||
import bisq.core.dao.state.model.blockchain.Block;
|
|
||||||
import bisq.core.dao.state.model.governance.IssuanceType;
|
|
||||||
import bisq.core.locale.Res;
|
|
||||||
import bisq.core.monetary.Price;
|
|
||||||
import bisq.core.provider.price.PriceFeedService;
|
|
||||||
import bisq.core.user.Preferences;
|
|
||||||
import bisq.core.util.BsqFormatter;
|
|
||||||
|
|
||||||
import bisq.common.util.Tuple3;
|
|
||||||
|
|
||||||
import org.bitcoinj.core.Coin;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.TextField;
|
|
||||||
import javafx.scene.control.Tooltip;
|
|
||||||
import javafx.scene.layout.GridPane;
|
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
|
|
||||||
import javafx.beans.value.ChangeListener;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
|
||||||
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
|
|
||||||
|
|
||||||
@FxmlView
|
|
||||||
public class DetailsView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
|
||||||
|
|
||||||
private final DaoFacade daoFacade;
|
|
||||||
private final PriceFeedService priceFeedService;
|
|
||||||
private final Preferences preferences;
|
|
||||||
private final BsqFormatter bsqFormatter;
|
|
||||||
|
|
||||||
private int gridRow = 0;
|
|
||||||
private TextField genesisIssueAmountTextField, compRequestIssueAmountTextField, reimbursementAmountTextField, availableAmountTextField,
|
|
||||||
burntAmountTextField, totalLockedUpAmountTextField, totalUnlockingAmountTextField,
|
|
||||||
totalUnlockedAmountTextField, totalConfiscatedAmountTextField, allTxTextField, burntTxTextField,
|
|
||||||
utxoTextField, compensationIssuanceTxTextField,
|
|
||||||
reimbursementIssuanceTxTextField, priceTextField, marketCapTextField;
|
|
||||||
private ChangeListener<Number> priceChangeListener;
|
|
||||||
private Coin availableAmount;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor, lifecycle
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private DetailsView(DaoFacade daoFacade,
|
|
||||||
PriceFeedService priceFeedService,
|
|
||||||
Preferences preferences,
|
|
||||||
BsqFormatter bsqFormatter) {
|
|
||||||
this.daoFacade = daoFacade;
|
|
||||||
this.priceFeedService = priceFeedService;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.bsqFormatter = bsqFormatter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize() {
|
|
||||||
int columnIndex = 2;
|
|
||||||
|
|
||||||
int startRow = gridRow;
|
|
||||||
addTitledGroupBg(root, ++gridRow, 5, Res.get("dao.wallet.dashboard.distribution"));
|
|
||||||
genesisIssueAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.genesisIssueAmount")).second;
|
|
||||||
compRequestIssueAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.compRequestIssueAmount")).second;
|
|
||||||
reimbursementAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.reimbursementAmount")).second;
|
|
||||||
burntAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.burntAmount")).second;
|
|
||||||
availableAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.availableAmount")).second;
|
|
||||||
|
|
||||||
gridRow = startRow;
|
|
||||||
addTitledGroupBg(root, ++gridRow, columnIndex, 5, Res.get("dao.wallet.dashboard.locked"), Layout.GROUP_DISTANCE);
|
|
||||||
totalLockedUpAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalLockedUpAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
|
||||||
totalUnlockingAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalUnlockingAmount")).second;
|
|
||||||
totalUnlockedAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalUnlockedAmount")).second;
|
|
||||||
totalConfiscatedAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalConfiscatedAmount")).second;
|
|
||||||
gridRow++;
|
|
||||||
|
|
||||||
startRow = gridRow;
|
|
||||||
addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.wallet.dashboard.market"), Layout.GROUP_DISTANCE);
|
|
||||||
priceTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.price"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
|
||||||
marketCapTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.marketCap")).second;
|
|
||||||
|
|
||||||
gridRow = startRow;
|
|
||||||
addTitledGroupBg(root, ++gridRow, columnIndex, 2, Res.get("dao.wallet.dashboard.genesis"), Layout.GROUP_DISTANCE);
|
|
||||||
String genTxHeight = String.valueOf(daoFacade.getGenesisBlockHeight());
|
|
||||||
String genesisTxId = daoFacade.getGenesisTxId();
|
|
||||||
String url = preferences.getBsqBlockChainExplorer().txUrl + genesisTxId;
|
|
||||||
addTopLabelReadOnlyTextField(root, gridRow, columnIndex, Res.get("dao.wallet.dashboard.genesisBlockHeight"),
|
|
||||||
genTxHeight, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
|
||||||
|
|
||||||
// TODO use addTopLabelTxIdTextField
|
|
||||||
Tuple3<Label, HyperlinkWithIcon, VBox> tuple = FormBuilder.addTopLabelHyperlinkWithIcon(root, ++gridRow, columnIndex,
|
|
||||||
Res.get("dao.wallet.dashboard.genesisTxId"), genesisTxId, url, 0);
|
|
||||||
HyperlinkWithIcon hyperlinkWithIcon = tuple.second;
|
|
||||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", genesisTxId)));
|
|
||||||
|
|
||||||
startRow = gridRow;
|
|
||||||
addTitledGroupBg(root, ++gridRow, 3, Res.get("dao.wallet.dashboard.txDetails"), Layout.GROUP_DISTANCE);
|
|
||||||
allTxTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.allTx"),
|
|
||||||
genTxHeight, Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
|
||||||
utxoTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.utxo")).second;
|
|
||||||
compensationIssuanceTxTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow,
|
|
||||||
Res.get("dao.wallet.dashboard.compensationIssuanceTx")).second;
|
|
||||||
|
|
||||||
gridRow = startRow;
|
|
||||||
addTitledGroupBg(root, ++gridRow, columnIndex, 3, "", Layout.GROUP_DISTANCE);
|
|
||||||
reimbursementIssuanceTxTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, columnIndex,
|
|
||||||
Res.get("dao.wallet.dashboard.reimbursementIssuanceTx"),
|
|
||||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
|
||||||
burntTxTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex,
|
|
||||||
Res.get("dao.wallet.dashboard.burntTx")).second;
|
|
||||||
++gridRow;
|
|
||||||
|
|
||||||
priceChangeListener = (observable, oldValue, newValue) -> updatePrice();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void activate() {
|
|
||||||
daoFacade.addBsqStateListener(this);
|
|
||||||
priceFeedService.updateCounterProperty().addListener(priceChangeListener);
|
|
||||||
|
|
||||||
updateWithBsqBlockChainData();
|
|
||||||
updatePrice();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void deactivate() {
|
|
||||||
daoFacade.removeBsqStateListener(this);
|
|
||||||
priceFeedService.updateCounterProperty().removeListener(priceChangeListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// DaoStateListener
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onParseBlockCompleteAfterBatchProcessing(Block block) {
|
|
||||||
updateWithBsqBlockChainData();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Private
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void updateWithBsqBlockChainData() {
|
|
||||||
Coin issuedAmountFromGenesis = daoFacade.getGenesisTotalSupply();
|
|
||||||
genesisIssueAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromGenesis));
|
|
||||||
|
|
||||||
Coin issuedAmountFromCompRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.COMPENSATION));
|
|
||||||
compRequestIssueAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromCompRequests));
|
|
||||||
Coin issuedAmountFromReimbursementRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.REIMBURSEMENT));
|
|
||||||
reimbursementAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromReimbursementRequests));
|
|
||||||
|
|
||||||
Coin burntFee = Coin.valueOf(daoFacade.getTotalBurntFee());
|
|
||||||
Coin totalLockedUpAmount = Coin.valueOf(daoFacade.getTotalLockupAmount());
|
|
||||||
Coin totalUnlockingAmount = Coin.valueOf(daoFacade.getTotalAmountOfUnLockingTxOutputs());
|
|
||||||
Coin totalUnlockedAmount = Coin.valueOf(daoFacade.getTotalAmountOfUnLockedTxOutputs());
|
|
||||||
Coin totalConfiscatedAmount = Coin.valueOf(daoFacade.getTotalAmountOfConfiscatedTxOutputs());
|
|
||||||
availableAmount = issuedAmountFromGenesis
|
|
||||||
.add(issuedAmountFromCompRequests)
|
|
||||||
.add(issuedAmountFromReimbursementRequests)
|
|
||||||
.subtract(burntFee)
|
|
||||||
.subtract(totalConfiscatedAmount);
|
|
||||||
|
|
||||||
availableAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(availableAmount));
|
|
||||||
burntAmountTextField.setText("-" + bsqFormatter.formatAmountWithGroupSeparatorAndCode(burntFee));
|
|
||||||
totalLockedUpAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalLockedUpAmount));
|
|
||||||
totalUnlockingAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockingAmount));
|
|
||||||
totalUnlockedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockedAmount));
|
|
||||||
totalConfiscatedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalConfiscatedAmount));
|
|
||||||
allTxTextField.setText(String.valueOf(daoFacade.getTxs().size()));
|
|
||||||
utxoTextField.setText(String.valueOf(daoFacade.getUnspentTxOutputs().size()));
|
|
||||||
compensationIssuanceTxTextField.setText(String.valueOf(daoFacade.getNumIssuanceTransactions(IssuanceType.COMPENSATION)));
|
|
||||||
reimbursementIssuanceTxTextField.setText(String.valueOf(daoFacade.getNumIssuanceTransactions(IssuanceType.REIMBURSEMENT)));
|
|
||||||
burntTxTextField.setText(String.valueOf(daoFacade.getFeeTxs().size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePrice() {
|
|
||||||
Optional<Price> optionalBsqPrice = priceFeedService.getBsqPrice();
|
|
||||||
if (optionalBsqPrice.isPresent()) {
|
|
||||||
Price bsqPrice = optionalBsqPrice.get();
|
|
||||||
priceTextField.setText(bsqFormatter.formatPrice(bsqPrice) + " BSQ/BTC");
|
|
||||||
|
|
||||||
marketCapTextField.setText(bsqFormatter.formatMarketCap(priceFeedService.getMarketPrice("BSQ"),
|
|
||||||
priceFeedService.getMarketPrice(preferences.getPreferredTradeCurrency().getCode()),
|
|
||||||
availableAmount));
|
|
||||||
} else {
|
|
||||||
priceTextField.setText(Res.get("shared.na"));
|
|
||||||
marketCapTextField.setText(Res.get("shared.na"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -20,14 +20,13 @@
|
|||||||
<?import javafx.scene.layout.AnchorPane?>
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
<?import javafx.scene.layout.GridPane?>
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.economy.details.DetailsView"
|
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.economy.supply.SupplyView"
|
||||||
hgap="5.0" vgap="5.0"
|
hgap="5.0" vgap="5.0"
|
||||||
AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0"
|
AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0"
|
||||||
AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="20.0"
|
AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="20.0"
|
||||||
xmlns:fx="http://javafx.com/fxml">
|
xmlns:fx="http://javafx.com/fxml">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints percentWidth="50"/>
|
<ColumnConstraints percentWidth="50"/>
|
||||||
<ColumnConstraints minWidth="10" maxWidth="5"/>
|
|
||||||
<ColumnConstraints percentWidth="50"/>
|
<ColumnConstraints percentWidth="50"/>
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
</GridPane>
|
</GridPane>
|
@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
* 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.desktop.main.dao.economy.supply;
|
||||||
|
|
||||||
|
import bisq.desktop.common.view.ActivatableView;
|
||||||
|
import bisq.desktop.common.view.FxmlView;
|
||||||
|
import bisq.desktop.components.TitledGroupBg;
|
||||||
|
import bisq.desktop.util.Layout;
|
||||||
|
|
||||||
|
import bisq.core.dao.DaoFacade;
|
||||||
|
import bisq.core.dao.state.DaoStateListener;
|
||||||
|
import bisq.core.dao.state.DaoStateService;
|
||||||
|
import bisq.core.dao.state.model.blockchain.Block;
|
||||||
|
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.core.locale.Res;
|
||||||
|
import bisq.core.util.BsqFormatter;
|
||||||
|
|
||||||
|
import bisq.common.util.Tuple3;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.Coin;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import javafx.scene.chart.AreaChart;
|
||||||
|
import javafx.scene.chart.NumberAxis;
|
||||||
|
import javafx.scene.chart.XYChart;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Side;
|
||||||
|
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.FormatStyle;
|
||||||
|
import java.time.temporal.TemporalAdjuster;
|
||||||
|
import java.time.temporal.TemporalAdjusters;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||||
|
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import java.sql.Date;
|
||||||
|
|
||||||
|
@FxmlView
|
||||||
|
public class SupplyView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||||
|
|
||||||
|
private static final String MONTH = "month";
|
||||||
|
|
||||||
|
private final DaoFacade daoFacade;
|
||||||
|
private DaoStateService daoStateService;
|
||||||
|
private final BsqFormatter bsqFormatter;
|
||||||
|
|
||||||
|
private int gridRow = 0;
|
||||||
|
private TextField genesisIssueAmountTextField, compRequestIssueAmountTextField, reimbursementAmountTextField,
|
||||||
|
burntAmountTextField, totalLockedUpAmountTextField, totalUnlockingAmountTextField,
|
||||||
|
totalUnlockedAmountTextField, totalConfiscatedAmountTextField;
|
||||||
|
private XYChart.Series<Number, Number> seriesBSQIssued, seriesBSQBurnt;
|
||||||
|
|
||||||
|
private static final Map<String, TemporalAdjuster> ADJUSTERS = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor, lifecycle
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SupplyView(DaoFacade daoFacade,
|
||||||
|
DaoStateService daoStateService,
|
||||||
|
BsqFormatter bsqFormatter) {
|
||||||
|
this.daoFacade = daoFacade;
|
||||||
|
this.daoStateService = daoStateService;
|
||||||
|
this.bsqFormatter = bsqFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
|
||||||
|
ADJUSTERS.put(MONTH, TemporalAdjusters.firstDayOfMonth());
|
||||||
|
|
||||||
|
createSupplyIncreasedInformation();
|
||||||
|
createSupplyReducedInformation();
|
||||||
|
createSupplyLockedInformation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void activate() {
|
||||||
|
daoFacade.addBsqStateListener(this);
|
||||||
|
|
||||||
|
updateWithBsqBlockChainData();
|
||||||
|
updateBSQTokenData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deactivate() {
|
||||||
|
daoFacade.removeBsqStateListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DaoStateListener
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onParseBlockCompleteAfterBatchProcessing(Block block) {
|
||||||
|
updateWithBsqBlockChainData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void createSupplyIncreasedInformation() {
|
||||||
|
addTitledGroupBg(root, ++gridRow, 3, Res.get("dao.factsAndFigures.supply.issued"));
|
||||||
|
|
||||||
|
Tuple3<Label, TextField, VBox> genesisAmountTuple = addTopLabelReadOnlyTextField(root, gridRow,
|
||||||
|
Res.get("dao.factsAndFigures.supply.genesisIssueAmount"), Layout.FIRST_ROW_DISTANCE);
|
||||||
|
genesisIssueAmountTextField = genesisAmountTuple.second;
|
||||||
|
GridPane.setColumnSpan(genesisAmountTuple.third, 2);
|
||||||
|
|
||||||
|
compRequestIssueAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||||
|
Res.get("dao.factsAndFigures.supply.compRequestIssueAmount")).second;
|
||||||
|
reimbursementAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, 1,
|
||||||
|
Res.get("dao.factsAndFigures.supply.reimbursementAmount")).second;
|
||||||
|
|
||||||
|
|
||||||
|
seriesBSQIssued = new XYChart.Series<>();
|
||||||
|
createChart(seriesBSQIssued, Res.get("dao.factsAndFigures.supply.issued"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSupplyReducedInformation() {
|
||||||
|
addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.factsAndFigures.supply.burnt"), Layout.GROUP_DISTANCE);
|
||||||
|
|
||||||
|
Tuple3<Label, TextField, VBox> burntAmountTuple = addTopLabelReadOnlyTextField(root, gridRow,
|
||||||
|
Res.get("dao.factsAndFigures.supply.burntAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
burntAmountTextField = burntAmountTuple.second;
|
||||||
|
|
||||||
|
GridPane.setColumnSpan(burntAmountTuple.third, 2);
|
||||||
|
|
||||||
|
seriesBSQBurnt = new XYChart.Series<>();
|
||||||
|
createChart(seriesBSQBurnt, Res.get("dao.factsAndFigures.supply.burnt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSupplyLockedInformation() {
|
||||||
|
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.factsAndFigures.supply.locked"), Layout.GROUP_DISTANCE);
|
||||||
|
titledGroupBg.getStyleClass().add("last");
|
||||||
|
|
||||||
|
totalLockedUpAmountTextField = addTopLabelReadOnlyTextField(root, gridRow,
|
||||||
|
Res.get("dao.factsAndFigures.supply.totalLockedUpAmount"),
|
||||||
|
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||||
|
totalUnlockingAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, 1,
|
||||||
|
Res.get("dao.factsAndFigures.supply.totalUnlockingAmount"),
|
||||||
|
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||||
|
|
||||||
|
totalUnlockedAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||||
|
Res.get("dao.factsAndFigures.supply.totalUnlockedAmount")).second;
|
||||||
|
totalConfiscatedAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, 1,
|
||||||
|
Res.get("dao.factsAndFigures.supply.totalConfiscatedAmount")).second;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createChart(XYChart.Series<Number, Number> series, String seriesLabel) {
|
||||||
|
NumberAxis xAxis = new NumberAxis();
|
||||||
|
xAxis.setForceZeroInRange(false);
|
||||||
|
xAxis.setAutoRanging(true);
|
||||||
|
xAxis.setTickLabelGap(6);
|
||||||
|
xAxis.setTickMarkVisible(false);
|
||||||
|
xAxis.setMinorTickVisible(false);
|
||||||
|
xAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||||
|
@Override
|
||||||
|
public String toString(Number timestamp) {
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timestamp.longValue(),
|
||||||
|
0, OffsetDateTime.now(ZoneId.systemDefault()).getOffset());
|
||||||
|
return localDateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Number fromString(String string) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
NumberAxis yAxis = new NumberAxis();
|
||||||
|
yAxis.setForceZeroInRange(false);
|
||||||
|
yAxis.setSide(Side.RIGHT);
|
||||||
|
yAxis.setAutoRanging(true);
|
||||||
|
yAxis.setTickMarkVisible(false);
|
||||||
|
yAxis.setMinorTickVisible(false);
|
||||||
|
yAxis.setTickLabelGap(5);
|
||||||
|
yAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||||
|
@Override
|
||||||
|
public String toString(Number marketPrice) {
|
||||||
|
return bsqFormatter.formatBSQSatoshisWithCode(marketPrice.longValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Number fromString(String string) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
series.setName(seriesLabel);
|
||||||
|
|
||||||
|
AreaChart<Number, Number> chart = new AreaChart<>(xAxis, yAxis);
|
||||||
|
chart.setLegendVisible(true);
|
||||||
|
chart.setAnimated(false);
|
||||||
|
chart.setId("charts");
|
||||||
|
chart.setMinHeight(250);
|
||||||
|
chart.setPrefHeight(250);
|
||||||
|
chart.setCreateSymbols(true);
|
||||||
|
chart.setPadding(new Insets(0));
|
||||||
|
chart.getData().addAll(series);
|
||||||
|
|
||||||
|
GridPane.setColumnSpan(chart, 2);
|
||||||
|
GridPane.setRowIndex(chart, ++gridRow);
|
||||||
|
|
||||||
|
root.getChildren().add(chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateWithBsqBlockChainData() {
|
||||||
|
Coin issuedAmountFromGenesis = daoFacade.getGenesisTotalSupply();
|
||||||
|
genesisIssueAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromGenesis));
|
||||||
|
|
||||||
|
Coin issuedAmountFromCompRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.COMPENSATION));
|
||||||
|
compRequestIssueAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromCompRequests));
|
||||||
|
Coin issuedAmountFromReimbursementRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.REIMBURSEMENT));
|
||||||
|
reimbursementAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromReimbursementRequests));
|
||||||
|
|
||||||
|
Coin burntFee = Coin.valueOf(daoFacade.getTotalBurntFee());
|
||||||
|
Coin totalLockedUpAmount = Coin.valueOf(daoFacade.getTotalLockupAmount());
|
||||||
|
Coin totalUnlockingAmount = Coin.valueOf(daoFacade.getTotalAmountOfUnLockingTxOutputs());
|
||||||
|
Coin totalUnlockedAmount = Coin.valueOf(daoFacade.getTotalAmountOfUnLockedTxOutputs());
|
||||||
|
Coin totalConfiscatedAmount = Coin.valueOf(daoFacade.getTotalAmountOfConfiscatedTxOutputs());
|
||||||
|
|
||||||
|
burntAmountTextField.setText("-" + bsqFormatter.formatAmountWithGroupSeparatorAndCode(burntFee));
|
||||||
|
totalLockedUpAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalLockedUpAmount));
|
||||||
|
totalUnlockingAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockingAmount));
|
||||||
|
totalUnlockedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockedAmount));
|
||||||
|
totalConfiscatedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalConfiscatedAmount));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBSQTokenData() {
|
||||||
|
seriesBSQIssued.getData().clear();
|
||||||
|
seriesBSQBurnt.getData().clear();
|
||||||
|
|
||||||
|
Map<LocalDate, List<Tx>> feesBurntByMonth = daoStateService.getBurntFeeTxs().stream()
|
||||||
|
.sorted(Comparator.comparing(Tx::getTime))
|
||||||
|
.collect(Collectors.groupingBy(item -> new Date(item.getTime()).toLocalDate()
|
||||||
|
.with(ADJUSTERS.get(MONTH))));
|
||||||
|
|
||||||
|
List<XYChart.Data<Number, Number>> updatedBurntBSQ = feesBurntByMonth.keySet().stream()
|
||||||
|
.map(date -> {
|
||||||
|
ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault());
|
||||||
|
return new XYChart.Data<Number, Number>(zonedDateTime.toInstant().getEpochSecond(), feesBurntByMonth.get(date)
|
||||||
|
.stream()
|
||||||
|
.mapToDouble(Tx::getBurntFee)
|
||||||
|
.sum()
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
seriesBSQBurnt.getData().setAll(updatedBurntBSQ);
|
||||||
|
|
||||||
|
Stream<Issuance> bsqByCompensation = daoStateService.getIssuanceSet(IssuanceType.COMPENSATION).stream()
|
||||||
|
.sorted(Comparator.comparing(Issuance::getChainHeight));
|
||||||
|
|
||||||
|
Stream<Issuance> bsqByReImbursement = daoStateService.getIssuanceSet(IssuanceType.REIMBURSEMENT).stream()
|
||||||
|
.sorted(Comparator.comparing(Issuance::getChainHeight));
|
||||||
|
|
||||||
|
Map<LocalDate, List<Issuance>> bsqAddedByVote = Stream.concat(bsqByCompensation, bsqByReImbursement)
|
||||||
|
.collect(Collectors.groupingBy(item -> new Date(daoFacade.getBlockTime(item.getChainHeight())).toLocalDate()
|
||||||
|
.with(ADJUSTERS.get(MONTH))));
|
||||||
|
|
||||||
|
List<XYChart.Data<Number, Number>> updatedAddedBSQ = bsqAddedByVote.keySet().stream()
|
||||||
|
.map(date -> {
|
||||||
|
ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault());
|
||||||
|
return new XYChart.Data<Number, Number>(zonedDateTime.toInstant().getEpochSecond(), bsqAddedByVote.get(date)
|
||||||
|
.stream()
|
||||||
|
.mapToDouble(Issuance::getAmount)
|
||||||
|
.sum());
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
seriesBSQIssued.getData().setAll(updatedAddedBSQ);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
|
<?import javafx.scene.layout.GridPane?>
|
||||||
|
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.economy.transactions.BSQTransactionsView"
|
||||||
|
hgap="5.0" vgap="5.0"
|
||||||
|
AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0"
|
||||||
|
AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="20.0"
|
||||||
|
xmlns:fx="http://javafx.com/fxml">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints percentWidth="50"/>
|
||||||
|
<ColumnConstraints percentWidth="50"/>
|
||||||
|
</columnConstraints>
|
||||||
|
</GridPane>
|
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* 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.desktop.main.dao.economy.transactions;
|
||||||
|
|
||||||
|
import bisq.desktop.common.view.ActivatableView;
|
||||||
|
import bisq.desktop.common.view.FxmlView;
|
||||||
|
import bisq.desktop.components.HyperlinkWithIcon;
|
||||||
|
import bisq.desktop.components.TitledGroupBg;
|
||||||
|
import bisq.desktop.util.Layout;
|
||||||
|
|
||||||
|
import bisq.core.dao.DaoFacade;
|
||||||
|
import bisq.core.dao.state.DaoStateListener;
|
||||||
|
import bisq.core.dao.state.model.blockchain.Block;
|
||||||
|
import bisq.core.dao.state.model.governance.IssuanceType;
|
||||||
|
import bisq.core.locale.Res;
|
||||||
|
import bisq.core.user.Preferences;
|
||||||
|
|
||||||
|
import bisq.common.util.Tuple3;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||||
|
import static bisq.desktop.util.FormBuilder.addTopLabelHyperlinkWithIcon;
|
||||||
|
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
|
||||||
|
|
||||||
|
@FxmlView
|
||||||
|
public class BSQTransactionsView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||||
|
|
||||||
|
private final DaoFacade daoFacade;
|
||||||
|
private final Preferences preferences;
|
||||||
|
|
||||||
|
private int gridRow = 0;
|
||||||
|
private TextField allTxTextField, burntTxTextField,
|
||||||
|
utxoTextField, compensationIssuanceTxTextField,
|
||||||
|
reimbursementIssuanceTxTextField;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor, lifecycle
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BSQTransactionsView(DaoFacade daoFacade,
|
||||||
|
Preferences preferences) {
|
||||||
|
this.daoFacade = daoFacade;
|
||||||
|
this.preferences = preferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
addTitledGroupBg(root, gridRow, 2, Res.get("dao.factsAndFigures.transactions.genesis"));
|
||||||
|
String genTxHeight = String.valueOf(daoFacade.getGenesisBlockHeight());
|
||||||
|
String genesisTxId = daoFacade.getGenesisTxId();
|
||||||
|
String url = preferences.getBsqBlockChainExplorer().txUrl + genesisTxId;
|
||||||
|
|
||||||
|
GridPane.setColumnSpan(addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.factsAndFigures.transactions.genesisBlockHeight"),
|
||||||
|
genTxHeight, Layout.FIRST_ROW_DISTANCE).third, 2);
|
||||||
|
|
||||||
|
// TODO use addTopLabelTxIdTextField
|
||||||
|
Tuple3<Label, HyperlinkWithIcon, VBox> tuple = addTopLabelHyperlinkWithIcon(root, ++gridRow,
|
||||||
|
Res.get("dao.factsAndFigures.transactions.genesisTxId"), genesisTxId, url, 0);
|
||||||
|
HyperlinkWithIcon hyperlinkWithIcon = tuple.second;
|
||||||
|
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", genesisTxId)));
|
||||||
|
|
||||||
|
GridPane.setColumnSpan(tuple.third, 2);
|
||||||
|
|
||||||
|
|
||||||
|
int startRow = ++gridRow;
|
||||||
|
|
||||||
|
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, 3, Res.get("dao.factsAndFigures.transactions.txDetails"), Layout.GROUP_DISTANCE);
|
||||||
|
titledGroupBg.getStyleClass().add("last");
|
||||||
|
|
||||||
|
allTxTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.factsAndFigures.transactions.allTx"),
|
||||||
|
genTxHeight, Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||||
|
utxoTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.factsAndFigures.transactions.utxo")).second;
|
||||||
|
compensationIssuanceTxTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||||
|
Res.get("dao.factsAndFigures.transactions.compensationIssuanceTx")).second;
|
||||||
|
|
||||||
|
int columnIndex = 1;
|
||||||
|
|
||||||
|
gridRow = startRow;
|
||||||
|
|
||||||
|
titledGroupBg = addTitledGroupBg(root, startRow, columnIndex, 3, "", Layout.GROUP_DISTANCE);
|
||||||
|
titledGroupBg.getStyleClass().add("last");
|
||||||
|
|
||||||
|
reimbursementIssuanceTxTextField = addTopLabelReadOnlyTextField(root, gridRow, columnIndex,
|
||||||
|
Res.get("dao.factsAndFigures.transactions.reimbursementIssuanceTx"),
|
||||||
|
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||||
|
burntTxTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex,
|
||||||
|
Res.get("dao.factsAndFigures.transactions.burntTx")).second;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void activate() {
|
||||||
|
daoFacade.addBsqStateListener(this);
|
||||||
|
|
||||||
|
updateWithBsqBlockChainData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deactivate() {
|
||||||
|
daoFacade.removeBsqStateListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DaoStateListener
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onParseBlockCompleteAfterBatchProcessing(Block block) {
|
||||||
|
updateWithBsqBlockChainData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void updateWithBsqBlockChainData() {
|
||||||
|
allTxTextField.setText(String.valueOf(daoFacade.getTxs().size()));
|
||||||
|
utxoTextField.setText(String.valueOf(daoFacade.getUnspentTxOutputs().size()));
|
||||||
|
compensationIssuanceTxTextField.setText(String.valueOf(daoFacade.getNumIssuanceTransactions(IssuanceType.COMPENSATION)));
|
||||||
|
reimbursementIssuanceTxTextField.setText(String.valueOf(daoFacade.getNumIssuanceTransactions(IssuanceType.REIMBURSEMENT)));
|
||||||
|
burntTxTextField.setText(String.valueOf(daoFacade.getFeeTxs().size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -336,7 +336,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||||||
areaChart.setId("charts");
|
areaChart.setId("charts");
|
||||||
areaChart.setMinHeight(300);
|
areaChart.setMinHeight(300);
|
||||||
areaChart.setPrefHeight(300);
|
areaChart.setPrefHeight(300);
|
||||||
areaChart.setCreateSymbols(false);
|
areaChart.setCreateSymbols(true);
|
||||||
areaChart.setPadding(new Insets(0, 10, 0, 10));
|
areaChart.setPadding(new Insets(0, 10, 0, 10));
|
||||||
areaChart.getData().addAll(seriesBuy, seriesSell);
|
areaChart.getData().addAll(seriesBuy, seriesSell);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user