Change classes name to be more precised what they do

Change Insight Api Generator to use Manager and simplifier the code
Added check for the crypto coin of the cryptocoin request
Change CryptoNet to CryptoCoin, all the insight cryptos use only one coin.
Added Queries to search and insert Bitcoin Transaction
This commit is contained in:
hvarona 2018-10-04 23:59:32 -04:00
parent b55d22324a
commit 86c16bbb7b
8 changed files with 184 additions and 236 deletions

View file

@ -1,54 +1,50 @@
package cy.agorise.crystalwallet.apigenerator; package cy.agorise.crystalwallet.apigenerator;
import android.content.Context;
import java.util.HashMap; import java.util.HashMap;
import cy.agorise.crystalwallet.apigenerator.insightapi.AddressesActivityWatcher;
import cy.agorise.crystalwallet.apigenerator.insightapi.BroadcastTransaction; import cy.agorise.crystalwallet.apigenerator.insightapi.BroadcastTransaction;
import cy.agorise.crystalwallet.apigenerator.insightapi.GetEstimateFee; import cy.agorise.crystalwallet.apigenerator.insightapi.GetEstimateFee;
import cy.agorise.crystalwallet.apigenerator.insightapi.GetTransactionByAddress; import cy.agorise.crystalwallet.apigenerator.insightapi.GetTransactionByAddress;
import cy.agorise.crystalwallet.apigenerator.insightapi.GetTransactionData; import cy.agorise.crystalwallet.enums.CryptoCoin;
import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.crystalwallet.network.CryptoNetManager; import cy.agorise.crystalwallet.network.CryptoNetManager;
public class InsightApiGenerator { public class InsightApiGenerator {
private static HashMap<CryptoNet,GetTransactionByAddress> transactionGetters = new HashMap(); private static HashMap<CryptoCoin,GetTransactionByAddress> transactionGetters = new HashMap();
private static HashMap<CryptoNet,GetTransactionData> transacitonFollowers = new HashMap(); private static HashMap<CryptoCoin,AddressesActivityWatcher> transactionFollowers = new HashMap();
/** /**
* Fecth all the transaciton for a giving address * Fecth all the transaciton for a giving address
* @param cryptoNet the crypto net of the address * @param cryptoCoin the crypto net of the address
* @param address The address String * @param address The address String
* @param request the request api to response * @param request the request api to response
* @param subscribe If needs to follow the address (Real time) * @param subscribe If needs to follow the address (Real time)
*/ */
public static void getTransactionFromAddress(CryptoNet cryptoNet, String address, public static void getTransactionFromAddress(CryptoCoin cryptoCoin, String address,
ApiRequest request, boolean subscribe){ ApiRequest request, boolean subscribe){
if(!transactionGetters.containsKey(cryptoNet)){ if(!transactionGetters.containsKey(cryptoCoin)){
transactionGetters.put(cryptoNet,new GetTransactionByAddress(cryptoNet,CryptoNetManager.getURL(cryptoNet))); transactionGetters.put(cryptoCoin,new GetTransactionByAddress(cryptoCoin,CryptoNetManager.getURL(cryptoCoin.getCryptoNet())));
} }
transactionGetters.get(cryptoNet).addAddress(address); transactionGetters.get(cryptoCoin).addAddress(address);
//TODO process request transactionGetters.get(cryptoCoin).start();
if(subscribe){
if(!transactionFollowers.containsKey(cryptoCoin)){
transactionFollowers.put(cryptoCoin,new AddressesActivityWatcher(CryptoNetManager.getURL(cryptoCoin.getCryptoNet()),cryptoCoin));
}
transactionFollowers.get(cryptoCoin).addAddress(address);
transactionFollowers.get(cryptoCoin).connect();
} }
/**
* Funciton used for unconfirmed transactions
* @param cryptoNet
* @param txid
* @param context
*/
public static void followTransaction(CryptoNet cryptoNet, String txid, Context context){
} }
/** /**
* Broadcast an insight api transaction * Broadcast an insight api transaction
* @param cryptoNet The cryptoNet of the transaction * @param cryptoCoin The cryptoNet of the transaction
* @param rawtx the transaction to be broadcasted * @param rawtx the transaction to be broadcasted
*/ */
public static void broadcastTransaction(CryptoNet cryptoNet, String rawtx, final ApiRequest request){ public static void broadcastTransaction(CryptoCoin cryptoCoin, String rawtx, final ApiRequest request){
BroadcastTransaction bTransaction = new BroadcastTransaction(rawtx, CryptoNetManager.getURL(cryptoNet), "api", new BroadcastTransaction.BroadCastTransactionListener() { BroadcastTransaction bTransaction = new BroadcastTransaction(rawtx,
CryptoNetManager.getURL(cryptoCoin.getCryptoNet()), "api", new BroadcastTransaction.BroadCastTransactionListener() {
@Override @Override
public void onSuccess() { public void onSuccess() {
request.getListener().success(true,request.getId()); request.getListener().success(true,request.getId());
@ -64,13 +60,15 @@ public class InsightApiGenerator {
request.getListener().fail(request.getId()); request.getListener().fail(request.getId());
} }
}); });
bTransaction.start();
} }
/** /**
* Fetch the estimated fee for a transaction * Fetch the estimated fee for a transaction
*/ */
public static void getEstimateFee(CryptoNet cryptoNet, final ApiRequest request){ public static void getEstimateFee(CryptoCoin cryptoCoin, final ApiRequest request){
GetEstimateFee.getEstimateFee(CryptoNetManager.getURL(cryptoNet), new GetEstimateFee.estimateFeeListener() { GetEstimateFee.getEstimateFee(CryptoNetManager.getURL(cryptoCoin.getCryptoNet()),
new GetEstimateFee.estimateFeeListener() {
@Override @Override
public void estimateFee(long value) { public void estimateFee(long value) {
request.listener.success(value,request.getId()); request.listener.success(value,request.getId());

View file

@ -12,6 +12,7 @@ import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import cy.agorise.crystalwallet.enums.CryptoCoin;
import cy.agorise.crystalwallet.models.GeneralCoinAccount; import cy.agorise.crystalwallet.models.GeneralCoinAccount;
import io.socket.client.IO; import io.socket.client.IO;
import io.socket.client.Socket; import io.socket.client.Socket;
@ -24,12 +25,9 @@ import io.socket.emitter.Emitter;
* *
*/ */
public class AccountActivityWatcher { public class AddressesActivityWatcher {
/** private final CryptoCoin cryptoCoin;
* The mAccount to be monitor
*/
private final GeneralCoinAccount mAccount;
/** /**
* The list of address to monitor * The list of address to monitor
*/ */
@ -38,10 +36,6 @@ public class AccountActivityWatcher {
* the Socket.IO * the Socket.IO
*/ */
private Socket mSocket; private Socket mSocket;
/**
* This app mContext, used to save on the DB
*/
private final Context mContext;
private final String mServerUrl; private final String mServerUrl;
@ -55,9 +49,9 @@ public class AccountActivityWatcher {
try { try {
System.out.println("Receive accountActivtyWatcher " + os[0].toString() ); System.out.println("Receive accountActivtyWatcher " + os[0].toString() );
String txid = ((JSONObject) os[0]).getString(InsightApiConstants.sTxTag); String txid = ((JSONObject) os[0]).getString(InsightApiConstants.sTxTag);
new GetTransactionData(txid, mAccount, mServerUrl, mContext).start(); new GetTransactionData(txid, mServerUrl, cryptoCoin).start();
} catch (JSONException ex) { } catch (JSONException ex) {
Logger.getLogger(AccountActivityWatcher.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(AddressesActivityWatcher.class.getName()).log(Level.SEVERE, null, ex);
} }
} }
}; };
@ -84,7 +78,9 @@ public class AccountActivityWatcher {
private final Emitter.Listener onDisconnect = new Emitter.Listener() { private final Emitter.Listener onDisconnect = new Emitter.Listener() {
@Override @Override
public void call(Object... os) { public void call(Object... os) {
System.out.println("Disconnected to accountActivityWatcher"); try {
Thread.sleep(60000);
} catch (InterruptedException ignore) {}
mSocket.connect(); mSocket.connect();
} }
}; };
@ -99,19 +95,20 @@ public class AccountActivityWatcher {
for(Object ob : os) { for(Object ob : os) {
System.out.println("accountActivityWatcher " + ob.toString()); System.out.println("accountActivityWatcher " + ob.toString());
} }
try {
Thread.sleep(60000);
} catch (InterruptedException ignore) {}
mSocket.connect();
} }
}; };
/** /**
* Basic constructor * Basic constructor
* *
* @param mAccount The mAccount to be monitor
* @param mContext This app mContext
*/ */
public AccountActivityWatcher(String serverUrl, GeneralCoinAccount mAccount, Context mContext) { public AddressesActivityWatcher(String serverUrl, CryptoCoin cryptoCoin) {
this.mServerUrl = serverUrl; this.mServerUrl = serverUrl;
this.mAccount = mAccount; this.cryptoCoin = cryptoCoin;
this.mContext = mContext;
try { try {
this.mSocket = IO.socket(serverUrl); this.mSocket = IO.socket(serverUrl);
this.mSocket.on(Socket.EVENT_CONNECT, onConnect); this.mSocket.on(Socket.EVENT_CONNECT, onConnect);
@ -141,13 +138,11 @@ public class AccountActivityWatcher {
* Connects the Socket * Connects the Socket
*/ */
public void connect() { public void connect() {
//TODO change to use log
System.out.println("accountActivityWatcher connecting");
try{ try{
if(this.mSocket == null || !this.mSocket.connected()) {
this.mSocket.connect(); this.mSocket.connect();
}catch(Exception e){ }
//TODO change exception handler }catch(Exception ignore){
System.out.println("accountActivityWatcher exception " + e.getMessage());
} }
} }

View file

@ -16,6 +16,7 @@ import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vin;
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout; import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout;
import cy.agorise.crystalwallet.enums.CryptoCoin; import cy.agorise.crystalwallet.enums.CryptoCoin;
import cy.agorise.crystalwallet.enums.CryptoNet; import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.crystalwallet.manager.GeneralAccountManager;
import cy.agorise.crystalwallet.models.CryptoCurrency; import cy.agorise.crystalwallet.models.CryptoCurrency;
import cy.agorise.crystalwallet.models.GTxIO; import cy.agorise.crystalwallet.models.GTxIO;
import cy.agorise.crystalwallet.models.GeneralCoinAccount; import cy.agorise.crystalwallet.models.GeneralCoinAccount;
@ -41,14 +42,14 @@ public class GetTransactionByAddress extends Thread implements Callback<AddressT
private InsightApiServiceGenerator mServiceGenerator; private InsightApiServiceGenerator mServiceGenerator;
private String serverUrl; private String serverUrl;
private CryptoNet cryptoNet; private CryptoCoin cryptoNet;
private boolean inProcess = false; private boolean inProcess = false;
/** /**
* Basic consturcotr * Basic consturcotr
*/ */
public GetTransactionByAddress(CryptoNet cryptoNet, String serverUrl) { public GetTransactionByAddress(CryptoCoin cryptoNet, String serverUrl) {
this.cryptoNet = cryptoNet; this.cryptoNet = cryptoNet;
this.serverUrl = serverUrl; this.serverUrl = serverUrl;
this.mServiceGenerator = new InsightApiServiceGenerator(serverUrl); this.mServiceGenerator = new InsightApiServiceGenerator(serverUrl);
@ -76,7 +77,7 @@ public class GetTransactionByAddress extends Thread implements Callback<AddressT
AddressTxi addressTxi = response.body(); AddressTxi addressTxi = response.body();
for (Txi txi : addressTxi.items) { for (Txi txi : addressTxi.items) {
//TODO call manager GeneralAccountManager.getAccountManager(this.cryptoNet).processTxi(txi);
} }
} }

View file

@ -7,6 +7,8 @@ import java.util.Date;
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Txi; import cy.agorise.crystalwallet.apigenerator.insightapi.models.Txi;
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vin; import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vin;
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout; import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout;
import cy.agorise.crystalwallet.enums.CryptoCoin;
import cy.agorise.crystalwallet.manager.GeneralAccountManager;
import cy.agorise.crystalwallet.models.GTxIO; import cy.agorise.crystalwallet.models.GTxIO;
import cy.agorise.crystalwallet.models.GeneralCoinAccount; import cy.agorise.crystalwallet.models.GeneralCoinAccount;
import cy.agorise.crystalwallet.models.GeneralCoinAddress; import cy.agorise.crystalwallet.models.GeneralCoinAddress;
@ -20,10 +22,6 @@ import retrofit2.Response;
*/ */
public class GetTransactionData extends Thread implements Callback<Txi> { public class GetTransactionData extends Thread implements Callback<Txi> {
/**
* The account to be query
*/
private final GeneralCoinAccount mAccount;
/** /**
* The transaction txid to be query * The transaction txid to be query
*/ */
@ -32,10 +30,6 @@ public class GetTransactionData extends Thread implements Callback<Txi> {
* The serviceGenerator to call * The serviceGenerator to call
*/ */
private InsightApiServiceGenerator mServiceGenerator; private InsightApiServiceGenerator mServiceGenerator;
/**
* This app context, used to save on the DB
*/
private Context mContext;
private String mServerUrl; private String mServerUrl;
/** /**
@ -43,30 +37,28 @@ public class GetTransactionData extends Thread implements Callback<Txi> {
*/ */
private boolean mMustWait = false; private boolean mMustWait = false;
private CryptoCoin cryptoCoin;
/** /**
* Constructor used to query for a transaction with unknown confirmations * Constructor used to query for a transaction with unknown confirmations
* @param txid The txid of the transaciton to be query * @param txid The txid of the transaciton to be query
* @param account The account to be query
* @param context This app Context
*/ */
public GetTransactionData(String txid, GeneralCoinAccount account,String serverUrl, Context context) { public GetTransactionData(String txid, String serverUrl, CryptoCoin cryptoCoin) {
this(txid, account, serverUrl, context, false); this(txid, serverUrl, cryptoCoin, false);
} }
/** /**
* Consturctor to be used qhen the confirmations of the transaction are known * Consturctor to be used qhen the confirmations of the transaction are known
* @param txid The txid of the transaciton to be query * @param txid The txid of the transaciton to be query
* @param account The account to be query
* @param context This app Context
* @param mustWait If there is less confirmation that needed * @param mustWait If there is less confirmation that needed
*/ */
public GetTransactionData(String txid, GeneralCoinAccount account,String serverUrl, Context context, boolean mustWait) { public GetTransactionData(String txid, String serverUrl, CryptoCoin cryptoCoin, boolean mustWait) {
this.mServerUrl = serverUrl; this.mServerUrl = serverUrl;
this.mAccount = account;
this.mTxId= txid; this.mTxId= txid;
this.mServiceGenerator = new InsightApiServiceGenerator(serverUrl); this.mServiceGenerator = new InsightApiServiceGenerator(serverUrl);
this.mContext = context;
this.mMustWait = mustWait; this.mMustWait = mustWait;
this.cryptoCoin = cryptoCoin;
} }
/** /**
@ -91,97 +83,12 @@ public class GetTransactionData extends Thread implements Callback<Txi> {
@Override @Override
public void onResponse(Call<Txi> call, Response<Txi> response) { public void onResponse(Call<Txi> call, Response<Txi> response) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
Txi txi = response.body(); Txi txi = response.body();
GeneralAccountManager.getAccountManager(this.cryptoCoin).processTxi(txi);
GeneralTransaction transaction = new GeneralTransaction(); if (txi.confirmations < this.cryptoCoin.getCryptoNet().getConfirmationsNeeded()) {
transaction.setAccount(this.mAccount);
transaction.setTxid(txi.txid);
transaction.setBlock(txi.blockheight);
transaction.setDate(new Date(txi.time * 1000));
transaction.setFee((long) (txi.fee * Math.pow(10,this.mAccount.getCryptoCoin().getPrecision())));
transaction.setConfirm(txi.confirmations);
transaction.setType(this.mAccount.getCryptoCoin());
transaction.setBlockHeight(txi.blockheight);
for (Vin vin : txi.vin) {
GTxIO input = new GTxIO();
input.setAmount((long) (vin.value * Math.pow(10,this.mAccount.getCryptoCoin().getPrecision())));
input.setTransaction(transaction);
input.setOut(true);
input.setType(this.mAccount.getCryptoCoin());
String addr = vin.addr;
input.setAddressString(addr);
input.setIndex(vin.n);
input.setScriptHex(vin.scriptSig.hex);
input.setOriginalTxid(vin.txid);
for (GeneralCoinAddress address : this.mAccount.getAddresses()) {
if (address.getAddressString(this.mAccount.getNetworkParam()).equals(addr)) {
input.setAddress(address);
if (!address.hasTransactionOutput(input, this.mAccount.getNetworkParam())) {
address.getTransactionOutput().add(input);
}
}
}
transaction.getTxInputs().add(input);
}
for (Vout vout : txi.vout) {
if(vout.scriptPubKey.addresses == null || vout.scriptPubKey.addresses.length <= 0){
// The address is null, this must be a memo
String hex = vout.scriptPubKey.hex;
int opReturnIndex = hex.indexOf("6a");
if(opReturnIndex >= 0) {
byte[] memoBytes = new byte[Integer.parseInt(hex.substring(opReturnIndex+2,opReturnIndex+4),16)];
for(int i = 0; i < memoBytes.length;i++){
memoBytes[i] = Byte.parseByte(hex.substring(opReturnIndex+4+(i*2),opReturnIndex+6+(i*2)),16);
}
transaction.setMemo(new String(memoBytes));
System.out.println("Memo read : " + transaction.getMemo()); //TODO log this line
}
}else {
GTxIO output = new GTxIO();
output.setAmount((long) (vout.value * Math.pow(10, this.mAccount.getCryptoCoin().getPrecision())));
output.setTransaction(transaction);
output.setOut(false);
output.setType(this.mAccount.getCryptoCoin());
String addr = vout.scriptPubKey.addresses[0];
output.setAddressString(addr);
output.setIndex(vout.n);
output.setScriptHex(vout.scriptPubKey.hex);
for (GeneralCoinAddress address : this.mAccount.getAddresses()) {
if (address.getAddressString(this.mAccount.getNetworkParam()).equals(addr)) {
output.setAddress(address);
if (!address.hasTransactionInput(output, this.mAccount.getNetworkParam())) {
address.getTransactionInput().add(output);
}
}
}
transaction.getTxOutputs().add(output);
}
}
// This is for features like dash instantSend
if(txi.txlock && txi.confirmations< this.mAccount.getCryptoNet().getConfirmationsNeeded()){
transaction.setConfirm(this.mAccount.getCryptoNet().getConfirmationsNeeded());
}
//TODO database
/*SCWallDatabase db = new SCWallDatabase(this.mContext);
long idTransaction = db.getGeneralTransactionId(transaction);
if (idTransaction == -1) {
db.putGeneralTransaction(transaction);
} else {
transaction.setId(idTransaction);
db.updateGeneralTransaction(transaction);
}*/
this.mAccount.updateTransaction(transaction);
this.mAccount.balanceChange();
if (transaction.getConfirm() < this.mAccount.getCryptoNet().getConfirmationsNeeded()) {
//If transaction weren't confirmed, add the transaction to watch for change on the confirmations //If transaction weren't confirmed, add the transaction to watch for change on the confirmations
new GetTransactionData(this.mTxId, this.mAccount, this.mServerUrl, this.mContext, true).start(); new GetTransactionData(this.mTxId, this.mServerUrl, this.cryptoCoin, true).start();
} }
} }
} }

View file

@ -2,8 +2,11 @@ package cy.agorise.crystalwallet.dao;
import android.arch.lifecycle.LiveData; import android.arch.lifecycle.LiveData;
import android.arch.persistence.room.Dao; import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.OnConflictStrategy;
import android.arch.persistence.room.Query; import android.arch.persistence.room.Query;
import cy.agorise.crystalwallet.models.BitcoinTransaction;
import cy.agorise.crystalwallet.models.BitcoinTransactionExtended; import cy.agorise.crystalwallet.models.BitcoinTransactionExtended;
/** /**
@ -14,4 +17,10 @@ public interface BitcoinTransactionDao {
@Query("SELECT * FROM crypto_coin_transaction cct, bitcoin_transaction bt WHERE bt.crypto_coin_transaction_id = cct.id") @Query("SELECT * FROM crypto_coin_transaction cct, bitcoin_transaction bt WHERE bt.crypto_coin_transaction_id = cct.id")
LiveData<BitcoinTransactionExtended> getAll(); LiveData<BitcoinTransactionExtended> getAll();
@Query("SELECT * FROM bitcoin_transaction bt WHERE bt.tx_id = :txid")
BitcoinTransaction getByTxid(String txid);
@Insert(onConflict = OnConflictStrategy.REPLACE)
public long[] insertBitcoinTransaction(BitcoinTransaction... transactions);
} }

View file

@ -21,6 +21,7 @@ import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.apigenerator.grapheneoperation.AccountUpgradeOperationBuilder; import cy.agorise.crystalwallet.apigenerator.grapheneoperation.AccountUpgradeOperationBuilder;
import cy.agorise.crystalwallet.application.constant.BitsharesConstant; import cy.agorise.crystalwallet.application.constant.BitsharesConstant;
import cy.agorise.crystalwallet.dao.AccountSeedDao; import cy.agorise.crystalwallet.dao.AccountSeedDao;
import cy.agorise.crystalwallet.enums.CryptoCoin;
import cy.agorise.crystalwallet.models.BitsharesAccountNameCache; import cy.agorise.crystalwallet.models.BitsharesAccountNameCache;
import cy.agorise.crystalwallet.models.seed.BIP39; import cy.agorise.crystalwallet.models.seed.BIP39;
import cy.agorise.crystalwallet.requestmanagers.CryptoNetEquivalentRequest; import cy.agorise.crystalwallet.requestmanagers.CryptoNetEquivalentRequest;
@ -220,26 +221,28 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
*/ */
@Override @Override
public void onNewRequest(CryptoNetInfoRequest request) { public void onNewRequest(CryptoNetInfoRequest request) {
if (request instanceof ValidateImportBitsharesAccountRequest){ if(request.getCoin().equals(CryptoCoin.BITSHARES)) {
if (request instanceof ValidateImportBitsharesAccountRequest) {
this.validateImportAccount((ValidateImportBitsharesAccountRequest) request); this.validateImportAccount((ValidateImportBitsharesAccountRequest) request);
} else if (request instanceof ValidateExistBitsharesAccountRequest){ } else if (request instanceof ValidateExistBitsharesAccountRequest) {
this.validateExistAcccount((ValidateExistBitsharesAccountRequest) request); this.validateExistAcccount((ValidateExistBitsharesAccountRequest) request);
} else if (request instanceof ValidateBitsharesSendRequest){ } else if (request instanceof ValidateBitsharesSendRequest) {
this.validateSendRequest((ValidateBitsharesSendRequest) request); this.validateSendRequest((ValidateBitsharesSendRequest) request);
}else if (request instanceof CryptoNetEquivalentRequest){ } else if (request instanceof CryptoNetEquivalentRequest) {
this.getEquivalentValue((CryptoNetEquivalentRequest) request); this.getEquivalentValue((CryptoNetEquivalentRequest) request);
}else if (request instanceof ValidateCreateBitsharesAccountRequest){ } else if (request instanceof ValidateCreateBitsharesAccountRequest) {
this.validateCreateAccount((ValidateCreateBitsharesAccountRequest) request); this.validateCreateAccount((ValidateCreateBitsharesAccountRequest) request);
}else if (request instanceof ValidateBitsharesLTMUpgradeRequest){ } else if (request instanceof ValidateBitsharesLTMUpgradeRequest) {
this.validateLTMAccountUpgrade((ValidateBitsharesLTMUpgradeRequest) request); this.validateLTMAccountUpgrade((ValidateBitsharesLTMUpgradeRequest) request);
}else if (request instanceof GetBitsharesAccountNameCacheRequest){ } else if (request instanceof GetBitsharesAccountNameCacheRequest) {
this.getBitsharesAccountNameCacheRequest((GetBitsharesAccountNameCacheRequest) request); this.getBitsharesAccountNameCacheRequest((GetBitsharesAccountNameCacheRequest) request);
}else{ } else {
//TODO not implemented //TODO not implemented
System.out.println("Error request not implemented " + request.getClass().getName()); System.out.println("Error request not implemented " + request.getClass().getName());
} }
} }
}
/** /**
* Process the import account request * Process the import account request

View file

@ -12,7 +12,9 @@ import org.bitcoinj.crypto.HDKeyDerivation;
import org.bitcoinj.script.Script; import org.bitcoinj.script.Script;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import cy.agorise.crystalwallet.apigenerator.ApiRequest; import cy.agorise.crystalwallet.apigenerator.ApiRequest;
@ -23,7 +25,9 @@ import cy.agorise.crystalwallet.apigenerator.insightapi.GetTransactionData;
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Txi; import cy.agorise.crystalwallet.apigenerator.insightapi.models.Txi;
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vin; import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vin;
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout; import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout;
import cy.agorise.crystalwallet.dao.CrystalDatabase;
import cy.agorise.crystalwallet.enums.CryptoCoin; import cy.agorise.crystalwallet.enums.CryptoCoin;
import cy.agorise.crystalwallet.models.BitcoinTransaction;
import cy.agorise.crystalwallet.models.CryptoNetAccount; import cy.agorise.crystalwallet.models.CryptoNetAccount;
import cy.agorise.crystalwallet.models.GTxIO; import cy.agorise.crystalwallet.models.GTxIO;
import cy.agorise.crystalwallet.models.GeneralCoinAccount; import cy.agorise.crystalwallet.models.GeneralCoinAccount;
@ -36,7 +40,27 @@ import cy.agorise.graphenej.Util;
public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener { public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener {
CryptoCoin cryptoCoin; static HashMap<CryptoCoin, GeneralAccountManager> generalAccountManagers = new HashMap();
private static CryptoCoin[] SUPPORTED_COINS = new CryptoCoin[]{
CryptoCoin.BITCOIN,
CryptoCoin.BITCOIN_TEST,
CryptoCoin.DASH,
CryptoCoin.LITECOIN
} ;
final CryptoCoin cryptoCoin;
final Context context;
public static GeneralAccountManager getAccountManager(CryptoCoin coin){
return generalAccountManagers.get(coin);
}
public GeneralAccountManager(CryptoCoin cryptoCoin, Context context) {
this.cryptoCoin = cryptoCoin;
this.context = context;
generalAccountManagers.put(cryptoCoin,this);
}
@Override @Override
public void createAccountFromSeed(CryptoNetAccount account, ManagerRequest request, Context context) { public void createAccountFromSeed(CryptoNetAccount account, ManagerRequest request, Context context) {
@ -55,6 +79,14 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
@Override @Override
public void onNewRequest(CryptoNetInfoRequest request) { public void onNewRequest(CryptoNetInfoRequest request) {
if(Arrays.asList(SUPPORTED_COINS).contains(request.getCoin())){
if(request instanceof GeneralAccountSendRequest){
this.send((GeneralAccountSendRequest)request);
}else{
System.out.println("Invalid " +this.cryptoCoin.getLabel() + " request ");
}
}
} }
@ -63,21 +95,27 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
* @param txi * @param txi
*/ */
public void processTxi(Txi txi){ public void processTxi(Txi txi){
CrystalDatabase db = CrystalDatabase.getAppDatabase(this.context);
BitcoinTransaction btTransaction = db.bitcoinTransactionDao().getByTxid(txi.txid);
if(btTransaction != null){
btTransaction.setConfirmations(txi.confirmations);
db.bitcoinTransactionDao().insertBitcoinTransaction(btTransaction);
}else {
GeneralCoinAccount tempAccount = null;
GeneralTransaction transaction = new GeneralTransaction(); GeneralTransaction transaction = new GeneralTransaction();
//transaction.setAccount(this.mAccount); //transaction.setAccount(this.mAccount);
transaction.setTxid(txi.txid); transaction.setTxid(txi.txid);
transaction.setBlock(txi.blockheight); transaction.setBlock(txi.blockheight);
transaction.setDate(new Date(txi.time * 1000)); transaction.setDate(new Date(txi.time * 1000));
transaction.setFee((long) (txi.fee * Math.pow(10,cryptoCoin.getPrecision()))); transaction.setFee((long) (txi.fee * Math.pow(10, cryptoCoin.getPrecision())));
transaction.setConfirm(txi.confirmations); transaction.setConfirm(txi.confirmations);
transaction.setType(cryptoCoin); transaction.setType(cryptoCoin);
transaction.setBlockHeight(txi.blockheight); transaction.setBlockHeight(txi.blockheight);
for (Vin vin : txi.vin) { for (Vin vin : txi.vin) {
GTxIO input = new GTxIO(); GTxIO input = new GTxIO();
input.setAmount((long) (vin.value * Math.pow(10,cryptoCoin.getPrecision()))); input.setAmount((long) (vin.value * Math.pow(10, cryptoCoin.getPrecision())));
input.setTransaction(transaction); input.setTransaction(transaction);
input.setOut(true); input.setOut(true);
input.setType(cryptoCoin); input.setType(cryptoCoin);
@ -100,18 +138,18 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
} }
for (Vout vout : txi.vout) { for (Vout vout : txi.vout) {
if(vout.scriptPubKey.addresses == null || vout.scriptPubKey.addresses.length <= 0){ if (vout.scriptPubKey.addresses == null || vout.scriptPubKey.addresses.length <= 0) {
// The address is null, this must be a memo // The address is null, this must be a memo
String hex = vout.scriptPubKey.hex; String hex = vout.scriptPubKey.hex;
int opReturnIndex = hex.indexOf("6a"); int opReturnIndex = hex.indexOf("6a");
if(opReturnIndex >= 0) { if (opReturnIndex >= 0) {
byte[] memoBytes = new byte[Integer.parseInt(hex.substring(opReturnIndex+2,opReturnIndex+4),16)]; byte[] memoBytes = new byte[Integer.parseInt(hex.substring(opReturnIndex + 2, opReturnIndex + 4), 16)];
for(int i = 0; i < memoBytes.length;i++){ for (int i = 0; i < memoBytes.length; i++) {
memoBytes[i] = Byte.parseByte(hex.substring(opReturnIndex+4+(i*2),opReturnIndex+6+(i*2)),16); memoBytes[i] = Byte.parseByte(hex.substring(opReturnIndex + 4 + (i * 2), opReturnIndex + 6 + (i * 2)), 16);
} }
transaction.setMemo(new String(memoBytes)); transaction.setMemo(new String(memoBytes));
} }
}else { } else {
GTxIO output = new GTxIO(); GTxIO output = new GTxIO();
output.setAmount((long) (vout.value * Math.pow(10, cryptoCoin.getPrecision()))); output.setAmount((long) (vout.value * Math.pow(10, cryptoCoin.getPrecision())));
output.setTransaction(transaction); output.setTransaction(transaction);
@ -136,7 +174,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
transaction.getTxOutputs().add(output); transaction.getTxOutputs().add(output);
} }
} }
if(txi.txlock && txi.confirmations< cryptoCoin.getCryptoNet().getConfirmationsNeeded()){ if (txi.txlock && txi.confirmations < cryptoCoin.getCryptoNet().getConfirmationsNeeded()) {
transaction.setConfirm(cryptoCoin.getCryptoNet().getConfirmationsNeeded()); transaction.setConfirm(cryptoCoin.getCryptoNet().getConfirmationsNeeded());
} }
//TODO database //TODO database
@ -159,12 +197,13 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
} }
}*/ }*/
} }
}
public void send(final GeneralAccountSendRequest request){ public void send(final GeneralAccountSendRequest request){
//TODO check server connection //TODO check server connection
//TODO validate to address //TODO validate to address
InsightApiGenerator.getEstimateFee(request.getAccount().getCryptoNet(),new ApiRequest(1, new ApiRequestListener() { InsightApiGenerator.getEstimateFee(request.getAccount().getCryptoCoin(),new ApiRequest(1, new ApiRequestListener() {
@Override @Override
public void success(Object answer, int idPetition) { public void success(Object answer, int idPetition) {
Transaction tx = new Transaction(request.getAccount().getNetworkParam()); Transaction tx = new Transaction(request.getAccount().getNetworkParam());
@ -233,7 +272,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
tx.addSignedInput(outPoint, script, utxo.getAddress().getKey(), Transaction.SigHash.ALL, true); tx.addSignedInput(outPoint, script, utxo.getAddress().getKey(), Transaction.SigHash.ALL, true);
} }
InsightApiGenerator.broadcastTransaction(request.getAccount().getCryptoNet(),Util.bytesToHex(tx.bitcoinSerialize()),new ApiRequest(1, new ApiRequestListener() { InsightApiGenerator.broadcastTransaction(request.getAccount().getCryptoCoin(),Util.bytesToHex(tx.bitcoinSerialize()),new ApiRequest(1, new ApiRequestListener() {
@Override @Override
public void success(Object answer, int idPetition) { public void success(Object answer, int idPetition) {
request.setStatus(GeneralAccountSendRequest.StatusCode.SUCCEEDED); request.setStatus(GeneralAccountSendRequest.StatusCode.SUCCEEDED);

View file

@ -21,13 +21,6 @@ public abstract class CryptoNetInfoRequest {
*/ */
protected CryptoNetInfoRequestListener listener; protected CryptoNetInfoRequestListener listener;
protected CryptoNetInfoRequest(CryptoCoin coin){ protected CryptoNetInfoRequest(CryptoCoin coin){
this.coin = coin; this.coin = coin;
} }
@ -43,4 +36,7 @@ public abstract class CryptoNetInfoRequest {
CryptoNetInfoRequests.getInstance().removeRequest(this); CryptoNetInfoRequests.getInstance().removeRequest(this);
} }
public CryptoCoin getCoin() {
return coin;
}
} }