mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 23:06:39 +01:00
Add LegacyBurningMan to UI
It is not included in BurningManCandidate candidate map as that would complicate things. We only want to show it in the UI for informational purposes. Signed-off-by: HenrikJannsen <boilingfrog@gmx.com>
This commit is contained in:
parent
883b0542a1
commit
d4646cc19f
6 changed files with 179 additions and 46 deletions
|
@ -33,18 +33,18 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
public final class BurningManCandidate {
|
||||
public class BurningManCandidate {
|
||||
private final List<CompensationModel> compensationModels = new ArrayList<>();
|
||||
private long accumulatedCompensationAmount;
|
||||
private long accumulatedDecayedCompensationAmount;
|
||||
private double compensationShare; // Share of accumulated decayed compensation amounts in relation to total issued amounts
|
||||
private Optional<String> mostRecentAddress = Optional.empty();
|
||||
protected Optional<String> mostRecentAddress = Optional.empty();
|
||||
|
||||
private final List<BurnOutputModel> burnOutputModels = new ArrayList<>();
|
||||
private long accumulatedBurnAmount;
|
||||
private long accumulatedDecayedBurnAmount;
|
||||
private double burnAmountShare; // Share of accumulated decayed burn amounts in relation to total burned amounts
|
||||
private double cappedBurnAmountShare; // Capped burnAmountShare. Cannot be larger than boostedCompensationShare
|
||||
protected double burnAmountShare; // Share of accumulated decayed burn amounts in relation to total burned amounts
|
||||
protected double cappedBurnAmountShare; // Capped burnAmountShare. Cannot be larger than boostedCompensationShare
|
||||
|
||||
BurningManCandidate() {
|
||||
}
|
||||
|
|
|
@ -18,14 +18,21 @@
|
|||
package bisq.core.dao.burningman;
|
||||
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.CyclesInDaoStateService;
|
||||
import bisq.core.dao.governance.proposal.MyProposalListService;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.blockchain.BaseTx;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.state.model.blockchain.Tx;
|
||||
import bisq.core.dao.state.model.blockchain.TxOutput;
|
||||
import bisq.core.dao.state.model.governance.CompensationProposal;
|
||||
import bisq.core.dao.state.model.governance.Proposal;
|
||||
|
||||
import bisq.network.p2p.storage.P2PDataStorage;
|
||||
|
||||
import bisq.common.app.DevEnv;
|
||||
import bisq.common.util.Hex;
|
||||
import bisq.common.util.Tuple2;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -48,8 +55,10 @@ public class BurningManPresentationService implements DaoStateListener {
|
|||
// Burn target gets increased by that amount to give more flexibility.
|
||||
// Burn target is calculated from reimbursements + estimated BTC fees - burned amounts.
|
||||
static final long BURN_TARGET_BOOST_AMOUNT = DevEnv.isDevTesting() ? 1000000 : 10000000;
|
||||
public static final String LEGACY_BURNING_MAN_NAME = "Legacy Burningman";
|
||||
|
||||
private final DaoStateService daoStateService;
|
||||
private final CyclesInDaoStateService cyclesInDaoStateService;
|
||||
private final MyProposalListService myProposalListService;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final BurningManService burningManService;
|
||||
|
@ -63,14 +72,18 @@ public class BurningManPresentationService implements DaoStateListener {
|
|||
private Set<String> myCompensationRequestNames = null;
|
||||
@SuppressWarnings("OptionalAssignedToNull")
|
||||
private Optional<Set<String>> myGenesisOutputNames = null;
|
||||
private Optional<LegacyBurningMan> legacyBurningMan = Optional.empty();
|
||||
private final Map<P2PDataStorage.ByteArray, Set<TxOutput>> proofOfBurnOpReturnTxOutputByHash = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
public BurningManPresentationService(DaoStateService daoStateService,
|
||||
CyclesInDaoStateService cyclesInDaoStateService,
|
||||
MyProposalListService myProposalListService,
|
||||
BsqWalletService bsqWalletService,
|
||||
BurningManService burningManService,
|
||||
BurnTargetService burnTargetService) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.cyclesInDaoStateService = cyclesInDaoStateService;
|
||||
this.myProposalListService = myProposalListService;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.burningManService = burningManService;
|
||||
|
@ -96,6 +109,8 @@ public class BurningManPresentationService implements DaoStateListener {
|
|||
burnTarget = Optional.empty();
|
||||
myCompensationRequestNames = null;
|
||||
averageDistributionPerCycle = Optional.empty();
|
||||
legacyBurningMan = Optional.empty();
|
||||
proofOfBurnOpReturnTxOutputByHash.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,4 +238,49 @@ public class BurningManPresentationService implements DaoStateListener {
|
|||
burningManCandidatesByName.putAll(burningManService.getBurningManCandidatesByName(currentChainHeight));
|
||||
return burningManCandidatesByName;
|
||||
}
|
||||
|
||||
public LegacyBurningMan getLegacyBurningMan() {
|
||||
if (legacyBurningMan.isPresent()) {
|
||||
return legacyBurningMan.get();
|
||||
}
|
||||
|
||||
if (proofOfBurnOpReturnTxOutputByHash.isEmpty()) {
|
||||
proofOfBurnOpReturnTxOutputByHash.putAll(burningManService.getProofOfBurnOpReturnTxOutputByHash(currentChainHeight));
|
||||
}
|
||||
|
||||
// We do not add the legacy burningman to the list but keep it as class field only to avoid that it
|
||||
// interferes with usage of the burningManCandidatesByName map.
|
||||
LegacyBurningMan legacyBurningMan = new LegacyBurningMan(burningManService.getLegacyBurningManAddress(currentChainHeight));
|
||||
// Those are the hashes used by legacy BM for burning
|
||||
Set<String> hashes = Set.of("1701e47e5d8030f444c182b5e243871ebbaeadb5e82f",
|
||||
"1701293c488822f98e70e047012f46f5f1647f37deb7",
|
||||
"1701721206fe6b40777763de1c741f4fd2706d94775d");
|
||||
proofOfBurnOpReturnTxOutputByHash.values().stream()
|
||||
.flatMap(txOutputs -> txOutputs.stream()
|
||||
.filter(txOutput -> {
|
||||
String hash = Hex.encode(txOutput.getOpReturnData());
|
||||
return hashes.stream().anyMatch(e -> e.equals(hash));
|
||||
}))
|
||||
.forEach(burnOutput -> {
|
||||
int burnOutputHeight = burnOutput.getBlockHeight();
|
||||
Optional<Tx> optionalTx = daoStateService.getTx(burnOutput.getTxId());
|
||||
long burnOutputAmount = optionalTx.map(Tx::getBurntBsq).orElse(0L);
|
||||
long date = optionalTx.map(BaseTx::getTime).orElse(0L);
|
||||
int cycleIndex = cyclesInDaoStateService.getCycleIndexAtChainHeight(burnOutputHeight);
|
||||
legacyBurningMan.addBurnOutputModel(new BurnOutputModel(burnOutputAmount,
|
||||
burnOutputAmount,
|
||||
burnOutputHeight,
|
||||
burnOutput.getTxId(),
|
||||
date,
|
||||
cycleIndex));
|
||||
});
|
||||
// Set remaining share if the sum of all capped shares does not reach 100%.
|
||||
double burnAmountShareOfOthers = getBurningManCandidatesByName().values().stream()
|
||||
.mapToDouble(BurningManCandidate::getCappedBurnAmountShare)
|
||||
.sum();
|
||||
legacyBurningMan.applyBurnAmountShare(1 - burnAmountShareOfOthers);
|
||||
|
||||
this.legacyBurningMan = Optional.of(legacyBurningMan);
|
||||
return legacyBurningMan;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,7 +178,6 @@ class BurningManService {
|
|||
return burningManCandidatesByName;
|
||||
}
|
||||
|
||||
|
||||
String getLegacyBurningManAddress(int chainHeight) {
|
||||
return daoStateService.getParamValue(Param.RECIPIENT_BTC_ADDRESS, chainHeight);
|
||||
}
|
||||
|
@ -188,7 +187,7 @@ class BurningManService {
|
|||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private Map<P2PDataStorage.ByteArray, Set<TxOutput>> getProofOfBurnOpReturnTxOutputByHash(int chainHeight) {
|
||||
Map<P2PDataStorage.ByteArray, Set<TxOutput>> getProofOfBurnOpReturnTxOutputByHash(int chainHeight) {
|
||||
Map<P2PDataStorage.ByteArray, Set<TxOutput>> map = new HashMap<>();
|
||||
daoStateService.getProofOfBurnOpReturnTxOutputs().stream()
|
||||
.filter(txOutput -> txOutput.getBlockHeight() <= chainHeight)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.burningman;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public final class LegacyBurningMan extends BurningManCandidate {
|
||||
LegacyBurningMan(String address) {
|
||||
mostRecentAddress = Optional.of(address);
|
||||
}
|
||||
|
||||
void applyBurnAmountShare(double burnAmountShare) {
|
||||
this.burnAmountShare = burnAmountShare;
|
||||
this.cappedBurnAmountShare = burnAmountShare;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateShares(double totalDecayedCompensationAmounts, double totalDecayedBurnAmounts) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ package bisq.desktop.main.dao.burnbsq.burningmen;
|
|||
|
||||
import bisq.core.dao.burningman.BurningManCandidate;
|
||||
import bisq.core.dao.burningman.BurningManPresentationService;
|
||||
import bisq.core.dao.burningman.LegacyBurningMan;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.FormattingUtils;
|
||||
import bisq.core.util.coin.BsqFormatter;
|
||||
|
@ -32,9 +33,9 @@ import lombok.Getter;
|
|||
@EqualsAndHashCode
|
||||
class BurningmenListItem {
|
||||
private final BurningManCandidate burningManCandidate;
|
||||
private final String name, address, burnAmountShareAsString, cappedBurnAmountShareAsString, compensationShareAsString,
|
||||
accumulatedDecayedBurnAmountAsBsq, burnTargetAsBsq, maxBurnTargetAsBsq, accumulatedBurnAmountAsBsq,
|
||||
accumulatedDecayedCompensationAmountAsBsq, accumulatedCompensationAmountAsBsq, expectedRevenueAsBsq;
|
||||
private final String name, address, cappedBurnAmountShareAsString, compensationShareAsString,
|
||||
accumulatedDecayedBurnAmountAsBsq, burnTargetAsBsq, accumulatedBurnAmountAsBsq,
|
||||
accumulatedDecayedCompensationAmountAsBsq, accumulatedCompensationAmountAsBsq, expectedRevenueAsBsq, numIssuancesAsString;
|
||||
private final long burnTarget, maxBurnTarget, accumulatedDecayedBurnAmount, accumulatedBurnAmount,
|
||||
accumulatedDecayedCompensationAmount, accumulatedCompensationAmount, expectedRevenue;
|
||||
private final int numBurnOutputs, numIssuances;
|
||||
|
@ -49,31 +50,65 @@ class BurningmenListItem {
|
|||
this.name = name;
|
||||
address = burningManCandidate.getMostRecentAddress().orElse(Res.get("shared.na"));
|
||||
|
||||
// Burn
|
||||
Tuple2<Long, Long> burnTargetTuple = burningManPresentationService.getCandidateBurnTarget(burningManCandidate);
|
||||
burnTarget = burnTargetTuple.first;
|
||||
burnTargetAsBsq = bsqFormatter.formatCoin(burnTarget);
|
||||
maxBurnTarget = burnTargetTuple.second;
|
||||
maxBurnTargetAsBsq = bsqFormatter.formatCoin(maxBurnTarget);
|
||||
accumulatedBurnAmount = burningManCandidate.getAccumulatedBurnAmount();
|
||||
accumulatedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedBurnAmount);
|
||||
accumulatedDecayedBurnAmount = burningManCandidate.getAccumulatedDecayedBurnAmount();
|
||||
accumulatedDecayedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedDecayedBurnAmount);
|
||||
burnAmountShare = burningManCandidate.getBurnAmountShare();
|
||||
burnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(burnAmountShare);
|
||||
cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare();
|
||||
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare);
|
||||
expectedRevenue = burningManPresentationService.getExpectedRevenue(burningManCandidate);
|
||||
expectedRevenueAsBsq = bsqFormatter.formatCoinWithCode(expectedRevenue);
|
||||
numBurnOutputs = burningManCandidate.getBurnOutputModels().size();
|
||||
if (burningManCandidate instanceof LegacyBurningMan) {
|
||||
// Burn
|
||||
burnTarget = 0;
|
||||
burnTargetAsBsq = "";
|
||||
maxBurnTarget = 0;
|
||||
accumulatedBurnAmount = burningManCandidate.getAccumulatedBurnAmount();
|
||||
accumulatedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedBurnAmount);
|
||||
accumulatedDecayedBurnAmount = 0;
|
||||
accumulatedDecayedBurnAmountAsBsq = "";
|
||||
|
||||
// Issuance
|
||||
accumulatedCompensationAmount = burningManCandidate.getAccumulatedCompensationAmount();
|
||||
accumulatedCompensationAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedCompensationAmount);
|
||||
accumulatedDecayedCompensationAmount = burningManCandidate.getAccumulatedDecayedCompensationAmount();
|
||||
accumulatedDecayedCompensationAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedDecayedCompensationAmount);
|
||||
compensationShare = burningManCandidate.getCompensationShare();
|
||||
compensationShareAsString = FormattingUtils.formatToPercentWithSymbol(compensationShare);
|
||||
numIssuances = burningManCandidate.getCompensationModels().size();
|
||||
burnAmountShare = burningManCandidate.getBurnAmountShare();
|
||||
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(burnAmountShare);
|
||||
cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare();
|
||||
|
||||
expectedRevenue = burningManPresentationService.getExpectedRevenue(burningManCandidate);
|
||||
expectedRevenueAsBsq = bsqFormatter.formatCoinWithCode(expectedRevenue);
|
||||
numBurnOutputs = burningManCandidate.getBurnOutputModels().size();
|
||||
|
||||
// There is no issuance for legacy BM
|
||||
accumulatedCompensationAmount = 0;
|
||||
accumulatedCompensationAmountAsBsq = "";
|
||||
accumulatedDecayedCompensationAmount = 0;
|
||||
accumulatedDecayedCompensationAmountAsBsq = "";
|
||||
compensationShare = 0;
|
||||
compensationShareAsString = "";
|
||||
numIssuances = 0;
|
||||
numIssuancesAsString = "";
|
||||
} else {
|
||||
// Burn
|
||||
Tuple2<Long, Long> burnTargetTuple = burningManPresentationService.getCandidateBurnTarget(burningManCandidate);
|
||||
burnTarget = burnTargetTuple.first;
|
||||
maxBurnTarget = burnTargetTuple.second;
|
||||
burnTargetAsBsq = Res.get("dao.burningmen.burnTarget.fromTo", bsqFormatter.formatCoin(burnTarget), bsqFormatter.formatCoin(maxBurnTarget));
|
||||
accumulatedBurnAmount = burningManCandidate.getAccumulatedBurnAmount();
|
||||
accumulatedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedBurnAmount);
|
||||
accumulatedDecayedBurnAmount = burningManCandidate.getAccumulatedDecayedBurnAmount();
|
||||
accumulatedDecayedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedDecayedBurnAmount);
|
||||
burnAmountShare = burningManCandidate.getBurnAmountShare();
|
||||
cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare();
|
||||
if (burnAmountShare != cappedBurnAmountShare) {
|
||||
cappedBurnAmountShareAsString = Res.get("dao.burningmen.table.burnAmountShare.capped",
|
||||
FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare),
|
||||
FormattingUtils.formatToPercentWithSymbol(burnAmountShare));
|
||||
} else {
|
||||
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare);
|
||||
}
|
||||
expectedRevenue = burningManPresentationService.getExpectedRevenue(burningManCandidate);
|
||||
expectedRevenueAsBsq = bsqFormatter.formatCoinWithCode(expectedRevenue);
|
||||
numBurnOutputs = burningManCandidate.getBurnOutputModels().size();
|
||||
|
||||
// Issuance
|
||||
accumulatedCompensationAmount = burningManCandidate.getAccumulatedCompensationAmount();
|
||||
accumulatedCompensationAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedCompensationAmount);
|
||||
accumulatedDecayedCompensationAmount = burningManCandidate.getAccumulatedDecayedCompensationAmount();
|
||||
accumulatedDecayedCompensationAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedDecayedCompensationAmount);
|
||||
compensationShare = burningManCandidate.getCompensationShare();
|
||||
compensationShareAsString = FormattingUtils.formatToPercentWithSymbol(compensationShare);
|
||||
numIssuances = burningManCandidate.getCompensationModels().size();
|
||||
numIssuancesAsString = String.valueOf(numIssuances);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -444,6 +444,10 @@ public class BurningmenView extends ActivatableView<ScrollPane, Void> implements
|
|||
burningmenObservableList.setAll(burningManPresentationService.getBurningManCandidatesByName().entrySet().stream()
|
||||
.map(entry -> new BurningmenListItem(burningManPresentationService, entry.getKey(), entry.getValue(), bsqFormatter))
|
||||
.collect(Collectors.toList()));
|
||||
burningmenObservableList.add(new BurningmenListItem(burningManPresentationService,
|
||||
BurningManPresentationService.LEGACY_BURNING_MAN_NAME,
|
||||
burningManPresentationService.getLegacyBurningMan(),
|
||||
bsqFormatter));
|
||||
reimbursementObservableList.setAll(burningManPresentationService.getReimbursements().stream()
|
||||
.map(reimbursementModel -> new ReimbursementListItem(reimbursementModel, bsqFormatter))
|
||||
.collect(Collectors.toList()));
|
||||
|
@ -564,9 +568,7 @@ public class BurningmenView extends ActivatableView<ScrollPane, Void> implements
|
|||
public void updateItem(final BurningmenListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(Res.get("dao.burningmen.burnTarget.fromTo",
|
||||
item.getBurnTargetAsBsq(),
|
||||
item.getMaxBurnTargetAsBsq()));
|
||||
setText(item.getBurnTargetAsBsq());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
|
@ -614,13 +616,7 @@ public class BurningmenView extends ActivatableView<ScrollPane, Void> implements
|
|||
public void updateItem(final BurningmenListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
if (item.getBurnAmountShare() != item.getCappedBurnAmountShare()) {
|
||||
setText(Res.get("dao.burningmen.table.burnAmountShare.capped",
|
||||
item.getCappedBurnAmountShareAsString(),
|
||||
item.getBurnAmountShareAsString()));
|
||||
} else {
|
||||
setText(item.getBurnAmountShareAsString());
|
||||
}
|
||||
setText(item.getCappedBurnAmountShareAsString());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
|
@ -657,7 +653,7 @@ public class BurningmenView extends ActivatableView<ScrollPane, Void> implements
|
|||
column.setSortType(TableColumn.SortType.DESCENDING);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.burningmen.table.burnAmount"));
|
||||
column.setMinWidth(110);
|
||||
column.setMinWidth(130);
|
||||
column.getStyleClass().add("last-column");
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
|
@ -791,7 +787,7 @@ public class BurningmenView extends ActivatableView<ScrollPane, Void> implements
|
|||
public void updateItem(final BurningmenListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(String.valueOf(item.getNumIssuances()));
|
||||
setText(item.getNumIssuancesAsString());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue