crystal-wallet-android/app/src/main/java/cy/agorise/crystalwallet/models/GeneralCoinAddress.java

372 lines
12 KiB
Java

package cy.agorise.crystalwallet.models;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.crypto.DeterministicKey;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import cy.agorise.graphenej.Util;
/**
* Represents an Address of a General Coin Account
*/
public class GeneralCoinAddress {
/**
* The id on the database
*/
private long mId = -1;
/**
* The account that this address belongs
*/
private final GeneralCoinAccount mAccount;
/**
* If this is change or external
*/
private final boolean mIsChange;
/**
* The index fo this address in the account
*/
private final int mIndex;
/**
* The ky used to calculate the address
*/
private ECKey mKey;
/**
* The list of the transactions that used this address as input
*/
private List<GTxIO> mTransactionInput = new ArrayList<>();
/**
* The list of the transactions that used this address as output
*/
private List<GTxIO> mTransactionOutput = new ArrayList<>();
/**
* Contrsutcotr used from the database
* @param id The id on the database
* @param account The account of this address
* @param isChange if it is change or external address
* @param index the index on the account of this address
* @param publicHexKey The public Address String
*/
public GeneralCoinAddress(long id, GeneralCoinAccount account, boolean isChange, int index, String publicHexKey) {
this.mId = id;
this.mAccount = account;
this.mIsChange = isChange;
this.mIndex = index;
this.mKey = ECKey.fromPublicOnly(Util.hexToBytes(publicHexKey));
}
/**
* Basic constructor
* @param account The account of this address
* @param isChange if it is change or external address
* @param index The index on the account of this address
* @param key The key to generate the private and the public key of this address
*/
public GeneralCoinAddress(GeneralCoinAccount account, boolean isChange, int index, DeterministicKey key) {
this.mId = -1;
this.mAccount = account;
this.mIsChange = isChange;
this.mIndex = index;
this.mKey = key;
}
/**
* Getter of the database id
*/
public long getId() {
return mId;
}
/**
* Setter of the database id
*/
public void setId(long id) {
this.mId = id;
}
/**
* Getter for he account
*/
public GeneralCoinAccount getAccount() {
return mAccount;
}
/**
* Indicates if this addres is change, if not is external
*/
public boolean isIsChange() {
return mIsChange;
}
/**
* Getter for the index on the account of this address
*/
public int getIndex() {
return mIndex;
}
/**
* Getter for the key of this address
*/
public ECKey getKey() {
return mKey;
}
/**
* Set the key for generate private key, this is used when this address is loaded from the database
* and want to be used to send transactions
* @param key The key that generates the private and the public key
*/
public void setKey(DeterministicKey key) {
this.mKey = key;
}
/**
* Get the address as a String
* @param param The network param of this address
*/
public String getAddressString(NetworkParameters param) {
return mKey.toAddress(param).toString();
}
/**
* Returns the bitcoinj Address representing this address
* @param param The network parameter of this address
*/
public Address getAddress(NetworkParameters param) {
return mKey.toAddress(param);
}
/**
* Gets the list of transaction that this address is input
*/
public List<GTxIO> getTransactionInput() {
return mTransactionInput;
}
/**
* Set the transactions that this address is input
*/
public void setTransactionInput(List<GTxIO> transactionInput) {
this.mTransactionInput = transactionInput;
}
/**
* Find if this address is input of a transaction
* @param inputToFind The GTxIO to find
* @param param The network parameter of this address
* @return if this address belongs to the transaction
*/
public boolean hasTransactionInput(GTxIO inputToFind, NetworkParameters param) {
for (GTxIO input : mTransactionInput) {
if ((input.getTransaction().getTxid().equals(inputToFind.getTransaction().getTxid()))
&& (input.getAddress().getAddressString(param).equals(inputToFind.getAddress()
.getAddressString(param)))) {
return true;
}
}
return false;
}
/**
* Gets the list of transaction that this address is output
*/
public List<GTxIO> getTransactionOutput() {
return mTransactionOutput;
}
/**
* Find if this address is output of a transaction
* @param outputToFind The GTxIO to find
* @param param the network parameter of this address
* @return if this address belongs to the transaction
*/
public boolean hasTransactionOutput(GTxIO outputToFind, NetworkParameters param) {
for (GTxIO output : mTransactionOutput) {
if ((output.getTransaction().getTxid().equals(outputToFind.getTransaction().getTxid()))
&& (output.getAddress().getAddressString(param).equals(outputToFind.getAddress()
.getAddressString(param)))) {
return true;
}
}
return false;
}
/**
* Sets the list of transaction that this address is output
*/
public void setTransactionOutput(List<GTxIO> outputTransaction) {
this.mTransactionOutput = outputTransaction;
}
/**
* Get the amount of uncofirmed balance
*/
public long getUnconfirmedBalance() {
long answer = 0;
for (GTxIO input : mTransactionInput) {
if (input.getTransaction().getConfirm() < mAccount.getCryptoNet().getConfirmationsNeeded()) {
answer += input.getAmount();
}
}
for (GTxIO output : mTransactionOutput) {
if (output.getTransaction().getConfirm() < mAccount.getCryptoNet().getConfirmationsNeeded()) {
answer -= output.getAmount();
}
}
return answer;
}
/**
* Get the amount of confirmed balance
*/
public long getConfirmedBalance() {
long answer = 0;
for (GTxIO input : mTransactionInput) {
if (input.getTransaction().getConfirm() >= mAccount.getCryptoNet().getConfirmationsNeeded()) {
answer += input.getAmount();
}
}
for (GTxIO output : mTransactionOutput) {
if (output.getTransaction().getConfirm() >= mAccount.getCryptoNet().getConfirmationsNeeded()) {
answer -= output.getAmount();
}
}
return answer;
}
/**
* Get the date of the last transaction or null if there is no transaction
*/
public Date getLastDate() {
Date lastDate = null;
for (GTxIO input : mTransactionInput) {
if (lastDate == null || lastDate.before(input.getTransaction().getDate())) {
lastDate = input.getTransaction().getDate();
}
}
for (GTxIO output : mTransactionOutput) {
if (lastDate == null || lastDate.before(output.getTransaction().getDate())) {
lastDate = output.getTransaction().getDate();
}
}
return lastDate;
}
/**
* Get the amount of the less cofnirmed transaction, this is used to set how confirmations are
* left
*/
public int getLessConfirmed(){
int lessConfirm = -1;
for (GTxIO input : mTransactionInput) {
if (lessConfirm == -1 || input.getTransaction().getConfirm() < lessConfirm) {
lessConfirm = input.getTransaction().getConfirm();
}
}
for (GTxIO output : mTransactionOutput) {
if (lessConfirm == -1 || output.getTransaction().getConfirm() < lessConfirm) {
lessConfirm = output.getTransaction().getConfirm();
}
}
return lessConfirm;
}
/**
* Gets the unspend transactions input
* @return The list with the unspend transasctions
*/
public List<GTxIO> getUTXos(){
List<GTxIO> utxo = new ArrayList<>();
for(GTxIO gitx : mTransactionInput){
boolean find = false;
for(GTxIO gotx : mTransactionOutput){
if(gitx.getTransaction().getTxid().equals(gotx.getOriginalTxid())){
find = true;
break;
}
}
if(!find){
utxo.add(gitx);
}
}
return utxo;
}
/**
* Fire the onBalanceChange event
*/
public void BalanceChange() {
this.getAccount().balanceChange();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GeneralCoinAddress that = (GeneralCoinAddress) o;
return mIsChange == that.mIsChange && mIndex == that.mIndex && mId == -1
&& (mAccount != null ? mAccount.equals(that.mAccount) : that.mAccount == null
&& (mKey != null ? mKey.equals(that.mKey) : that.mKey == null
&& (mTransactionInput != null ? mTransactionInput.equals(that.mTransactionInput)
: that.mTransactionInput == null && (mTransactionOutput != null
? mTransactionOutput.equals(that.mTransactionOutput)
: that.mTransactionOutput == null))));
}
@Override
public int hashCode() {
int result = (int) mId;
result = 31 * result + (mAccount != null ? mAccount.hashCode() : 0);
result = 31 * result + (mIsChange ? 1 : 0);
result = 31 * result + mIndex;
result = 31 * result + (mKey != null ? mKey.hashCode() : 0);
result = 31 * result + (mTransactionInput != null ? mTransactionInput.hashCode() : 0);
result = 31 * result + (mTransactionOutput != null ? mTransactionOutput.hashCode() : 0);
return result;
}
/**
* Update the transactions of this Address
* @param transaction The transaction to update
* @return true if this address has the transaction false otherwise
*/
public boolean updateTransaction(GeneralTransaction transaction){
for(GTxIO gitx : mTransactionInput){
if(gitx.getTransaction().equals(transaction)){
gitx.getTransaction().setConfirm(transaction.getConfirm());
gitx.getTransaction().setBlock(transaction.getBlock());
gitx.getTransaction().setBlockHeight(transaction.getBlockHeight());
gitx.getTransaction().setDate(transaction.getDate());
gitx.getTransaction().setMemo(transaction.getMemo());
return true;
}
}
for(GTxIO gotx : mTransactionOutput){
if(gotx.getTransaction().equals(transaction)){
gotx.getTransaction().setConfirm(transaction.getConfirm());
gotx.getTransaction().setBlock(transaction.getBlock());
gotx.getTransaction().setBlockHeight(transaction.getBlockHeight());
gotx.getTransaction().setDate(transaction.getDate());
gotx.getTransaction().setMemo(transaction.getMemo());
return true;
}
}
return false;
}
}