mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Move proposal payload in separate class
This commit is contained in:
parent
1126c50a7c
commit
563fa3cc28
@ -261,9 +261,7 @@ public class BtcWalletService extends WalletService {
|
|||||||
|
|
||||||
numInputs = resultTx.getInputs().size();
|
numInputs = resultTx.getInputs().size();
|
||||||
|
|
||||||
printTx("resultTx", resultTx);
|
|
||||||
txSize = resultTx.bitcoinSerialize().length + sigSizePerInput * numInputs;
|
txSize = resultTx.bitcoinSerialize().length + sigSizePerInput * numInputs;
|
||||||
log.error("txSize " + txSize);
|
|
||||||
// We need min. 1 output beside op_return
|
// We need min. 1 output beside op_return
|
||||||
// calculated fee must be inside of a tolerance range with tx fee
|
// calculated fee must be inside of a tolerance range with tx fee
|
||||||
final int tolerance = 1000;
|
final int tolerance = 1000;
|
||||||
|
@ -17,122 +17,33 @@
|
|||||||
|
|
||||||
package io.bitsquare.dao.proposals;
|
package io.bitsquare.dao.proposals;
|
||||||
|
|
||||||
import io.bitsquare.p2p.NodeAddress;
|
import io.bitsquare.app.Version;
|
||||||
import io.bitsquare.p2p.storage.payload.LazyProcessedStoragePayload;
|
import io.bitsquare.common.persistance.Persistable;
|
||||||
import io.bitsquare.p2p.storage.payload.PersistedStoragePayload;
|
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
public class Proposal implements Persistable {
|
||||||
import java.util.Arrays;
|
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||||
import java.util.Date;
|
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class Proposal implements LazyProcessedStoragePayload, PersistedStoragePayload {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(Proposal.class);
|
private static final Logger log = LoggerFactory.getLogger(Proposal.class);
|
||||||
|
|
||||||
|
private final ProposalPayload proposalPayload;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Enums
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public enum Phase {
|
|
||||||
NEW,
|
|
||||||
OPEN_FOR_VOTING,
|
|
||||||
OPEN_FOR_FUNDING,
|
|
||||||
CLOSED
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final long TTL = TimeUnit.DAYS.toMillis(30);
|
|
||||||
|
|
||||||
public final String uid;
|
|
||||||
public final String name;
|
|
||||||
public final String title;
|
|
||||||
public final String category;
|
|
||||||
public final String description;
|
|
||||||
public final String link;
|
|
||||||
public final Date startDate;
|
|
||||||
public final Date endDate;
|
|
||||||
public final Coin requestedBtc;
|
|
||||||
public final String btcAddress;
|
|
||||||
public final NodeAddress nodeAddress;
|
|
||||||
public final Date creationDate;
|
|
||||||
private PublicKey p2pStorageSignaturePubKey;
|
|
||||||
public final byte[] squPubKey;
|
|
||||||
|
|
||||||
// Signature of proposal data without signature, hash and feeTxId
|
|
||||||
public byte[] signature;
|
|
||||||
// Sha256Hash of proposal data including the signature but without feeTxId and hash
|
|
||||||
public byte[] hash;
|
|
||||||
|
|
||||||
// Set after we signed and set the hash. The hash is used in the OP_RETURN of the fee tx
|
|
||||||
public String feeTxId;
|
|
||||||
private boolean accepted;
|
private boolean accepted;
|
||||||
private Coin fundsReceived;
|
private Coin fundsReceived;
|
||||||
private int phaseAsOrdinal;
|
private boolean inVotePeriod;
|
||||||
|
private boolean inFundingPeriod;
|
||||||
|
private boolean closed;
|
||||||
|
private boolean waitingForVotingPeriod;
|
||||||
|
|
||||||
public Proposal(String uid,
|
public Proposal(ProposalPayload proposalPayload) {
|
||||||
String name,
|
this.proposalPayload = proposalPayload;
|
||||||
String title,
|
|
||||||
String category,
|
|
||||||
String description,
|
|
||||||
String link,
|
|
||||||
Date startDate,
|
|
||||||
Date endDate,
|
|
||||||
Coin requestedBtc,
|
|
||||||
String btcAddress,
|
|
||||||
NodeAddress nodeAddress,
|
|
||||||
PublicKey p2pStorageSignaturePubKey,
|
|
||||||
byte[] squPubKey) {
|
|
||||||
|
|
||||||
creationDate = new Date();
|
|
||||||
this.uid = uid;
|
|
||||||
this.name = name;
|
|
||||||
this.title = title;
|
|
||||||
this.category = category;
|
|
||||||
this.description = description;
|
|
||||||
this.link = link;
|
|
||||||
this.startDate = startDate;
|
|
||||||
this.endDate = endDate;
|
|
||||||
this.requestedBtc = requestedBtc;
|
|
||||||
this.btcAddress = btcAddress;
|
|
||||||
this.nodeAddress = nodeAddress;
|
|
||||||
this.p2pStorageSignaturePubKey = p2pStorageSignaturePubKey;
|
|
||||||
this.squPubKey = squPubKey;
|
|
||||||
setPhase(Phase.NEW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public ProposalPayload getProposalPayload() {
|
||||||
public long getTTL() {
|
return proposalPayload;
|
||||||
return TTL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PublicKey getOwnerPubKey() {
|
|
||||||
return p2pStorageSignaturePubKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setSignature(byte[] signature) {
|
|
||||||
this.signature = signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHash(byte[] hash) {
|
|
||||||
this.hash = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called after tx is published
|
|
||||||
public void setFeeTxId(String feeTxId) {
|
|
||||||
this.feeTxId = feeTxId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Phase getPhase() {
|
|
||||||
return Phase.values()[phaseAsOrdinal];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPhase(Phase phase) {
|
|
||||||
phaseAsOrdinal = phase.ordinal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAccepted() {
|
public boolean isAccepted() {
|
||||||
@ -151,77 +62,35 @@ public class Proposal implements LazyProcessedStoragePayload, PersistedStoragePa
|
|||||||
this.fundsReceived = fundsReceived;
|
this.fundsReceived = fundsReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String shortId() {
|
public boolean isInVotePeriod() {
|
||||||
return uid.substring(0, 8);
|
return inVotePeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setInVotePeriod(boolean inVotePeriod) {
|
||||||
public boolean equals(Object o) {
|
this.inVotePeriod = inVotePeriod;
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
Proposal proposal = (Proposal) o;
|
|
||||||
|
|
||||||
if (uid != null ? !uid.equals(proposal.uid) : proposal.uid != null) return false;
|
|
||||||
if (name != null ? !name.equals(proposal.name) : proposal.name != null) return false;
|
|
||||||
if (title != null ? !title.equals(proposal.title) : proposal.title != null) return false;
|
|
||||||
if (category != null ? !category.equals(proposal.category) : proposal.category != null) return false;
|
|
||||||
if (description != null ? !description.equals(proposal.description) : proposal.description != null)
|
|
||||||
return false;
|
|
||||||
if (link != null ? !link.equals(proposal.link) : proposal.link != null) return false;
|
|
||||||
if (startDate != null ? !startDate.equals(proposal.startDate) : proposal.startDate != null) return false;
|
|
||||||
if (endDate != null ? !endDate.equals(proposal.endDate) : proposal.endDate != null) return false;
|
|
||||||
if (requestedBtc != null ? !requestedBtc.equals(proposal.requestedBtc) : proposal.requestedBtc != null)
|
|
||||||
return false;
|
|
||||||
if (btcAddress != null ? !btcAddress.equals(proposal.btcAddress) : proposal.btcAddress != null) return false;
|
|
||||||
if (nodeAddress != null ? !nodeAddress.equals(proposal.nodeAddress) : proposal.nodeAddress != null)
|
|
||||||
return false;
|
|
||||||
if (creationDate != null ? !creationDate.equals(proposal.creationDate) : proposal.creationDate != null)
|
|
||||||
return false;
|
|
||||||
if (p2pStorageSignaturePubKey != null ? !p2pStorageSignaturePubKey.equals(proposal.p2pStorageSignaturePubKey) : proposal.p2pStorageSignaturePubKey != null)
|
|
||||||
return false;
|
|
||||||
return Arrays.equals(squPubKey, proposal.squPubKey);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public boolean isInFundingPeriod() {
|
||||||
public int hashCode() {
|
return inFundingPeriod;
|
||||||
int result = uid != null ? uid.hashCode() : 0;
|
|
||||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
|
||||||
result = 31 * result + (title != null ? title.hashCode() : 0);
|
|
||||||
result = 31 * result + (category != null ? category.hashCode() : 0);
|
|
||||||
result = 31 * result + (description != null ? description.hashCode() : 0);
|
|
||||||
result = 31 * result + (link != null ? link.hashCode() : 0);
|
|
||||||
result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
|
|
||||||
result = 31 * result + (endDate != null ? endDate.hashCode() : 0);
|
|
||||||
result = 31 * result + (requestedBtc != null ? requestedBtc.hashCode() : 0);
|
|
||||||
result = 31 * result + (btcAddress != null ? btcAddress.hashCode() : 0);
|
|
||||||
result = 31 * result + (nodeAddress != null ? nodeAddress.hashCode() : 0);
|
|
||||||
result = 31 * result + (creationDate != null ? creationDate.hashCode() : 0);
|
|
||||||
result = 31 * result + (p2pStorageSignaturePubKey != null ? p2pStorageSignaturePubKey.hashCode() : 0);
|
|
||||||
result = 31 * result + (squPubKey != null ? Arrays.hashCode(squPubKey) : 0);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setInFundingPeriod(boolean inFundingPeriod) {
|
||||||
public String toString() {
|
this.inFundingPeriod = inFundingPeriod;
|
||||||
return "Proposal{" +
|
|
||||||
"uid='" + uid + '\'' +
|
|
||||||
", text='" + name + '\'' +
|
|
||||||
", title='" + title + '\'' +
|
|
||||||
", category='" + category + '\'' +
|
|
||||||
", description='" + description + '\'' +
|
|
||||||
", link='" + link + '\'' +
|
|
||||||
", startDate=" + startDate +
|
|
||||||
", endDate=" + endDate +
|
|
||||||
", requestedBtc=" + requestedBtc +
|
|
||||||
", btcAddress='" + btcAddress + '\'' +
|
|
||||||
", nodeAddress=" + nodeAddress +
|
|
||||||
", pubKey=" + Arrays.toString(squPubKey) +
|
|
||||||
", signature=" + signature +
|
|
||||||
", hash=" + hash +
|
|
||||||
", feeTxId=" + feeTxId +
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClosed() {
|
||||||
|
return closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClosed(boolean closed) {
|
||||||
|
this.closed = closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWaitingForVotingPeriod() {
|
||||||
|
return waitingForVotingPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWaitingForVotingPeriod(boolean waitingForVotingPeriod) {
|
||||||
|
this.waitingForVotingPeriod = waitingForVotingPeriod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,8 +69,8 @@ public class ProposalManager {
|
|||||||
@Override
|
@Override
|
||||||
public void onAdded(ProtectedStorageEntry data) {
|
public void onAdded(ProtectedStorageEntry data) {
|
||||||
final StoragePayload storagePayload = data.getStoragePayload();
|
final StoragePayload storagePayload = data.getStoragePayload();
|
||||||
if (storagePayload instanceof Proposal)
|
if (storagePayload instanceof ProposalPayload)
|
||||||
addToList((Proposal) storagePayload, true);
|
addToList((ProposalPayload) storagePayload, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -82,18 +82,18 @@ public class ProposalManager {
|
|||||||
// At startup the P2PDataStorage inits earlier, otherwise we ge the listener called.
|
// At startup the P2PDataStorage inits earlier, otherwise we ge the listener called.
|
||||||
p2PService.getP2PDataStorage().getMap().values().forEach(e -> {
|
p2PService.getP2PDataStorage().getMap().values().forEach(e -> {
|
||||||
final StoragePayload storagePayload = e.getStoragePayload();
|
final StoragePayload storagePayload = e.getStoragePayload();
|
||||||
if (storagePayload instanceof Proposal)
|
if (storagePayload instanceof ProposalPayload)
|
||||||
addToList((Proposal) storagePayload, false);
|
addToList((ProposalPayload) storagePayload, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addToP2PNetwork(Proposal proposal) {
|
public void addToP2PNetwork(ProposalPayload proposalPayload) {
|
||||||
p2PService.addData(proposal, true);
|
p2PService.addData(proposalPayload, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addToList(Proposal proposal, boolean storeLocally) {
|
public void addToList(ProposalPayload proposalPayload, boolean storeLocally) {
|
||||||
if (!observableProposalsList.contains(proposal)) {
|
if (!observableProposalsList.stream().filter(e -> e.getProposalPayload().equals(proposalPayload)).findAny().isPresent()) {
|
||||||
observableProposalsList.add(proposal);
|
observableProposalsList.add(new Proposal(proposalPayload));
|
||||||
if (storeLocally)
|
if (storeLocally)
|
||||||
proposalsStorage.queueUpForSave(new ArrayList<>(observableProposalsList), 500);
|
proposalsStorage.queueUpForSave(new ArrayList<>(observableProposalsList), 500);
|
||||||
} else {
|
} else {
|
||||||
@ -106,6 +106,6 @@ public class ProposalManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void fundProposal(Proposal proposal, Coin amount, FutureCallback<Transaction> callback) {
|
public void fundProposal(Proposal proposal, Coin amount, FutureCallback<Transaction> callback) {
|
||||||
btcWalletService.fundProposal(amount, proposal.btcAddress, squWalletService.getSquAddressForProposalFunding(), callback);
|
btcWalletService.fundProposal(amount, proposal.getProposalPayload().btcAddress, squWalletService.getSquAddressForProposalFunding(), callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Bitsquare.
|
||||||
|
*
|
||||||
|
* Bitsquare 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.
|
||||||
|
*
|
||||||
|
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.bitsquare.dao.proposals;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Version;
|
||||||
|
import io.bitsquare.p2p.NodeAddress;
|
||||||
|
import io.bitsquare.p2p.storage.payload.LazyProcessedStoragePayload;
|
||||||
|
import io.bitsquare.p2p.storage.payload.PersistedStoragePayload;
|
||||||
|
import org.bitcoinj.core.Coin;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ProposalPayload implements LazyProcessedStoragePayload, PersistedStoragePayload {
|
||||||
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
|
private static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ProposalPayload.class);
|
||||||
|
|
||||||
|
public static final long TTL = TimeUnit.DAYS.toMillis(30);
|
||||||
|
|
||||||
|
public final String uid;
|
||||||
|
public final String name;
|
||||||
|
public final String title;
|
||||||
|
public final String category;
|
||||||
|
public final String description;
|
||||||
|
public final String link;
|
||||||
|
public final Date startDate;
|
||||||
|
public final Date endDate;
|
||||||
|
public final Coin requestedBtc;
|
||||||
|
public final String btcAddress;
|
||||||
|
public final NodeAddress nodeAddress;
|
||||||
|
public final Date creationDate;
|
||||||
|
//TODO store as byte array
|
||||||
|
public final PublicKey p2pStorageSignaturePubKey;
|
||||||
|
public final byte[] squPubKey;
|
||||||
|
|
||||||
|
// Signature of proposal data without signature, hash and feeTxId
|
||||||
|
public byte[] signature;
|
||||||
|
// Sha256Hash of proposal data including the signature but without feeTxId and hash
|
||||||
|
public byte[] hash;
|
||||||
|
|
||||||
|
// Set after we signed and set the hash. The hash is used in the OP_RETURN of the fee tx
|
||||||
|
public String feeTxId;
|
||||||
|
|
||||||
|
public ProposalPayload(String uid,
|
||||||
|
String name,
|
||||||
|
String title,
|
||||||
|
String category,
|
||||||
|
String description,
|
||||||
|
String link,
|
||||||
|
Date startDate,
|
||||||
|
Date endDate,
|
||||||
|
Coin requestedBtc,
|
||||||
|
String btcAddress,
|
||||||
|
NodeAddress nodeAddress,
|
||||||
|
PublicKey p2pStorageSignaturePubKey,
|
||||||
|
byte[] squPubKey) {
|
||||||
|
|
||||||
|
creationDate = new Date();
|
||||||
|
this.uid = uid;
|
||||||
|
this.name = name;
|
||||||
|
this.title = title;
|
||||||
|
this.category = category;
|
||||||
|
this.description = description;
|
||||||
|
this.link = link;
|
||||||
|
this.startDate = startDate;
|
||||||
|
this.endDate = endDate;
|
||||||
|
this.requestedBtc = requestedBtc;
|
||||||
|
this.btcAddress = btcAddress;
|
||||||
|
this.nodeAddress = nodeAddress;
|
||||||
|
this.p2pStorageSignaturePubKey = p2pStorageSignaturePubKey;
|
||||||
|
this.squPubKey = squPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTTL() {
|
||||||
|
return TTL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PublicKey getOwnerPubKey() {
|
||||||
|
return p2pStorageSignaturePubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setSignature(byte[] signature) {
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHash(byte[] hash) {
|
||||||
|
this.hash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called after tx is published
|
||||||
|
public void setFeeTxId(String feeTxId) {
|
||||||
|
this.feeTxId = feeTxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getShortId() {
|
||||||
|
return uid.substring(0, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
ProposalPayload proposal = (ProposalPayload) o;
|
||||||
|
|
||||||
|
if (uid != null ? !uid.equals(proposal.uid) : proposal.uid != null) return false;
|
||||||
|
if (name != null ? !name.equals(proposal.name) : proposal.name != null) return false;
|
||||||
|
if (title != null ? !title.equals(proposal.title) : proposal.title != null) return false;
|
||||||
|
if (category != null ? !category.equals(proposal.category) : proposal.category != null) return false;
|
||||||
|
if (description != null ? !description.equals(proposal.description) : proposal.description != null)
|
||||||
|
return false;
|
||||||
|
if (link != null ? !link.equals(proposal.link) : proposal.link != null) return false;
|
||||||
|
if (startDate != null ? !startDate.equals(proposal.startDate) : proposal.startDate != null) return false;
|
||||||
|
if (endDate != null ? !endDate.equals(proposal.endDate) : proposal.endDate != null) return false;
|
||||||
|
if (requestedBtc != null ? !requestedBtc.equals(proposal.requestedBtc) : proposal.requestedBtc != null)
|
||||||
|
return false;
|
||||||
|
if (btcAddress != null ? !btcAddress.equals(proposal.btcAddress) : proposal.btcAddress != null) return false;
|
||||||
|
if (nodeAddress != null ? !nodeAddress.equals(proposal.nodeAddress) : proposal.nodeAddress != null)
|
||||||
|
return false;
|
||||||
|
if (creationDate != null ? !creationDate.equals(proposal.creationDate) : proposal.creationDate != null)
|
||||||
|
return false;
|
||||||
|
if (p2pStorageSignaturePubKey != null ? !p2pStorageSignaturePubKey.equals(proposal.p2pStorageSignaturePubKey) : proposal.p2pStorageSignaturePubKey != null)
|
||||||
|
return false;
|
||||||
|
return Arrays.equals(squPubKey, proposal.squPubKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = uid != null ? uid.hashCode() : 0;
|
||||||
|
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||||
|
result = 31 * result + (title != null ? title.hashCode() : 0);
|
||||||
|
result = 31 * result + (category != null ? category.hashCode() : 0);
|
||||||
|
result = 31 * result + (description != null ? description.hashCode() : 0);
|
||||||
|
result = 31 * result + (link != null ? link.hashCode() : 0);
|
||||||
|
result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
|
||||||
|
result = 31 * result + (endDate != null ? endDate.hashCode() : 0);
|
||||||
|
result = 31 * result + (requestedBtc != null ? requestedBtc.hashCode() : 0);
|
||||||
|
result = 31 * result + (btcAddress != null ? btcAddress.hashCode() : 0);
|
||||||
|
result = 31 * result + (nodeAddress != null ? nodeAddress.hashCode() : 0);
|
||||||
|
result = 31 * result + (creationDate != null ? creationDate.hashCode() : 0);
|
||||||
|
result = 31 * result + (p2pStorageSignaturePubKey != null ? p2pStorageSignaturePubKey.hashCode() : 0);
|
||||||
|
result = 31 * result + (squPubKey != null ? Arrays.hashCode(squPubKey) : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Proposal{" +
|
||||||
|
"uid='" + uid + '\'' +
|
||||||
|
", text='" + name + '\'' +
|
||||||
|
", title='" + title + '\'' +
|
||||||
|
", category='" + category + '\'' +
|
||||||
|
", description='" + description + '\'' +
|
||||||
|
", link='" + link + '\'' +
|
||||||
|
", startDate=" + startDate +
|
||||||
|
", endDate=" + endDate +
|
||||||
|
", requestedBtc=" + requestedBtc +
|
||||||
|
", btcAddress='" + btcAddress + '\'' +
|
||||||
|
", nodeAddress=" + nodeAddress +
|
||||||
|
", pubKey=" + Arrays.toString(squPubKey) +
|
||||||
|
", signature=" + signature +
|
||||||
|
", hash=" + hash +
|
||||||
|
", feeTxId=" + feeTxId +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,17 +17,17 @@
|
|||||||
|
|
||||||
package io.bitsquare.gui.main.dao.proposals;
|
package io.bitsquare.gui.main.dao.proposals;
|
||||||
|
|
||||||
import io.bitsquare.dao.proposals.Proposal;
|
import io.bitsquare.dao.proposals.ProposalPayload;
|
||||||
import io.bitsquare.gui.components.InputTextField;
|
import io.bitsquare.gui.components.InputTextField;
|
||||||
import io.bitsquare.gui.util.Layout;
|
import io.bitsquare.gui.util.Layout;
|
||||||
import javafx.scene.control.TextField;
|
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
import static io.bitsquare.gui.util.FormBuilder.addLabelInputTextField;
|
||||||
|
import static io.bitsquare.gui.util.FormBuilder.addTitledGroupBg;
|
||||||
|
|
||||||
public class ProposalDisplay {
|
public class ProposalDisplay {
|
||||||
private static final Logger log = LoggerFactory.getLogger(ProposalDisplay.class);
|
private static final Logger log = LoggerFactory.getLogger(ProposalDisplay.class);
|
||||||
@ -35,7 +35,6 @@ public class ProposalDisplay {
|
|||||||
private GridPane gridPane;
|
private GridPane gridPane;
|
||||||
public InputTextField nameTextField, titleTextField, categoryTextField, descriptionTextField, linkTextField,
|
public InputTextField nameTextField, titleTextField, categoryTextField, descriptionTextField, linkTextField,
|
||||||
startDateTextField, endDateTextField, requestedBTCTextField, btcAddressTextField;
|
startDateTextField, endDateTextField, requestedBTCTextField, btcAddressTextField;
|
||||||
private TextField phaseTextField;
|
|
||||||
private int gridRow = 0;
|
private int gridRow = 0;
|
||||||
|
|
||||||
public ProposalDisplay(GridPane gridPane) {
|
public ProposalDisplay(GridPane gridPane) {
|
||||||
@ -53,10 +52,9 @@ public class ProposalDisplay {
|
|||||||
endDateTextField = addLabelInputTextField(gridPane, ++gridRow, "Delivery date:").second;
|
endDateTextField = addLabelInputTextField(gridPane, ++gridRow, "Delivery date:").second;
|
||||||
requestedBTCTextField = addLabelInputTextField(gridPane, ++gridRow, "Requested funds in BTC:").second;
|
requestedBTCTextField = addLabelInputTextField(gridPane, ++gridRow, "Requested funds in BTC:").second;
|
||||||
btcAddressTextField = addLabelInputTextField(gridPane, ++gridRow, "Bitcoin address:").second;
|
btcAddressTextField = addLabelInputTextField(gridPane, ++gridRow, "Bitcoin address:").second;
|
||||||
phaseTextField = addLabelTextField(gridPane, ++gridRow, "Phase:").second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fillWithProposalData(Proposal proposal) {
|
public void fillWithProposalData(ProposalPayload proposal) {
|
||||||
nameTextField.setText(proposal.name);
|
nameTextField.setText(proposal.name);
|
||||||
titleTextField.setText(proposal.title);
|
titleTextField.setText(proposal.title);
|
||||||
categoryTextField.setText(proposal.category);
|
categoryTextField.setText(proposal.category);
|
||||||
@ -66,7 +64,6 @@ public class ProposalDisplay {
|
|||||||
endDateTextField.setText(proposal.endDate.toString());
|
endDateTextField.setText(proposal.endDate.toString());
|
||||||
requestedBTCTextField.setText(proposal.requestedBtc.toPlainString());
|
requestedBTCTextField.setText(proposal.requestedBtc.toPlainString());
|
||||||
btcAddressTextField.setText(proposal.btcAddress.toString());
|
btcAddressTextField.setText(proposal.btcAddress.toString());
|
||||||
phaseTextField.setText(proposal.getPhase().name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearForm() {
|
public void clearForm() {
|
||||||
@ -79,7 +76,6 @@ public class ProposalDisplay {
|
|||||||
endDateTextField.setText("");
|
endDateTextField.setText("");
|
||||||
requestedBTCTextField.setText("");
|
requestedBTCTextField.setText("");
|
||||||
btcAddressTextField.setText("");
|
btcAddressTextField.setText("");
|
||||||
phaseTextField.setText("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fillWithMock() {
|
public void fillWithMock() {
|
||||||
|
@ -174,20 +174,22 @@ public class ActiveProposalsView extends ActivatableView<SplitPane, Void> {
|
|||||||
}
|
}
|
||||||
proposalDisplay.removeAllFields();
|
proposalDisplay.removeAllFields();
|
||||||
proposalDisplay.createAllFields();
|
proposalDisplay.createAllFields();
|
||||||
proposal.setPhase(Proposal.Phase.OPEN_FOR_FUNDING);
|
|
||||||
proposal.setAccepted(true);
|
|
||||||
if (proposal.getPhase() == Proposal.Phase.NEW) {
|
|
||||||
|
|
||||||
} else if (proposal.getPhase() == Proposal.Phase.OPEN_FOR_VOTING) {
|
//TODO
|
||||||
|
proposal.setInVotePeriod(true);
|
||||||
|
|
||||||
|
if (proposal.isWaitingForVotingPeriod()) {
|
||||||
|
addLabel(gridPane, proposalDisplay.incrementAndGetGridRow(), "This proposal is not open anymore for funding. Please wait until the next funding period starts.");
|
||||||
|
} else if (proposal.isInVotePeriod()) {
|
||||||
voteButton = addButtonAfterGroup(gridPane, proposalDisplay.incrementAndGetGridRow(), "Vote on proposal");
|
voteButton = addButtonAfterGroup(gridPane, proposalDisplay.incrementAndGetGridRow(), "Vote on proposal");
|
||||||
voteButton.setOnAction(event -> {
|
voteButton.setOnAction(event -> {
|
||||||
navigation.navigateTo(MainView.class, DaoView.class, VotingView.class, VotingDashboardView.class);
|
navigation.navigateTo(MainView.class, DaoView.class, VotingView.class, VotingDashboardView.class);
|
||||||
});
|
});
|
||||||
} else if (proposal.getPhase() == Proposal.Phase.OPEN_FOR_FUNDING) {
|
} else if (proposal.isInFundingPeriod()) {
|
||||||
checkArgument(proposal.isAccepted(), "A proposal with state OPEN_FOR_FUNDING must be accepted.");
|
checkArgument(proposal.isAccepted(), "A proposal with state OPEN_FOR_FUNDING must be accepted.");
|
||||||
fundButton = addButtonAfterGroup(gridPane, proposalDisplay.incrementAndGetGridRow(), "Fund proposal");
|
fundButton = addButtonAfterGroup(gridPane, proposalDisplay.incrementAndGetGridRow(), "Fund proposal");
|
||||||
fundButton.setOnAction(event -> {
|
fundButton.setOnAction(event -> {
|
||||||
fundProposalWindow.applyProposal(proposal).
|
fundProposalWindow.applyProposal(proposal.getProposalPayload()).
|
||||||
onAction(() -> {
|
onAction(() -> {
|
||||||
Coin amount = btcFormatter.parseToCoin(fundProposalWindow.getAmount().getText());
|
Coin amount = btcFormatter.parseToCoin(fundProposalWindow.getAmount().getText());
|
||||||
proposalManager.fundProposal(proposal, amount,
|
proposalManager.fundProposal(proposal, amount,
|
||||||
@ -205,12 +207,12 @@ public class ActiveProposalsView extends ActivatableView<SplitPane, Void> {
|
|||||||
});
|
});
|
||||||
}).show();
|
}).show();
|
||||||
});
|
});
|
||||||
} else if (proposal.getPhase() == Proposal.Phase.CLOSED) {
|
} else if (proposal.isClosed()) {
|
||||||
addLabel(gridPane, proposalDisplay.incrementAndGetGridRow(), "This proposal is not open anymore for funding. Please wait until the next funding period starts.");
|
addLabel(gridPane, proposalDisplay.incrementAndGetGridRow(), "This proposal is not open anymore for funding. Please wait until the next funding period starts.");
|
||||||
}
|
}
|
||||||
proposalDisplay.setAllFieldsEditable(false);
|
proposalDisplay.setAllFieldsEditable(false);
|
||||||
|
|
||||||
proposalDisplay.fillWithProposalData(proposal);
|
proposalDisplay.fillWithProposalData(proposal.getProposalPayload());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,14 +235,14 @@ public class ActiveProposalsView extends ActivatableView<SplitPane, Void> {
|
|||||||
public void updateItem(final Proposal item, boolean empty) {
|
public void updateItem(final Proposal item, boolean empty) {
|
||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
if (item != null)
|
if (item != null)
|
||||||
setText(formatter.formatDateTime(item.creationDate));
|
setText(formatter.formatDateTime(item.getProposalPayload().creationDate));
|
||||||
else
|
else
|
||||||
setText("");
|
setText("");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dateColumn.setComparator((o1, o2) -> o1.creationDate.compareTo(o2.creationDate));
|
dateColumn.setComparator((o1, o2) -> o1.getProposalPayload().creationDate.compareTo(o2.getProposalPayload().creationDate));
|
||||||
tableView.getColumns().add(dateColumn);
|
tableView.getColumns().add(dateColumn);
|
||||||
tableView.getSortOrder().add(dateColumn);
|
tableView.getSortOrder().add(dateColumn);
|
||||||
|
|
||||||
@ -258,14 +260,14 @@ public class ActiveProposalsView extends ActivatableView<SplitPane, Void> {
|
|||||||
public void updateItem(final Proposal item, boolean empty) {
|
public void updateItem(final Proposal item, boolean empty) {
|
||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
if (item != null)
|
if (item != null)
|
||||||
setText(item.name);
|
setText(item.getProposalPayload().name);
|
||||||
else
|
else
|
||||||
setText("");
|
setText("");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
nameColumn.setComparator((o1, o2) -> o1.name.compareTo(o2.name));
|
nameColumn.setComparator((o1, o2) -> o1.getProposalPayload().name.compareTo(o2.getProposalPayload().name));
|
||||||
tableView.getColumns().add(nameColumn);
|
tableView.getColumns().add(nameColumn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
package io.bitsquare.gui.main.dao.proposals.active;
|
package io.bitsquare.gui.main.dao.proposals.active;
|
||||||
|
|
||||||
import io.bitsquare.dao.proposals.Proposal;
|
import io.bitsquare.dao.proposals.ProposalPayload;
|
||||||
import io.bitsquare.gui.components.InputTextField;
|
import io.bitsquare.gui.components.InputTextField;
|
||||||
import io.bitsquare.gui.main.overlays.Overlay;
|
import io.bitsquare.gui.main.overlays.Overlay;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
@ -33,7 +33,7 @@ import static io.bitsquare.gui.util.FormBuilder.addLabelTextField;
|
|||||||
|
|
||||||
public class FundProposalWindow extends Overlay<FundProposalWindow> {
|
public class FundProposalWindow extends Overlay<FundProposalWindow> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(FundProposalWindow.class);
|
private static final Logger log = LoggerFactory.getLogger(FundProposalWindow.class);
|
||||||
private Proposal proposal;
|
private ProposalPayload proposal;
|
||||||
private InputTextField amount;
|
private InputTextField amount;
|
||||||
private TextField info;
|
private TextField info;
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ public class FundProposalWindow extends Overlay<FundProposalWindow> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FundProposalWindow applyProposal(Proposal proposal) {
|
public FundProposalWindow applyProposal(ProposalPayload proposal) {
|
||||||
this.proposal = proposal;
|
this.proposal = proposal;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ public class FundProposalWindow extends Overlay<FundProposalWindow> {
|
|||||||
info = addLabelTextField(gridPane, ++rowIndex, "Proposal ID:").second;
|
info = addLabelTextField(gridPane, ++rowIndex, "Proposal ID:").second;
|
||||||
amount = addLabelInputTextField(gridPane, ++rowIndex, "Amount in BTC:").second;
|
amount = addLabelInputTextField(gridPane, ++rowIndex, "Amount in BTC:").second;
|
||||||
|
|
||||||
info.setText(proposal.shortId());
|
info.setText(proposal.getShortId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,8 +27,8 @@ import io.bitsquare.btc.wallet.ChangeBelowDustException;
|
|||||||
import io.bitsquare.btc.wallet.SquWalletService;
|
import io.bitsquare.btc.wallet.SquWalletService;
|
||||||
import io.bitsquare.common.ByteArrayUtils;
|
import io.bitsquare.common.ByteArrayUtils;
|
||||||
import io.bitsquare.common.crypto.KeyRing;
|
import io.bitsquare.common.crypto.KeyRing;
|
||||||
import io.bitsquare.dao.proposals.Proposal;
|
|
||||||
import io.bitsquare.dao.proposals.ProposalManager;
|
import io.bitsquare.dao.proposals.ProposalManager;
|
||||||
|
import io.bitsquare.dao.proposals.ProposalPayload;
|
||||||
import io.bitsquare.gui.common.view.ActivatableView;
|
import io.bitsquare.gui.common.view.ActivatableView;
|
||||||
import io.bitsquare.gui.common.view.FxmlView;
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
import io.bitsquare.gui.main.dao.proposals.ProposalDisplay;
|
import io.bitsquare.gui.main.dao.proposals.ProposalDisplay;
|
||||||
@ -60,7 +60,7 @@ public class CreateProposalView extends ActivatableView<GridPane, Void> {
|
|||||||
|
|
||||||
private ProposalDisplay proposalDisplay;
|
private ProposalDisplay proposalDisplay;
|
||||||
private Button createButton;
|
private Button createButton;
|
||||||
|
|
||||||
private final NodeAddress nodeAddress;
|
private final NodeAddress nodeAddress;
|
||||||
private final PublicKey p2pStorageSignaturePubKey;
|
private final PublicKey p2pStorageSignaturePubKey;
|
||||||
private final SquWalletService squWalletService;
|
private final SquWalletService squWalletService;
|
||||||
@ -106,7 +106,7 @@ public class CreateProposalView extends ActivatableView<GridPane, Void> {
|
|||||||
Date startDate = new Date();
|
Date startDate = new Date();
|
||||||
Date endDate = new Date();
|
Date endDate = new Date();
|
||||||
|
|
||||||
Proposal proposal = new Proposal(UUID.randomUUID().toString(),
|
ProposalPayload proposalPayload = new ProposalPayload(UUID.randomUUID().toString(),
|
||||||
proposalDisplay.nameTextField.getText(),
|
proposalDisplay.nameTextField.getText(),
|
||||||
proposalDisplay.titleTextField.getText(),
|
proposalDisplay.titleTextField.getText(),
|
||||||
proposalDisplay.categoryTextField.getText(),
|
proposalDisplay.categoryTextField.getText(),
|
||||||
@ -120,10 +120,10 @@ public class CreateProposalView extends ActivatableView<GridPane, Void> {
|
|||||||
p2pStorageSignaturePubKey,
|
p2pStorageSignaturePubKey,
|
||||||
squKeyPair.getPubKey()
|
squKeyPair.getPubKey()
|
||||||
);
|
);
|
||||||
Sha256Hash hash = Sha256Hash.of(ByteArrayUtils.objectToByteArray(proposal));
|
Sha256Hash hash = Sha256Hash.of(ByteArrayUtils.objectToByteArray(proposalPayload));
|
||||||
proposal.setSignature(squKeyPair.sign(hash).encodeToDER());
|
proposalPayload.setSignature(squKeyPair.sign(hash).encodeToDER());
|
||||||
hash = Sha256Hash.of(ByteArrayUtils.objectToByteArray(proposal));
|
hash = Sha256Hash.of(ByteArrayUtils.objectToByteArray(proposalPayload));
|
||||||
proposal.setHash(hash.getBytes());
|
proposalPayload.setHash(hash.getBytes());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Coin createProposalFee = feeService.getCreateProposalFee();
|
Coin createProposalFee = feeService.getCreateProposalFee();
|
||||||
@ -133,10 +133,10 @@ public class CreateProposalView extends ActivatableView<GridPane, Void> {
|
|||||||
@Override
|
@Override
|
||||||
public void onSuccess(@Nullable Transaction transaction) {
|
public void onSuccess(@Nullable Transaction transaction) {
|
||||||
checkNotNull(transaction, "Transaction must not be null at signAndBroadcastProposalFeeTx callback.");
|
checkNotNull(transaction, "Transaction must not be null at signAndBroadcastProposalFeeTx callback.");
|
||||||
proposal.setFeeTxId(transaction.getHashAsString());
|
proposalPayload.setFeeTxId(transaction.getHashAsString());
|
||||||
publishToP2PNetwork(proposal);
|
publishToP2PNetwork(proposalPayload);
|
||||||
proposalDisplay.clearForm();
|
proposalDisplay.clearForm();
|
||||||
new Popup<>().confirmation("Your proposal has been successfully published.").show();
|
new Popup<>().confirmation("Your proposalPayload has been successfully published.").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -154,8 +154,8 @@ public class CreateProposalView extends ActivatableView<GridPane, Void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void publishToP2PNetwork(Proposal proposal) {
|
private void publishToP2PNetwork(ProposalPayload proposalPayload) {
|
||||||
proposalManager.addToP2PNetwork(proposal);
|
proposalManager.addToP2PNetwork(proposalPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user