tangem-app-android-audited/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java
2018-12-16 19:51:54 +03:00

295 lines
No EOL
9.1 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.tangem.domain.wallet;
import android.net.Uri;
import android.text.InputFilter;
import com.tangem.tangemcard.reader.CardProtocol;
import com.tangem.tangemcard.tasks.SignTask;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
/**
* Created by Ilia on 15.02.2018.
*/
public abstract class CoinEngine {
public static class InternalAmount extends BigDecimal {
private String currency;
public InternalAmount() {
super(0);
currency="";
}
public InternalAmount(String amountString, String currency) {
super(amountString.replace(',','.'));
this.currency=currency;
}
public InternalAmount(long amount, String currency) {
super(amount);
this.currency=currency;
}
public InternalAmount(BigDecimal amount, String currency) {
super(amount.unscaledValue(), amount.scale());
this.currency=currency;
}
public InternalAmount(BigInteger amount, String currency) {
super(new BigDecimal(amount).unscaledValue(), new BigDecimal(amount).scale());
this.currency=currency;
}
public boolean notZero()
{
return compareTo(BigDecimal.ZERO)>0;
}
public boolean isZero() {
return compareTo(BigDecimal.ZERO)==0;
}
public String getCurrency() {
return currency;
}
public String toValueString(int decimals) {
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
symbols.setDecimalSeparator('.');
DecimalFormat df = new DecimalFormat();
df.setDecimalFormatSymbols(symbols);
df.setMaximumFractionDigits(decimals);
df.setMinimumFractionDigits(0);
df.setGroupingUsed(false);
BigDecimal bd=new BigDecimal(unscaledValue(), scale());
bd.setScale(decimals, ROUND_DOWN);
return df.format(bd);
}
public String toValueString() {
return toValueString(scale());
}
@Override
public String toString() {
return super.toString();
}
}
public static class Amount extends BigDecimal {
private String currency;
public Amount() {
super(0);
currency="";
}
public Amount(String amountString, String currency) {
super(amountString.replace(',','.'));
this.currency = currency;
}
public Amount(Long amount, String currency) {
super(amount);
this.currency = currency;
}
public Amount(BigDecimal amount, String currency) {
super(amount.unscaledValue(), amount.scale());
this.currency = currency;
}
public String getCurrency() {
return currency;
}
@Override
public String toString() {
return super.toString() + " " + currency;
}
public boolean notZero()
{
return compareTo(BigDecimal.ZERO)>0;
}
public String toDescriptionString(int decimals) {
return toValueString(decimals)+ " " + currency;
}
public String toValueString(int decimals) {
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
symbols.setDecimalSeparator('.');
DecimalFormat df = new DecimalFormat();
df.setDecimalFormatSymbols(symbols);
df.setMaximumFractionDigits(decimals);
df.setMinimumFractionDigits(0);
df.setGroupingUsed(false);
BigDecimal bd=new BigDecimal(unscaledValue(), scale());
bd.setScale(decimals, ROUND_DOWN);
return df.format(bd);
}
public String toValueString() {
return toValueString(scale());
}
public String toEquivalentString(double rateValue) {
if (rateValue > 0) {
BigDecimal biRate = new BigDecimal(rateValue);
BigDecimal exchangeCurs = biRate.multiply(this);
exchangeCurs = exchangeCurs.setScale(2, RoundingMode.DOWN);
return "USD " + exchangeCurs.toString();
} else {
return "";
}
}
public boolean isZero() {
return compareTo(BigDecimal.ZERO)==0;
}
}
protected TangemContext ctx;
public CoinEngine() {
}
public CoinEngine(TangemContext ctx) {
this.ctx = ctx;
}
public abstract boolean awaitingConfirmation();
public abstract boolean hasBalanceInfo();
public abstract boolean isBalanceNotZero();
// public abstract byte[] sign(Amount feeValue, Amount amountValue, boolean IncFee, String targetAddress, CardProtocol protocol) throws Exception;
// TODO - change isExtractPossible to isExtractPossible and if not - return string message
public abstract boolean isExtractPossible();
public abstract Uri getShareWalletUriExplorer();
public abstract Uri getShareWalletUri();
public abstract boolean checkNewTransactionAmount(Amount amount);
// TODO - move minFeeInInternalUnits to CoinData
public abstract boolean checkNewTransactionAmountAndFee(Amount amount, Amount fee, Boolean isFeeIncluded);
public abstract boolean validateBalance(BalanceValidator balanceValidator);
public abstract Amount getBalance();
public abstract String getBalanceHTML();
public abstract String getBalanceCurrency();
public abstract InputFilter[] getAmountInputFilters();
public abstract String getOfflineBalanceHTML();
public abstract String evaluateFeeEquivalent(String fee);
public abstract String getFeeCurrency();
public abstract boolean isNeedCheckNode();
public abstract String getBalanceEquivalent();
public abstract boolean validateAddress(String address);
public abstract String calculateAddress(byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException;
public abstract Amount convertToAmount(InternalAmount internalAmount) throws Exception;
public abstract Amount convertToAmount(String strAmount, String currency);
public abstract InternalAmount convertToInternalAmount(Amount amount) throws Exception;
public abstract InternalAmount convertToInternalAmount(byte[] bytes) throws Exception;
public abstract byte[] convertToByteArray(InternalAmount internalAmount) throws Exception;
public abstract CoinData createCoinData();
public abstract String getUnspentInputsDescription();
public void defineWallet() throws CardProtocol.TangemException {
try {
String wallet = calculateAddress(ctx.getCard().getWalletPublicKey());
ctx.getCoinData().setWallet(wallet);
}
catch (Exception e)
{
ctx.getCoinData().setWallet("ERROR");
throw new CardProtocol.TangemException("Can't define wallet address");
}
}
public abstract SignTask.PaymentToSign constructPayment(Amount amountValue, Amount feeValue, boolean IncFee, String targetAddress) throws Exception;
public interface OnNeedSendPayment
{
void onPaymentPrepared(byte[] txForSend);
}
protected OnNeedSendPayment onNeedSendPayment;
public void setOnNeedSendPayment(OnNeedSendPayment onNeedSendPayment) {
this.onNeedSendPayment = onNeedSendPayment;
}
protected void notifyOnNeedSendPayment(byte[] txForSend) throws Exception {
if(onNeedSendPayment==null)
throw new Exception("Payment signed but no callback defined to send!");
onNeedSendPayment.onPaymentPrepared(txForSend);
}
public interface BlockchainRequestsCallbacks
{
/**
* Notification that the all requests in sequence completed
* Call after a last request completed
* If occurred error return in ctx.error
* @param success -*
*/
void onComplete(Boolean success);
/**
* Notification that a new part of data received and it's possible to update view
* May call when some request in the sequence completed but there are still a few requests left
*/
void onProgress();
/**
* Return flag that allow to add new or re-requests in the sequence
* Call between requests or when request fail and before re-request
* @return true if not need terminate (e.g. activity is online)
*/
boolean allowAdvance();
}
public abstract void requestBalanceAndUnspentTransactions(BlockchainRequestsCallbacks blockchainRequestsCallbacks) throws Exception;
public abstract void requestFee(BlockchainRequestsCallbacks blockchainRequestsCallbacks, String targetAddress, Amount amount) throws Exception;
public abstract void requestSendTransaction(BlockchainRequestsCallbacks blockchainRequestsCallbacks, byte[] txForSend) throws Exception;
}