mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Cleanup bond domain
This commit is contained in:
parent
edc1a35b15
commit
bee2d1ebd3
@ -25,16 +25,16 @@ import bisq.core.dao.governance.ballot.BallotListService;
|
||||
import bisq.core.dao.governance.blindvote.BlindVoteConsensus;
|
||||
import bisq.core.dao.governance.blindvote.MyBlindVoteListService;
|
||||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupService;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupType;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupReason;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupTxService;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputationService;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputationService;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputationRepository;
|
||||
import bisq.core.dao.governance.bond.reputation.MyReputationListService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesService;
|
||||
import bisq.core.dao.governance.bond.unlock.UnlockService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.governance.bond.unlock.UnlockTxService;
|
||||
import bisq.core.dao.governance.myvote.MyVote;
|
||||
import bisq.core.dao.governance.myvote.MyVoteListService;
|
||||
import bisq.core.dao.governance.param.Param;
|
||||
@ -119,12 +119,12 @@ public class DaoFacade implements DaoSetupService {
|
||||
private final RoleProposalFactory roleProposalFactory;
|
||||
private final GenericProposalFactory genericProposalFactory;
|
||||
private final RemoveAssetProposalFactory removeAssetProposalFactory;
|
||||
private final BondedRolesService bondedRolesService;
|
||||
private final BondedReputationService bondedReputationService;
|
||||
private final BondedRolesRepository bondedRolesRepository;
|
||||
private final BondedReputationRepository bondedReputationRepository;
|
||||
private final MyReputationListService myReputationListService;
|
||||
private final MyBondedReputationService myBondedReputationService;
|
||||
private final LockupService lockupService;
|
||||
private final UnlockService unlockService;
|
||||
private final MyBondedReputationRepository myBondedReputationRepository;
|
||||
private final LockupTxService lockupTxService;
|
||||
private final UnlockTxService unlockTxService;
|
||||
private final DaoStateStorageService daoStateStorageService;
|
||||
|
||||
private final ObjectProperty<DaoPhase.Phase> phaseProperty = new SimpleObjectProperty<>(DaoPhase.Phase.UNDEFINED);
|
||||
@ -145,12 +145,12 @@ public class DaoFacade implements DaoSetupService {
|
||||
RoleProposalFactory roleProposalFactory,
|
||||
GenericProposalFactory genericProposalFactory,
|
||||
RemoveAssetProposalFactory removeAssetProposalFactory,
|
||||
BondedRolesService bondedRolesService,
|
||||
BondedReputationService bondedReputationService,
|
||||
BondedRolesRepository bondedRolesRepository,
|
||||
BondedReputationRepository bondedReputationRepository,
|
||||
MyReputationListService myReputationListService,
|
||||
MyBondedReputationService myBondedReputationService,
|
||||
LockupService lockupService,
|
||||
UnlockService unlockService,
|
||||
MyBondedReputationRepository myBondedReputationRepository,
|
||||
LockupTxService lockupTxService,
|
||||
UnlockTxService unlockTxService,
|
||||
DaoStateStorageService daoStateStorageService) {
|
||||
this.proposalListPresentation = proposalListPresentation;
|
||||
this.ballotListService = ballotListService;
|
||||
@ -167,12 +167,12 @@ public class DaoFacade implements DaoSetupService {
|
||||
this.roleProposalFactory = roleProposalFactory;
|
||||
this.genericProposalFactory = genericProposalFactory;
|
||||
this.removeAssetProposalFactory = removeAssetProposalFactory;
|
||||
this.bondedRolesService = bondedRolesService;
|
||||
this.bondedReputationService = bondedReputationService;
|
||||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
this.bondedReputationRepository = bondedReputationRepository;
|
||||
this.myReputationListService = myReputationListService;
|
||||
this.myBondedReputationService = myBondedReputationService;
|
||||
this.lockupService = lockupService;
|
||||
this.unlockService = unlockService;
|
||||
this.myBondedReputationRepository = myBondedReputationRepository;
|
||||
this.lockupTxService = lockupTxService;
|
||||
this.unlockTxService = unlockTxService;
|
||||
this.daoStateStorageService = daoStateStorageService;
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ public class DaoFacade implements DaoSetupService {
|
||||
}
|
||||
|
||||
public List<BondedRole> getBondedRoles() {
|
||||
return bondedRolesService.getBonds();
|
||||
return bondedRolesRepository.getBonds();
|
||||
}
|
||||
|
||||
// Show fee
|
||||
@ -492,14 +492,14 @@ public class DaoFacade implements DaoSetupService {
|
||||
// Use case: Bonding
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void publishLockupTx(Coin lockupAmount, int lockTime, LockupType lockupType, byte[] hash,
|
||||
public void publishLockupTx(Coin lockupAmount, int lockTime, LockupReason lockupReason, byte[] hash,
|
||||
Consumer<String> resultHandler, ExceptionHandler exceptionHandler) {
|
||||
lockupService.publishLockupTx(lockupAmount, lockTime, lockupType, hash, resultHandler, exceptionHandler);
|
||||
lockupTxService.publishLockupTx(lockupAmount, lockTime, lockupReason, hash, resultHandler, exceptionHandler);
|
||||
}
|
||||
|
||||
public void publishUnlockTx(String lockupTxId, Consumer<String> resultHandler,
|
||||
ExceptionHandler exceptionHandler) {
|
||||
unlockService.publishUnlockTx(lockupTxId, resultHandler, exceptionHandler);
|
||||
unlockTxService.publishUnlockTx(lockupTxId, resultHandler, exceptionHandler);
|
||||
}
|
||||
|
||||
public long getTotalLockupAmount() {
|
||||
@ -519,19 +519,19 @@ public class DaoFacade implements DaoSetupService {
|
||||
}
|
||||
|
||||
public List<BondedRole> getActiveBondedRoles() {
|
||||
return bondedRolesService.getActiveBonds();
|
||||
return bondedRolesRepository.getActiveBonds();
|
||||
}
|
||||
|
||||
public List<Bond> getAllBonds() {
|
||||
List<BondedReputation> bondedReputations = bondedReputationService.getAllBonds();
|
||||
List<BondedRole> bondedRoles = bondedRolesService.getAllBonds();
|
||||
List<BondedReputation> bondedReputations = bondedReputationRepository.getBonds();
|
||||
List<BondedRole> bondedRoles = bondedRolesRepository.getBonds();
|
||||
List<Bond> bonds = new ArrayList<>(bondedReputations);
|
||||
bonds.addAll(bondedRoles);
|
||||
return bonds;
|
||||
}
|
||||
|
||||
public List<MyBondedReputation> getMyBondedReputations() {
|
||||
return myBondedReputationService.getMyBondedReputations();
|
||||
return myBondedReputationRepository.getMyBondedReputations();
|
||||
}
|
||||
|
||||
|
||||
@ -661,7 +661,7 @@ public class DaoFacade implements DaoSetupService {
|
||||
}
|
||||
|
||||
public boolean isMyRole(Role role) {
|
||||
return bondedRolesService.isMyRole(role);
|
||||
return bondedRolesRepository.isMyRole(role);
|
||||
}
|
||||
|
||||
public Optional<Bond> getBondByLockupTxId(String lockupTxId) {
|
||||
|
@ -26,12 +26,12 @@ import bisq.core.dao.governance.blindvote.MyBlindVoteListService;
|
||||
import bisq.core.dao.governance.blindvote.network.RepublishGovernanceDataHandler;
|
||||
import bisq.core.dao.governance.blindvote.storage.BlindVoteStorageService;
|
||||
import bisq.core.dao.governance.blindvote.storage.BlindVoteStore;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupService;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputationService;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputationService;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupTxService;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputationRepository;
|
||||
import bisq.core.dao.governance.bond.reputation.MyReputationListService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesService;
|
||||
import bisq.core.dao.governance.bond.unlock.UnlockService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.governance.bond.unlock.UnlockTxService;
|
||||
import bisq.core.dao.governance.myvote.MyVoteListService;
|
||||
import bisq.core.dao.governance.period.CycleService;
|
||||
import bisq.core.dao.governance.period.PeriodService;
|
||||
@ -186,12 +186,12 @@ public class DaoModule extends AppModule {
|
||||
bind(Integer.class).annotatedWith(Names.named(DaoOptionKeys.GENESIS_BLOCK_HEIGHT)).toInstance(genesisBlockHeight);
|
||||
|
||||
// Bonds
|
||||
bind(LockupService.class).in(Singleton.class);
|
||||
bind(UnlockService.class).in(Singleton.class);
|
||||
bind(BondedRolesService.class).in(Singleton.class);
|
||||
bind(BondedReputationService.class).in(Singleton.class);
|
||||
bind(LockupTxService.class).in(Singleton.class);
|
||||
bind(UnlockTxService.class).in(Singleton.class);
|
||||
bind(BondedRolesRepository.class).in(Singleton.class);
|
||||
bind(BondedReputationRepository.class).in(Singleton.class);
|
||||
bind(MyReputationListService.class).in(Singleton.class);
|
||||
bind(MyBondedReputationService.class).in(Singleton.class);
|
||||
bind(MyBondedReputationRepository.class).in(Singleton.class);
|
||||
|
||||
// Asset
|
||||
bind(AssetService.class).in(Singleton.class);
|
||||
|
@ -20,10 +20,10 @@ package bisq.core.dao;
|
||||
import bisq.core.dao.governance.ballot.BallotListService;
|
||||
import bisq.core.dao.governance.blindvote.BlindVoteListService;
|
||||
import bisq.core.dao.governance.blindvote.MyBlindVoteListService;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputationService;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputationService;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputationRepository;
|
||||
import bisq.core.dao.governance.bond.reputation.MyReputationListService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.governance.period.CycleService;
|
||||
import bisq.core.dao.governance.proposal.ProposalService;
|
||||
import bisq.core.dao.governance.voteresult.MissingDataRequestService;
|
||||
@ -60,10 +60,10 @@ public class DaoSetup {
|
||||
VoteRevealService voteRevealService,
|
||||
VoteResultService voteResultService,
|
||||
MissingDataRequestService missingDataRequestService,
|
||||
BondedReputationService bondedReputationService,
|
||||
BondedRolesService bondedRolesService,
|
||||
BondedReputationRepository bondedReputationRepository,
|
||||
BondedRolesRepository bondedRolesRepository,
|
||||
MyReputationListService myReputationListService,
|
||||
MyBondedReputationService myBondedReputationService,
|
||||
MyBondedReputationRepository myBondedReputationRepository,
|
||||
DaoFacade daoFacade,
|
||||
ExportJsonFilesService exportJsonFilesService) {
|
||||
|
||||
@ -79,10 +79,10 @@ public class DaoSetup {
|
||||
daoSetupServices.add(voteRevealService);
|
||||
daoSetupServices.add(voteResultService);
|
||||
daoSetupServices.add(missingDataRequestService);
|
||||
daoSetupServices.add(bondedReputationService);
|
||||
daoSetupServices.add(bondedRolesService);
|
||||
daoSetupServices.add(bondedReputationRepository);
|
||||
daoSetupServices.add(bondedRolesRepository);
|
||||
daoSetupServices.add(myReputationListService);
|
||||
daoSetupServices.add(myBondedReputationService);
|
||||
daoSetupServices.add(myBondedReputationRepository);
|
||||
daoSetupServices.add(daoFacade);
|
||||
daoSetupServices.add(exportJsonFilesService);
|
||||
daoSetupServices.add(bsqNodeProvider.getBsqNode());
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
package bisq.core.dao.governance.bond;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
import java.util.Objects;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -25,7 +25,7 @@ import lombok.Setter;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Base class for BondedRole and BondedAsset. Holds the bond state of the bonded asset.
|
||||
* Base class for BondedRole and BondedReputation. Holds the state of the bonded asset.
|
||||
*/
|
||||
@Getter
|
||||
public abstract class Bond<T extends BondedAsset> {
|
||||
@ -48,8 +48,7 @@ public abstract class Bond<T extends BondedAsset> {
|
||||
@Setter
|
||||
private int lockTime;
|
||||
|
||||
|
||||
public Bond(T bondedAsset) {
|
||||
protected Bond(T bondedAsset) {
|
||||
this.bondedAsset = bondedAsset;
|
||||
}
|
||||
|
||||
@ -58,8 +57,26 @@ public abstract class Bond<T extends BondedAsset> {
|
||||
bondState != BondState.UNLOCKED;
|
||||
}
|
||||
|
||||
public String getDisplayString() {
|
||||
return Res.get("dao.bonding.info", lockupTxId, getBondedAsset().getDisplayString());
|
||||
// Enums must not be used directly for hashCode or equals as it delivers the Object.hashCode (internal address)!
|
||||
// The equals and hashCode methods cannot be overwritten in Enums.
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Bond)) return false;
|
||||
Bond<?> bond = (Bond<?>) o;
|
||||
return amount == bond.amount &&
|
||||
lockupDate == bond.lockupDate &&
|
||||
unlockDate == bond.unlockDate &&
|
||||
lockTime == bond.lockTime &&
|
||||
Objects.equals(bondedAsset, bond.bondedAsset) &&
|
||||
Objects.equals(lockupTxId, bond.lockupTxId) &&
|
||||
Objects.equals(unlockTxId, bond.unlockTxId) &&
|
||||
bondState.name().equals(bond.bondState.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(bondedAsset, lockupTxId, unlockTxId, bondState.name(), amount, lockupDate, unlockDate, lockTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -72,6 +89,7 @@ public abstract class Bond<T extends BondedAsset> {
|
||||
",\n amount=" + amount +
|
||||
",\n lockupDate=" + lockupDate +
|
||||
",\n unlockDate=" + unlockDate +
|
||||
",\n lockTime=" + lockTime +
|
||||
"\n}";
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
package bisq.core.dao.governance.bond;
|
||||
|
||||
import bisq.core.dao.governance.bond.lockup.LockupType;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupReason;
|
||||
import bisq.core.dao.state.model.blockchain.OpReturnType;
|
||||
|
||||
import bisq.common.app.Version;
|
||||
@ -44,13 +44,13 @@ public class BondConsensus {
|
||||
@Getter
|
||||
private static int maxLockTime = 65535;
|
||||
|
||||
public static byte[] getLockupOpReturnData(int lockTime, LockupType type, byte[] hash) throws IOException {
|
||||
public static byte[] getLockupOpReturnData(int lockTime, LockupReason type, byte[] hash) throws IOException {
|
||||
// PushData of <= 4 bytes is converted to int when returned from bitcoind and not handled the way we
|
||||
// require by btcd-cli4j, avoid opReturns with 4 bytes or less
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
outputStream.write(OpReturnType.LOCKUP.getType());
|
||||
outputStream.write(Version.LOCKUP);
|
||||
outputStream.write(type.getType());
|
||||
outputStream.write(type.getId());
|
||||
byte[] bytes = Utilities.integerToByteArray(lockTime, 2);
|
||||
outputStream.write(bytes[0]);
|
||||
outputStream.write(bytes[1]);
|
||||
@ -72,19 +72,19 @@ public class BondConsensus {
|
||||
return Utilities.byteArrayToInteger(Arrays.copyOfRange(opReturnData, 3, 5));
|
||||
}
|
||||
|
||||
public static byte[] getHashFromOpReturnData(byte[] opReturnData) {
|
||||
return Arrays.copyOfRange(opReturnData, 5, 25);
|
||||
}
|
||||
|
||||
public static boolean isLockTimeInValidRange(int lockTime) {
|
||||
return lockTime >= BondConsensus.getMinLockTime() && lockTime <= BondConsensus.getMaxLockTime();
|
||||
}
|
||||
|
||||
public static Optional<LockupType> getLockupType(byte[] opReturnData) {
|
||||
return LockupType.getLockupType(opReturnData[2]);
|
||||
public static Optional<LockupReason> getLockupReason(byte[] opReturnData) {
|
||||
return LockupReason.getLockupReason(opReturnData[2]);
|
||||
}
|
||||
|
||||
public static boolean isLockTimeOver(long unlockBlockHeight, long currentBlockHeight) {
|
||||
return currentBlockHeight >= unlockBlockHeight;
|
||||
}
|
||||
|
||||
public static byte[] getHashFromOpReturnData(byte[] opReturnData) {
|
||||
return Arrays.copyOfRange(opReturnData, 5, 25);
|
||||
}
|
||||
}
|
||||
|
@ -40,95 +40,21 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* Manages bonds.
|
||||
* Collect bonds and bond asset data from other sources and provides access to the collection.
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BondService<T extends Bond, R extends BondedAsset> implements DaoStateListener, DaoSetupService {
|
||||
protected final DaoStateService daoStateService;
|
||||
protected final BsqWalletService bsqWalletService;
|
||||
|
||||
// This map is just for convenience. The data which are used to fill the map are stored in the DaoState (role, txs).
|
||||
protected final Map<String, T> bondByUidMap = new HashMap<>();
|
||||
|
||||
public abstract class BondRepository<T extends Bond, R extends BondedAsset> implements DaoStateListener, DaoSetupService {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
// Static
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public BondService(DaoStateService daoStateService, BsqWalletService bsqWalletService) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
|
||||
daoStateService.addBsqStateListener(this);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoSetupService
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void addListeners() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
updateMap();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
// TODO optimize to not re-write the whole map at each block
|
||||
updateMap();
|
||||
}
|
||||
|
||||
protected void updateMap() {
|
||||
getBondedAssetStream().forEach(bondedAsset -> {
|
||||
String uid = bondedAsset.getUid();
|
||||
bondByUidMap.putIfAbsent(uid, createBond(bondedAsset));
|
||||
T bond = bondByUidMap.get(uid);
|
||||
|
||||
daoStateService.getLockupTxOutputs().forEach(lockupTxOutput -> {
|
||||
updateBond(bond, bondedAsset, lockupTxOutput);
|
||||
});
|
||||
});
|
||||
|
||||
updateBondStateFromUnconfirmedLockupTxs();
|
||||
updateBondStateFromUnconfirmedUnlockTxs();
|
||||
}
|
||||
|
||||
public void updateBond(T bond, R bondedAsset, TxOutput lockupTxOutput) {
|
||||
// Lets see if we have a lock up tx.
|
||||
String lockupTxId = lockupTxOutput.getTxId();
|
||||
daoStateService.getTx(lockupTxId).ifPresent(lockupTx -> {
|
||||
byte[] opReturnData = lockupTx.getLastTxOutput().getOpReturnData();
|
||||
// We used the hash of th bonded bondedAsset object as our hash in OpReturn of the lock up tx to have a
|
||||
// unique binding of the tx to the data object.
|
||||
byte[] hash = BondConsensus.getHashFromOpReturnData(opReturnData);
|
||||
Optional<R> candidate = findBondedAssetByHash(hash);
|
||||
if (candidate.isPresent() && bondedAsset.equals(candidate.get()))
|
||||
applyBondState(daoStateService, bond, lockupTx, lockupTxOutput);
|
||||
});
|
||||
}
|
||||
|
||||
public static void applyBondState(DaoStateService daoStateService, Bond bond, Tx lockupTx, TxOutput lockupTxOutput) {
|
||||
if (bond.getBondState() != BondState.LOCKUP_TX_PENDING || bond.getBondState() != BondState.UNLOCK_TX_PENDING)
|
||||
bond.setBondState(BondState.LOCKUP_TX_CONFIRMED);
|
||||
@ -166,89 +92,6 @@ public abstract class BondService<T extends Bond, R extends BondedAsset> impleme
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract T createBond(R bondedAsset);
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public List<T> getBonds() {
|
||||
return new ArrayList<>(bondByUidMap.values());
|
||||
}
|
||||
|
||||
public List<T> getActiveBonds() {
|
||||
return bondByUidMap.values().stream()
|
||||
.filter(T::isActive)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<T> getAllBonds() {
|
||||
return new ArrayList<>(bondByUidMap.values());
|
||||
}
|
||||
|
||||
public Optional<T> findBondByLockupTxId(String lockupTxId) {
|
||||
return bondByUidMap.values().stream()
|
||||
.filter(bond -> lockupTxId.equals(bond.getLockupTxId()))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
public boolean wasBondedAssetAlreadyBonded(R bondedAsset) {
|
||||
T bond = bondByUidMap.get(bondedAsset.getUid());
|
||||
checkArgument(bond != null, "bond must not be null");
|
||||
return bond.getLockupTxId() != null;
|
||||
}
|
||||
|
||||
public Optional<R> findBondedAssetByHash(byte[] hash) {
|
||||
return getBondedAssetStream()
|
||||
.filter(bondedAsset -> Arrays.equals(bondedAsset.getHash(), hash))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
abstract protected Stream<R> getBondedAssetStream();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void updateBondStateFromUnconfirmedLockupTxs() {
|
||||
getBondedAssetStream().filter(bondedAsset -> isLockupTxUnconfirmed(bsqWalletService, bondedAsset))
|
||||
.map(bondedAsset -> bondByUidMap.get(bondedAsset.getUid()))
|
||||
.filter(bond -> bond.getBondState() == BondState.READY_FOR_LOCKUP)
|
||||
.forEach(bond -> {
|
||||
if ((bond.getLockupTxId() != null && daoStateService.isConfiscatedLockupTxOutput(bond.getLockupTxId())) ||
|
||||
(bond.getUnlockTxId() != null && daoStateService.isConfiscatedUnlockTxOutput(bond.getUnlockTxId()))) {
|
||||
bond.setBondState(BondState.CONFISCATED);
|
||||
} else {
|
||||
bond.setBondState(BondState.LOCKUP_TX_PENDING);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateBondStateFromUnconfirmedUnlockTxs() {
|
||||
getBondedAssetStream().filter(bondedAsset -> isUnlockTxUnconfirmed(bsqWalletService, daoStateService, bondedAsset))
|
||||
.map(bondedAsset -> bondByUidMap.get(bondedAsset.getUid()))
|
||||
.filter(bond -> bond.getBondState() == BondState.LOCKUP_TX_CONFIRMED)
|
||||
.forEach(bond -> {
|
||||
if ((bond.getLockupTxId() != null && daoStateService.isConfiscatedLockupTxOutput(bond.getLockupTxId())) ||
|
||||
(bond.getUnlockTxId() != null && daoStateService.isConfiscatedUnlockTxOutput(bond.getUnlockTxId()))) {
|
||||
bond.setBondState(BondState.CONFISCATED);
|
||||
} else {
|
||||
bond.setBondState(BondState.UNLOCK_TX_PENDING);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isLockupTxUnconfirmed(BsqWalletService bsqWalletService, BondedAsset bondedAsset) {
|
||||
return bsqWalletService.getPendingWalletTransactionsStream()
|
||||
.map(transaction -> transaction.getOutputs().get(transaction.getOutputs().size() - 1))
|
||||
@ -274,4 +117,127 @@ public abstract class BondService<T extends Bond, R extends BondedAsset> impleme
|
||||
.map(BaseTxOutput::getOpReturnData)
|
||||
.anyMatch(data -> Arrays.equals(BondConsensus.getHashFromOpReturnData(data), bondedAsset.getHash()));
|
||||
}
|
||||
|
||||
public static boolean isConfiscated(Bond bond, DaoStateService daoStateService) {
|
||||
return (bond.getLockupTxId() != null && daoStateService.isConfiscatedLockupTxOutput(bond.getLockupTxId())) ||
|
||||
(bond.getUnlockTxId() != null && daoStateService.isConfiscatedUnlockTxOutput(bond.getUnlockTxId()));
|
||||
}
|
||||
|
||||
|
||||
protected final DaoStateService daoStateService;
|
||||
protected final BsqWalletService bsqWalletService;
|
||||
|
||||
// This map is just for convenience. The data which are used to fill the map are stored in the DaoState (role, txs).
|
||||
protected final Map<String, T> bondByUidMap = new HashMap<>();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public BondRepository(DaoStateService daoStateService, BsqWalletService bsqWalletService) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
|
||||
daoStateService.addBsqStateListener(this);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoSetupService
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void addListeners() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
updateMap();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
// TODO optimize to not re-write the whole map at each block
|
||||
updateMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public List<T> getBonds() {
|
||||
return new ArrayList<>(bondByUidMap.values());
|
||||
}
|
||||
|
||||
public List<T> getActiveBonds() {
|
||||
return bondByUidMap.values().stream()
|
||||
.filter(T::isActive)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public boolean isBondedAssetAlreadyInBond(R bondedAsset) {
|
||||
boolean contains = bondByUidMap.containsKey(bondedAsset.getUid());
|
||||
return contains && bondByUidMap.get(bondedAsset.getUid()).getLockupTxId() != null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
abstract protected T createBond(R bondedAsset);
|
||||
|
||||
abstract protected void updateBond(T bond, R bondedAsset, TxOutput lockupTxOutput);
|
||||
|
||||
abstract protected Stream<R> getBondedAssetStream();
|
||||
|
||||
protected void updateMap() {
|
||||
getBondedAssetStream().forEach(bondedAsset -> {
|
||||
String uid = bondedAsset.getUid();
|
||||
bondByUidMap.putIfAbsent(uid, createBond(bondedAsset));
|
||||
T bond = bondByUidMap.get(uid);
|
||||
|
||||
daoStateService.getLockupTxOutputs().forEach(lockupTxOutput -> {
|
||||
updateBond(bond, bondedAsset, lockupTxOutput);
|
||||
});
|
||||
});
|
||||
|
||||
updateBondStateFromUnconfirmedLockupTxs();
|
||||
updateBondStateFromUnconfirmedUnlockTxs();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void updateBondStateFromUnconfirmedLockupTxs() {
|
||||
getBondedAssetStream().filter(bondedAsset -> isLockupTxUnconfirmed(bsqWalletService, bondedAsset))
|
||||
.map(bondedAsset -> bondByUidMap.get(bondedAsset.getUid()))
|
||||
.filter(bond -> bond.getBondState() == BondState.READY_FOR_LOCKUP)
|
||||
.forEach(bond -> bond.setBondState(isConfiscated(bond, daoStateService) ? BondState.CONFISCATED : BondState.LOCKUP_TX_PENDING));
|
||||
}
|
||||
|
||||
private void updateBondStateFromUnconfirmedUnlockTxs() {
|
||||
getBondedAssetStream().filter(bondedAsset -> isUnlockTxUnconfirmed(bsqWalletService, daoStateService, bondedAsset))
|
||||
.map(bondedAsset -> bondByUidMap.get(bondedAsset.getUid()))
|
||||
.filter(bond -> bond.getBondState() == BondState.LOCKUP_TX_CONFIRMED)
|
||||
.forEach(bond -> bond.setBondState(isConfiscated(bond, daoStateService) ? BondState.CONFISCATED : BondState.UNLOCK_TX_PENDING));
|
||||
}
|
||||
}
|
@ -17,14 +17,17 @@
|
||||
|
||||
package bisq.core.dao.governance.bond;
|
||||
|
||||
// Used in string properties ("dao.bond.bondState.*")
|
||||
/**
|
||||
* Holds the different states of a bond.
|
||||
* Used also in string properties ("dao.bond.bondState.*")
|
||||
*/
|
||||
public enum BondState {
|
||||
READY_FOR_LOCKUP, // Accepted by voting but no lockup tx made yet.
|
||||
READY_FOR_LOCKUP, // Accepted by voting (if role) but no lockup tx made yet.
|
||||
LOCKUP_TX_PENDING, // Tx broadcasted but not confirmed. Used only by tx publisher.
|
||||
LOCKUP_TX_CONFIRMED,
|
||||
UNLOCK_TX_PENDING, // Tx broadcasted but not confirmed. Used only by tx publisher.
|
||||
UNLOCK_TX_CONFIRMED,
|
||||
UNLOCKING, // lock time not expired
|
||||
UNLOCKED,
|
||||
CONFISCATED
|
||||
UNLOCKING, // Lock time still not expired
|
||||
UNLOCKED, // Fully unlocked
|
||||
CONFISCATED // Bond got confiscated by DAO voting
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
package bisq.core.dao.governance.bond;
|
||||
|
||||
/**
|
||||
* Interface of the bonded asset like the Role or Reputation.
|
||||
* Represents the bonded asset (e.g. Role or Reputation).
|
||||
*/
|
||||
public interface BondedAsset {
|
||||
byte[] getHash();
|
||||
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.core.dao.governance.bond;
|
||||
|
||||
import bisq.common.proto.persistable.PersistablePayload;
|
||||
|
||||
import io.bisq.generated.protobuffer.PB;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* Holds the hash of a confiscated bond.
|
||||
*/
|
||||
@Immutable
|
||||
@Value
|
||||
public class ConfiscateBond implements PersistablePayload {
|
||||
private final String lockupTxId;
|
||||
|
||||
public ConfiscateBond(String lockupTxId) {
|
||||
this.lockupTxId = lockupTxId;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PROTO BUFFER
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
public PB.ConfiscateBond toProtoMessage() {
|
||||
return PB.ConfiscateBond.newBuilder()
|
||||
.setLockupTxId(lockupTxId)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ConfiscateBond fromProto(PB.ConfiscateBond proto) {
|
||||
return new ConfiscateBond(proto.getLockupTxId());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConfiscateBond{" +
|
||||
"\n lockupTxId='" + lockupTxId + '\'' +
|
||||
"\n}";
|
||||
}
|
||||
}
|
@ -17,33 +17,32 @@
|
||||
|
||||
package bisq.core.dao.governance.bond.lockup;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public enum LockupType {
|
||||
/**
|
||||
* Reason for locking up a bond.
|
||||
*/
|
||||
public enum LockupReason {
|
||||
BONDED_ROLE((byte) 0x01),
|
||||
REPUTATION((byte) 0x02);
|
||||
|
||||
@Getter
|
||||
private byte type;
|
||||
private byte id;
|
||||
|
||||
LockupType(byte type) {
|
||||
this.type = type;
|
||||
LockupReason(byte id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDisplayString() {
|
||||
/* public String getDisplayString() {
|
||||
return Res.get("dao.bond.lockupType." + name());
|
||||
}
|
||||
}*/
|
||||
|
||||
public static Optional<LockupType> getLockupType(byte type) {
|
||||
return Arrays.stream(LockupType.values())
|
||||
.filter(lockupType -> lockupType.type == type)
|
||||
.map(Optional::of)
|
||||
.findAny()
|
||||
.orElse(Optional.empty());
|
||||
public static Optional<LockupReason> getLockupReason(byte id) {
|
||||
return Arrays.stream(LockupReason.values())
|
||||
.filter(lockupType -> lockupType.id == id)
|
||||
.findAny();
|
||||
}
|
||||
}
|
@ -43,8 +43,11 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* Service for publishing the lockup transaction.
|
||||
*/
|
||||
@Slf4j
|
||||
public class LockupService {
|
||||
public class LockupTxService {
|
||||
private final WalletsManager walletsManager;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final BtcWalletService btcWalletService;
|
||||
@ -55,7 +58,7 @@ public class LockupService {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public LockupService(WalletsManager walletsManager,
|
||||
public LockupTxService(WalletsManager walletsManager,
|
||||
BsqWalletService bsqWalletService,
|
||||
BtcWalletService btcWalletService) {
|
||||
this.walletsManager = walletsManager;
|
||||
@ -63,15 +66,14 @@ public class LockupService {
|
||||
this.btcWalletService = btcWalletService;
|
||||
}
|
||||
|
||||
public void publishLockupTx(Coin lockupAmount, int lockTime, LockupType lockupType, byte[] hash,
|
||||
public void publishLockupTx(Coin lockupAmount, int lockTime, LockupReason lockupReason, byte[] hash,
|
||||
Consumer<String> resultHandler, ExceptionHandler exceptionHandler) {
|
||||
checkArgument(lockTime <= BondConsensus.getMaxLockTime() &&
|
||||
lockTime >= BondConsensus.getMinLockTime(), "lockTime not in rage");
|
||||
lockTime >= BondConsensus.getMinLockTime(), "lockTime not in range");
|
||||
try {
|
||||
byte[] opReturnData = BondConsensus.getLockupOpReturnData(lockTime, lockupType, hash);
|
||||
byte[] opReturnData = BondConsensus.getLockupOpReturnData(lockTime, lockupReason, hash);
|
||||
Transaction lockupTx = createLockupTx(lockupAmount, opReturnData);
|
||||
|
||||
//noinspection Duplicates
|
||||
walletsManager.publishAndCommitBsqTx(lockupTx, new TxBroadcaster.Callback() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
@ -99,6 +101,8 @@ public class LockupService {
|
||||
throws InsufficientMoneyException, WalletException, TransactionVerificationException {
|
||||
Transaction preparedTx = bsqWalletService.getPreparedLockupTx(lockupAmount);
|
||||
Transaction txWithBtcFee = btcWalletService.completePreparedBsqTx(preparedTx, true, opReturnData);
|
||||
return bsqWalletService.signTx(txWithBtcFee);
|
||||
Transaction transaction = bsqWalletService.signTx(txWithBtcFee);
|
||||
log.info("Lockup tx: " + transaction);
|
||||
return transaction;
|
||||
}
|
||||
}
|
@ -29,11 +29,10 @@ import lombok.Getter;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public final class BondedReputation extends Bond<Reputation> {
|
||||
|
||||
public BondedReputation(Reputation reputation) {
|
||||
BondedReputation(Reputation reputation) {
|
||||
super(reputation);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BondedReputation{" +
|
||||
|
@ -20,8 +20,8 @@ package bisq.core.dao.governance.bond.reputation;
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.BondConsensus;
|
||||
import bisq.core.dao.governance.bond.BondService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesService;
|
||||
import bisq.core.dao.governance.bond.BondRepository;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.blockchain.TxOutput;
|
||||
|
||||
@ -35,20 +35,24 @@ import java.util.stream.Stream;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Collect bonded reputations from the daoState blockchain data excluding bonded roles
|
||||
* and provides access to the collection.
|
||||
*/
|
||||
@Slf4j
|
||||
public class BondedReputationService extends BondService<BondedReputation, Reputation> {
|
||||
private final BondedRolesService bondedRolesService;
|
||||
public class BondedReputationRepository extends BondRepository<BondedReputation, Reputation> {
|
||||
private final BondedRolesRepository bondedRolesRepository;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public BondedReputationService(DaoStateService daoStateService, BsqWalletService bsqWalletService,
|
||||
BondedRolesService bondedRolesService) {
|
||||
public BondedReputationRepository(DaoStateService daoStateService, BsqWalletService bsqWalletService,
|
||||
BondedRolesRepository bondedRolesRepository) {
|
||||
super(daoStateService, bsqWalletService);
|
||||
|
||||
this.bondedRolesService = bondedRolesService;
|
||||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
}
|
||||
|
||||
|
||||
@ -69,18 +73,13 @@ public class BondedReputationService extends BondService<BondedReputation, Reput
|
||||
@Override
|
||||
protected void updateMap() {
|
||||
bondByUidMap.clear();
|
||||
getBondedReputationStream().forEach(bondedReputation -> {
|
||||
bondByUidMap.put(bondedReputation.getBondedAsset().getUid(), bondedReputation);
|
||||
});
|
||||
getBondedReputationStream().forEach(bondedReputation -> bondByUidMap.put(bondedReputation.getBondedAsset().getUid(), bondedReputation));
|
||||
}
|
||||
|
||||
private Stream<BondedReputation> getBondedReputationStream() {
|
||||
Set<String> bondedRolesLockupTxIdSet = bondedRolesService.getAllBonds().stream().map(e -> e.getLockupTxId()).collect(Collectors.toSet());
|
||||
return daoStateService.getLockupTxOutputs().stream()
|
||||
return getLockupTxOutputsForBondedReputation()
|
||||
.map(lockupTxOutput -> {
|
||||
String lockupTxId = lockupTxOutput.getTxId();
|
||||
// long time = daoStateService.getTx(lockupTxId).map(BaseTx::getTime).orElse(0L);
|
||||
// lockupTxOutput is first output, but we need the data from the opReturn
|
||||
Optional<TxOutput> optionalOpReturnTxOutput = daoStateService.getLockupOpReturnTxOutput(lockupTxId);
|
||||
if (optionalOpReturnTxOutput.isPresent()) {
|
||||
TxOutput opReturnTxOutput = optionalOpReturnTxOutput.get();
|
||||
@ -94,16 +93,22 @@ public class BondedReputationService extends BondService<BondedReputation, Reput
|
||||
}
|
||||
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.filter(e -> !bondedRolesLockupTxIdSet.contains(e.getLockupTxId()));
|
||||
.filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
private Stream<TxOutput> getLockupTxOutputsForBondedReputation() {
|
||||
// We exclude bonded roles, so we store those ina lookup set.
|
||||
Set<String> bondedRolesLockupTxIdSet = bondedRolesRepository.getBonds().stream().map(Bond::getLockupTxId).collect(Collectors.toSet());
|
||||
return daoStateService.getLockupTxOutputs().stream()
|
||||
.filter(e -> !bondedRolesLockupTxIdSet.contains(e.getTxId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBond(BondedReputation bond, Reputation bondedAsset, TxOutput lockupTxOutput) {
|
||||
protected void updateBond(BondedReputation bond, Reputation bondedAsset, TxOutput lockupTxOutput) {
|
||||
// Lets see if we have a lock up tx.
|
||||
String lockupTxId = lockupTxOutput.getTxId();
|
||||
daoStateService.getTx(lockupTxId).ifPresent(lockupTx -> {
|
||||
applyBondState(daoStateService, bond, lockupTx, lockupTxOutput);
|
||||
BondRepository.applyBondState(daoStateService, bond, lockupTx, lockupTxOutput);
|
||||
});
|
||||
}
|
||||
}
|
@ -23,7 +23,8 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Wrapper for reputation which contains the mutable state of a bonded reputation. Only kept in memory.
|
||||
* Wrapper for reputation which contains the mutable state of my bonded reputation. Only kept in memory.
|
||||
* As it carries MyReputation it has access to the private salt data.
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
|
@ -20,7 +20,7 @@ package bisq.core.dao.governance.bond.reputation;
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.DaoSetupService;
|
||||
import bisq.core.dao.governance.bond.BondConsensus;
|
||||
import bisq.core.dao.governance.bond.BondService;
|
||||
import bisq.core.dao.governance.bond.BondRepository;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
|
||||
@ -36,8 +36,11 @@ import java.util.stream.Stream;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Collect MyBondedReputations from the myReputationListService and provides access to the collection.
|
||||
*/
|
||||
@Slf4j
|
||||
public class MyBondedReputationService implements DaoSetupService {
|
||||
public class MyBondedReputationRepository implements DaoSetupService {
|
||||
private final DaoStateService daoStateService;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final MyReputationListService myReputationListService;
|
||||
@ -48,7 +51,7 @@ public class MyBondedReputationService implements DaoSetupService {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public MyBondedReputationService(DaoStateService daoStateService,
|
||||
public MyBondedReputationRepository(DaoStateService daoStateService,
|
||||
BsqWalletService bsqWalletService,
|
||||
MyReputationListService myReputationListService) {
|
||||
this.daoStateService = daoStateService;
|
||||
@ -75,25 +78,24 @@ public class MyBondedReputationService implements DaoSetupService {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public List<MyBondedReputation> getMyBondedReputations() {
|
||||
// It can be that the same salt/hash is in several lockupTxs, so we use a map to eliminate duplicates by the
|
||||
// collection algorithm.
|
||||
Map<String, MyBondedReputation> map = new HashMap<>();
|
||||
// It can be that the same salt/hash is in several lockupTxs, so we use the bondByLockupTxIdMap to eliminate
|
||||
// duplicates by the collection algorithm.
|
||||
Map<String, MyBondedReputation> bondByLockupTxIdMap = new HashMap<>();
|
||||
myReputationListService.getMyReputationList().stream()
|
||||
.flatMap(this::getMyBondedReputation)
|
||||
.forEach(e -> map.putIfAbsent(e.getLockupTxId(), e));
|
||||
.forEach(e -> bondByLockupTxIdMap.putIfAbsent(e.getLockupTxId(), e));
|
||||
|
||||
return map.values().stream()
|
||||
return bondByLockupTxIdMap.values().stream()
|
||||
.peek(myBondedReputation -> {
|
||||
if ((myBondedReputation.getLockupTxId() != null && daoStateService.isConfiscatedLockupTxOutput(myBondedReputation.getLockupTxId())) ||
|
||||
(myBondedReputation.getUnlockTxId() != null && daoStateService.isConfiscatedUnlockTxOutput(myBondedReputation.getUnlockTxId()))) {
|
||||
if (BondRepository.isConfiscated(myBondedReputation, daoStateService)) {
|
||||
myBondedReputation.setBondState(BondState.CONFISCATED);
|
||||
} else {
|
||||
// We don't have a UI use case for showing LOCKUP_TX_PENDING yet, but lets keep the code so if needed
|
||||
// its there.
|
||||
if (BondService.isLockupTxUnconfirmed(bsqWalletService, myBondedReputation.getBondedAsset()) &&
|
||||
if (BondRepository.isLockupTxUnconfirmed(bsqWalletService, myBondedReputation.getBondedAsset()) &&
|
||||
myBondedReputation.getBondState() == BondState.READY_FOR_LOCKUP) {
|
||||
myBondedReputation.setBondState(BondState.LOCKUP_TX_PENDING);
|
||||
} else if (BondService.isUnlockTxUnconfirmed(bsqWalletService, daoStateService, myBondedReputation.getBondedAsset()) &&
|
||||
} else if (BondRepository.isUnlockTxUnconfirmed(bsqWalletService, daoStateService, myBondedReputation.getBondedAsset()) &&
|
||||
myBondedReputation.getBondState() == BondState.LOCKUP_TX_CONFIRMED) {
|
||||
myBondedReputation.setBondState(BondState.UNLOCK_TX_PENDING);
|
||||
}
|
||||
@ -110,9 +112,10 @@ public class MyBondedReputationService implements DaoSetupService {
|
||||
.map(lockupTx -> {
|
||||
byte[] opReturnData = lockupTx.getLastTxOutput().getOpReturnData();
|
||||
byte[] hash = BondConsensus.getHashFromOpReturnData(opReturnData);
|
||||
// There could be multiple txs with the same hash, so we collect a stream and not use an optional.
|
||||
if (Arrays.equals(hash, myReputation.getHash())) {
|
||||
MyBondedReputation myBondedReputation = new MyBondedReputation(myReputation);
|
||||
BondService.applyBondState(daoStateService, myBondedReputation, lockupTx, lockupTxOutput);
|
||||
BondRepository.applyBondState(daoStateService, myBondedReputation, lockupTx, lockupTxOutput);
|
||||
return myBondedReputation;
|
||||
} else {
|
||||
return null;
|
@ -37,13 +37,18 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* MyReputation is persisted locally and carries the private salt data. In contrast to Reputation which is the public
|
||||
* data everyone can derive from the blockchain data (hash in opReturn).
|
||||
*/
|
||||
@Immutable
|
||||
@Value
|
||||
@Slf4j
|
||||
public final class MyReputation implements PersistablePayload, NetworkPayload, BondedAsset {
|
||||
// Uid is needed to be sure that 2 objects with the same salt are kept separate.
|
||||
private final String uid;
|
||||
private final byte[] salt;
|
||||
private final transient byte[] hash; // not persisted as it is derived from salt. Stored for caching purpose only.
|
||||
private final transient byte[] hash; // Not persisted as it is derived from salt. Stored for caching purpose only.
|
||||
|
||||
public MyReputation(byte[] salt) {
|
||||
this(UUID.randomUUID().toString(), salt);
|
||||
|
@ -33,11 +33,11 @@ import lombok.EqualsAndHashCode;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MyReputationList extends PersistableList<MyReputation> {
|
||||
|
||||
public MyReputationList(List<MyReputation> list) {
|
||||
private MyReputationList(List<MyReputation> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
public MyReputationList() {
|
||||
MyReputationList() {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ public class MyReputationList extends PersistableList<MyReputation> {
|
||||
return PB.PersistableEnvelope.newBuilder().setMyReputationList(getBuilder()).build();
|
||||
}
|
||||
|
||||
public PB.MyReputationList.Builder getBuilder() {
|
||||
private PB.MyReputationList.Builder getBuilder() {
|
||||
return PB.MyReputationList.newBuilder()
|
||||
.addAllMyReputation(getList().stream()
|
||||
.map(MyReputation::toProtoMessage)
|
||||
|
@ -31,10 +31,14 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Manages the persistence of myReputation objects.
|
||||
*/
|
||||
@Slf4j
|
||||
public class MyReputationListService implements PersistedDataHost, DaoSetupService {
|
||||
|
||||
public interface MyReputationListChangeListener {
|
||||
@SuppressWarnings("unused")
|
||||
interface MyReputationListChangeListener {
|
||||
void onListChanged(List<MyReputation> list);
|
||||
}
|
||||
|
||||
@ -88,10 +92,6 @@ public class MyReputationListService implements PersistedDataHost, DaoSetupServi
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void addListener(MyReputationListChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void addReputation(MyReputation reputation) {
|
||||
if (!myReputationList.contains(reputation)) {
|
||||
myReputationList.add(reputation);
|
||||
@ -103,6 +103,11 @@ public class MyReputationListService implements PersistedDataHost, DaoSetupServi
|
||||
return myReputationList.getList();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void addListener(MyReputationListChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
|
@ -30,6 +30,8 @@ import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* Reputation objects we found on the blockchain. We only know the hash of it.
|
||||
* In contrast to MyReputation which represents the object we created and contains the
|
||||
* private salt data.
|
||||
*/
|
||||
@Immutable
|
||||
@Value
|
||||
|
@ -18,10 +18,10 @@
|
||||
package bisq.core.dao.governance.bond.role;
|
||||
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.BondService;
|
||||
import bisq.core.dao.governance.bond.BondConsensus;
|
||||
import bisq.core.dao.governance.bond.BondRepository;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.governance.BondedRoleType;
|
||||
import bisq.core.dao.state.model.blockchain.TxOutput;
|
||||
import bisq.core.dao.state.model.governance.Proposal;
|
||||
import bisq.core.dao.state.model.governance.Role;
|
||||
import bisq.core.dao.state.model.governance.RoleProposal;
|
||||
@ -30,6 +30,7 @@ import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@ -38,17 +39,17 @@ import java.util.stream.Stream;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Manages bonded roles if they got accepted by voting.
|
||||
* Collect bonded roles from the evaluatedProposals from the daoState and provides access to the collection.
|
||||
*/
|
||||
@Slf4j
|
||||
public class BondedRolesService extends BondService<BondedRole, Role> {
|
||||
public class BondedRolesRepository extends BondRepository<BondedRole, Role> {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public BondedRolesService(DaoStateService daoStateService, BsqWalletService bsqWalletService) {
|
||||
public BondedRolesRepository(DaoStateService daoStateService, BsqWalletService bsqWalletService) {
|
||||
super(daoStateService, bsqWalletService);
|
||||
}
|
||||
|
||||
@ -67,12 +68,6 @@ public class BondedRolesService extends BondService<BondedRole, Role> {
|
||||
.anyMatch(myWalletTransactionIds::contains);
|
||||
}
|
||||
|
||||
public Optional<BondedRoleType> getBondedRoleType(String lockUpTxId) {
|
||||
return findBondByLockupTxId(lockUpTxId)
|
||||
.map(Bond::getBondedAsset)
|
||||
.map(Role::getBondedRoleType);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
@ -88,6 +83,27 @@ public class BondedRolesService extends BondService<BondedRole, Role> {
|
||||
return getBondedRoleProposalStream().map(RoleProposal::getRole);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateBond(BondedRole bond, Role bondedAsset, TxOutput lockupTxOutput) {
|
||||
// Lets see if we have a lock up tx.
|
||||
String lockupTxId = lockupTxOutput.getTxId();
|
||||
daoStateService.getTx(lockupTxId).ifPresent(lockupTx -> {
|
||||
byte[] opReturnData = lockupTx.getLastTxOutput().getOpReturnData();
|
||||
// We used the hash of th bonded bondedAsset object as our hash in OpReturn of the lock up tx to have a
|
||||
// unique binding of the tx to the data object.
|
||||
byte[] hash = BondConsensus.getHashFromOpReturnData(opReturnData);
|
||||
Optional<Role> candidate = findBondedAssetByHash(hash);
|
||||
if (candidate.isPresent() && bondedAsset.equals(candidate.get()))
|
||||
applyBondState(daoStateService, bond, lockupTx, lockupTxOutput);
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<Role> findBondedAssetByHash(byte[] hash) {
|
||||
return getBondedAssetStream()
|
||||
.filter(bondedAsset -> Arrays.equals(bondedAsset.getHash(), hash))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
private Stream<RoleProposal> getBondedRoleProposalStream() {
|
||||
return daoStateService.getEvaluatedProposalList().stream()
|
||||
.filter(evaluatedProposal -> evaluatedProposal.getProposal() instanceof RoleProposal)
|
@ -35,12 +35,18 @@ import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* Service for publishing the unlock transaction.
|
||||
*/
|
||||
@Slf4j
|
||||
public class UnlockService {
|
||||
public class UnlockTxService {
|
||||
private final WalletsManager walletsManager;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final BtcWalletService btcWalletService;
|
||||
@ -52,7 +58,7 @@ public class UnlockService {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public UnlockService(WalletsManager walletsManager,
|
||||
public UnlockTxService(WalletsManager walletsManager,
|
||||
BsqWalletService bsqWalletService,
|
||||
BtcWalletService btcWalletService,
|
||||
DaoStateService daoStateService) {
|
||||
@ -62,13 +68,12 @@ public class UnlockService {
|
||||
this.daoStateService = daoStateService;
|
||||
}
|
||||
|
||||
public void publishUnlockTx(String lockupTxId, Consumer<String> resultHandler,
|
||||
ExceptionHandler exceptionHandler) {
|
||||
public void publishUnlockTx(String lockupTxId, Consumer<String> resultHandler, ExceptionHandler exceptionHandler) {
|
||||
try {
|
||||
TxOutput lockupTxOutput = daoStateService.getLockupTxOutput(lockupTxId).get();
|
||||
final Transaction unlockTx = getUnlockTx(lockupTxOutput);
|
||||
|
||||
//noinspection Duplicates
|
||||
Optional<TxOutput> optionalLockupTxOutput = daoStateService.getLockupTxOutput(lockupTxId);
|
||||
checkArgument(optionalLockupTxOutput.isPresent(), "lockupTxOutput must be present");
|
||||
TxOutput lockupTxOutput = optionalLockupTxOutput.get();
|
||||
Transaction unlockTx = getUnlockTx(lockupTxOutput);
|
||||
walletsManager.publishAndCommitBsqTx(unlockTx, new TxBroadcaster.Callback() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
@ -94,8 +99,7 @@ public class UnlockService {
|
||||
throws InsufficientMoneyException, WalletException, TransactionVerificationException {
|
||||
Transaction preparedTx = bsqWalletService.getPreparedUnlockTx(lockupTxOutput);
|
||||
Transaction txWithBtcFee = btcWalletService.completePreparedBsqTx(preparedTx, true, null);
|
||||
final Transaction transaction = bsqWalletService.signTx(txWithBtcFee);
|
||||
|
||||
Transaction transaction = bsqWalletService.signTx(txWithBtcFee);
|
||||
log.info("Unlock tx: " + transaction);
|
||||
return transaction;
|
||||
}
|
@ -25,8 +25,7 @@ import bisq.core.dao.governance.blindvote.BlindVoteConsensus;
|
||||
import bisq.core.dao.governance.blindvote.BlindVoteListService;
|
||||
import bisq.core.dao.governance.blindvote.VoteWithProposalTxId;
|
||||
import bisq.core.dao.governance.blindvote.VoteWithProposalTxIdList;
|
||||
import bisq.core.dao.governance.bond.ConfiscateBond;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.governance.merit.MeritConsensus;
|
||||
import bisq.core.dao.governance.period.PeriodService;
|
||||
import bisq.core.dao.governance.proposal.IssuanceProposal;
|
||||
@ -103,7 +102,7 @@ public class VoteResultService implements DaoStateListener, DaoSetupService {
|
||||
private final PeriodService periodService;
|
||||
private final BallotListService ballotListService;
|
||||
private final BlindVoteListService blindVoteListService;
|
||||
private final BondedRolesService bondedRolesService;
|
||||
private final BondedRolesRepository bondedRolesRepository;
|
||||
private final IssuanceService issuanceService;
|
||||
private final AssetService assetService;
|
||||
private final MissingDataRequestService missingDataRequestService;
|
||||
@ -122,7 +121,7 @@ public class VoteResultService implements DaoStateListener, DaoSetupService {
|
||||
PeriodService periodService,
|
||||
BallotListService ballotListService,
|
||||
BlindVoteListService blindVoteListService,
|
||||
BondedRolesService bondedRolesService,
|
||||
BondedRolesRepository bondedRolesRepository,
|
||||
IssuanceService issuanceService,
|
||||
AssetService assetService,
|
||||
MissingDataRequestService missingDataRequestService) {
|
||||
@ -132,7 +131,7 @@ public class VoteResultService implements DaoStateListener, DaoSetupService {
|
||||
this.periodService = periodService;
|
||||
this.ballotListService = ballotListService;
|
||||
this.blindVoteListService = blindVoteListService;
|
||||
this.bondedRolesService = bondedRolesService;
|
||||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
this.issuanceService = issuanceService;
|
||||
this.assetService = assetService;
|
||||
this.missingDataRequestService = missingDataRequestService;
|
||||
@ -661,7 +660,7 @@ public class VoteResultService implements DaoStateListener, DaoSetupService {
|
||||
acceptedEvaluatedProposals.forEach(evaluatedProposal -> {
|
||||
if (evaluatedProposal.getProposal() instanceof ConfiscateBondProposal) {
|
||||
ConfiscateBondProposal confiscateBondProposal = (ConfiscateBondProposal) evaluatedProposal.getProposal();
|
||||
daoStateService.confiscateBond(new ConfiscateBond(confiscateBondProposal.getLockupTxId()));
|
||||
daoStateService.confiscateBond(confiscateBondProposal.getLockupTxId());
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("\n################################################################################\n");
|
||||
|
@ -19,7 +19,7 @@ package bisq.core.dao.node.parser;
|
||||
|
||||
import bisq.core.dao.governance.blindvote.BlindVoteConsensus;
|
||||
import bisq.core.dao.governance.bond.BondConsensus;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupType;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupReason;
|
||||
import bisq.core.dao.governance.proposal.ProposalConsensus;
|
||||
import bisq.core.dao.governance.voteresult.VoteResultConsensus;
|
||||
import bisq.core.dao.node.parser.exceptions.InvalidParsingConditionException;
|
||||
@ -107,9 +107,9 @@ class OpReturnParser {
|
||||
case LOCKUP:
|
||||
if (!BondConsensus.hasOpReturnDataValidLength(opReturnData))
|
||||
return TxOutputType.INVALID_OUTPUT;
|
||||
Optional<LockupType> lockupType = BondConsensus.getLockupType(opReturnData);
|
||||
if (!lockupType.isPresent()) {
|
||||
log.warn("No lockupType found for lockup tx, opReturnData=" + Utilities.encodeToHex(opReturnData));
|
||||
Optional<LockupReason> optionalLockupReason = BondConsensus.getLockupReason(opReturnData);
|
||||
if (!optionalLockupReason.isPresent()) {
|
||||
log.warn("No lockupReason found for lockup tx, opReturnData=" + Utilities.encodeToHex(opReturnData));
|
||||
return TxOutputType.INVALID_OUTPUT;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ package bisq.core.dao.state;
|
||||
|
||||
import bisq.core.dao.DaoSetupService;
|
||||
import bisq.core.dao.governance.bond.BondConsensus;
|
||||
import bisq.core.dao.governance.bond.ConfiscateBond;
|
||||
import bisq.core.dao.governance.param.Param;
|
||||
import bisq.core.dao.state.model.DaoState;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
@ -742,8 +741,7 @@ public class DaoStateService implements DaoSetupService {
|
||||
}
|
||||
|
||||
// Confiscate bond
|
||||
public void confiscateBond(ConfiscateBond confiscateBond) {
|
||||
String lockupTxId = confiscateBond.getLockupTxId();
|
||||
public void confiscateBond(String lockupTxId) {
|
||||
Optional<TxOutput> optionalTxOutput = getLockupTxOutput(lockupTxId);
|
||||
if (optionalTxOutput.isPresent()) {
|
||||
TxOutput lockupTxOutput = optionalTxOutput.get();
|
||||
|
@ -21,10 +21,14 @@ import bisq.core.locale.Res;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
// Data here must not be changed as it would break backward compatibility! In case we need to change we need to add a new
|
||||
// entry and maintain the old one. Once all the role holders of an old deprecated role have revoked the role might get removed.
|
||||
|
||||
// Add entry to translation file "dao.bond.bondedRoleType...."
|
||||
/**
|
||||
* Data here must not be changed as it would break backward compatibility! In case we need to change we need to add a
|
||||
* new entry and maintain the old one. Once all the role holders of an old deprecated role have revoked the
|
||||
* role might get removed.
|
||||
*
|
||||
* Add entry to translation file "dao.bond.bondedRoleType...."
|
||||
*/
|
||||
public enum BondedRoleType {
|
||||
// admins
|
||||
GITHUB_ADMIN(50_000, 60, "https://github.com/bisq-network/roles/issues/16", true),
|
||||
|
@ -1339,9 +1339,9 @@ dao.bonding.info=Lockup Tx ID: {0} / {1}
|
||||
dao.bonding.reputation.salt.info=Salt: {0}
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.GITHUB_ADMIN=Github admin
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Gesperrte Gelder
|
||||
dao.bonding.dashboard.unlockingAmount=Entsperre Gelder (Warten Sie bis die Sperrzeit vorbei ist):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Gekoppelte Rolle
|
||||
dao.bond.lockupReason.BONDED_ROLE=Gekoppelte Rolle
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Gekoppeltes Ansehen
|
||||
dao.bond.lockupReason.REPUTATION=Gekoppeltes Ansehen
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Vermittler
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Запереть средства:
|
||||
dao.bonding.dashboard.unlockingAmount=Разблокировка средств (дождитесь окончания времени блокировки):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Обеспеченная роль
|
||||
dao.bond.lockupReason.BONDED_ROLE=Обеспеченная роль
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Обеспеченная репутация
|
||||
dao.bond.lockupReason.REPUTATION=Обеспеченная репутация
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Арбитр
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds:
|
||||
dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over):
|
||||
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.BONDED_ROLE=Bonded role
|
||||
dao.bond.lockupReason.BONDED_ROLE=Bonded role
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.lockupType.REPUTATION=Bonded reputation
|
||||
dao.bond.lockupReason.REPUTATION=Bonded reputation
|
||||
# suppress inspection "UnusedProperty"
|
||||
dao.bond.bondedRoleType.ARBITRATOR=Arbitrator
|
||||
# suppress inspection "UnusedProperty"
|
||||
|
@ -26,10 +26,10 @@ import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.btc.setup.WalletsSetup;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupType;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupReason;
|
||||
import bisq.core.dao.governance.bond.reputation.MyReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.MyReputationListService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.state.model.blockchain.TxOutput;
|
||||
import bisq.core.dao.state.model.governance.BondedRoleType;
|
||||
import bisq.core.dao.state.model.governance.Role;
|
||||
@ -56,7 +56,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
public class BondingViewUtils {
|
||||
private final P2PService p2PService;
|
||||
private final MyReputationListService myReputationListService;
|
||||
private final BondedRolesService bondedRolesService;
|
||||
private final BondedRolesRepository bondedRolesRepository;
|
||||
private final WalletsSetup walletsSetup;
|
||||
private final DaoFacade daoFacade;
|
||||
private final Navigation navigation;
|
||||
@ -65,14 +65,14 @@ public class BondingViewUtils {
|
||||
@Inject
|
||||
public BondingViewUtils(P2PService p2PService,
|
||||
MyReputationListService myReputationListService,
|
||||
BondedRolesService bondedRolesService,
|
||||
BondedRolesRepository bondedRolesRepository,
|
||||
WalletsSetup walletsSetup,
|
||||
DaoFacade daoFacade,
|
||||
Navigation navigation,
|
||||
BsqFormatter bsqFormatter) {
|
||||
this.p2PService = p2PService;
|
||||
this.myReputationListService = myReputationListService;
|
||||
this.bondedRolesService = bondedRolesService;
|
||||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
this.walletsSetup = walletsSetup;
|
||||
this.daoFacade = daoFacade;
|
||||
this.navigation = navigation;
|
||||
@ -83,8 +83,8 @@ public class BondingViewUtils {
|
||||
BondedRoleType bondedRoleType = role.getBondedRoleType();
|
||||
Coin lockupAmount = Coin.valueOf(bondedRoleType.getRequiredBond());
|
||||
int lockupTime = bondedRoleType.getUnlockTimeInBlocks();
|
||||
if (!bondedRolesService.wasBondedAssetAlreadyBonded(role)) {
|
||||
lockupBond(role.getHash(), lockupAmount, lockupTime, LockupType.BONDED_ROLE, resultHandler);
|
||||
if (!bondedRolesRepository.isBondedAssetAlreadyInBond(role)) {
|
||||
lockupBond(role.getHash(), lockupAmount, lockupTime, LockupReason.BONDED_ROLE, resultHandler);
|
||||
} else {
|
||||
handleError(new RuntimeException("The role has been used already for a lockup tx."));
|
||||
}
|
||||
@ -92,11 +92,11 @@ public class BondingViewUtils {
|
||||
|
||||
public void lockupBondForReputation(Coin lockupAmount, int lockupTime, byte[] salt, Consumer<String> resultHandler) {
|
||||
MyReputation myReputation = new MyReputation(salt);
|
||||
lockupBond(myReputation.getHash(), lockupAmount, lockupTime, LockupType.REPUTATION, resultHandler);
|
||||
lockupBond(myReputation.getHash(), lockupAmount, lockupTime, LockupReason.REPUTATION, resultHandler);
|
||||
myReputationListService.addReputation(myReputation);
|
||||
}
|
||||
|
||||
private void lockupBond(byte[] hash, Coin lockupAmount, int lockupTime, LockupType lockupType,
|
||||
private void lockupBond(byte[] hash, Coin lockupAmount, int lockupTime, LockupReason lockupReason,
|
||||
Consumer<String> resultHandler) {
|
||||
if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) {
|
||||
if (!DevEnv.isDevMode()) {
|
||||
@ -106,21 +106,21 @@ public class BondingViewUtils {
|
||||
lockupTime
|
||||
))
|
||||
.actionButtonText(Res.get("shared.yes"))
|
||||
.onAction(() -> publishLockupTx(hash, lockupAmount, lockupTime, lockupType, resultHandler))
|
||||
.onAction(() -> publishLockupTx(hash, lockupAmount, lockupTime, lockupReason, resultHandler))
|
||||
.closeButtonText(Res.get("shared.cancel"))
|
||||
.show();
|
||||
} else {
|
||||
publishLockupTx(hash, lockupAmount, lockupTime, lockupType, resultHandler);
|
||||
publishLockupTx(hash, lockupAmount, lockupTime, lockupReason, resultHandler);
|
||||
}
|
||||
} else {
|
||||
GUIUtil.showNotReadyForTxBroadcastPopups(p2PService, walletsSetup);
|
||||
}
|
||||
}
|
||||
|
||||
private void publishLockupTx(byte[] hash, Coin lockupAmount, int lockupTime, LockupType lockupType, Consumer<String> resultHandler) {
|
||||
private void publishLockupTx(byte[] hash, Coin lockupAmount, int lockupTime, LockupReason lockupReason, Consumer<String> resultHandler) {
|
||||
daoFacade.publishLockupTx(lockupAmount,
|
||||
lockupTime,
|
||||
lockupType,
|
||||
lockupReason,
|
||||
hash,
|
||||
txId -> {
|
||||
if (!DevEnv.isDevMode())
|
||||
|
@ -22,7 +22,7 @@ import bisq.desktop.main.dao.bonding.BondingViewUtils;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.locale.Res;
|
||||
@ -48,7 +48,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
class BondListItem implements DaoStateListener {
|
||||
private final Bond bond;
|
||||
private final DaoFacade daoFacade;
|
||||
private final BondedRolesService bondedRolesService;
|
||||
private final BondedRolesRepository bondedRolesRepository;
|
||||
private final BondingViewUtils bondingViewUtils;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final String bondType;
|
||||
@ -64,12 +64,12 @@ class BondListItem implements DaoStateListener {
|
||||
|
||||
BondListItem(Bond bond,
|
||||
DaoFacade daoFacade,
|
||||
BondedRolesService bondedRolesService,
|
||||
BondedRolesRepository bondedRolesRepository,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
BsqFormatter bsqFormatter) {
|
||||
this.bond = bond;
|
||||
this.daoFacade = daoFacade;
|
||||
this.bondedRolesService = bondedRolesService;
|
||||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
this.bondingViewUtils = bondingViewUtils;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
|
||||
|
@ -28,7 +28,7 @@ import bisq.desktop.util.validation.BsqValidator;
|
||||
import bisq.core.btc.listeners.BsqBalanceListener;
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesService;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.locale.Res;
|
||||
@ -75,7 +75,7 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final BsqValidator bsqValidator;
|
||||
private final BondingViewUtils bondingViewUtils;
|
||||
private final BondedRolesService bondedRolesService;
|
||||
private final BondedRolesRepository bondedRolesRepository;
|
||||
private final DaoFacade daoFacade;
|
||||
private final Preferences preferences;
|
||||
|
||||
@ -97,14 +97,14 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
||||
BsqFormatter bsqFormatter,
|
||||
BsqValidator bsqValidator,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
BondedRolesService bondedRolesService,
|
||||
BondedRolesRepository bondedRolesRepository,
|
||||
DaoFacade daoFacade,
|
||||
Preferences preferences) {
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.bsqValidator = bsqValidator;
|
||||
this.bondingViewUtils = bondingViewUtils;
|
||||
this.bondedRolesService = bondedRolesService;
|
||||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
this.daoFacade = daoFacade;
|
||||
this.preferences = preferences;
|
||||
}
|
||||
@ -208,7 +208,7 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
||||
.map(bond -> {
|
||||
return new BondListItem(bond,
|
||||
daoFacade,
|
||||
bondedRolesService,
|
||||
bondedRolesRepository,
|
||||
bondingViewUtils,
|
||||
bsqFormatter);
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user